生产环境的项目往往需要做负载均衡、跨域、反向代理、https(ssl) 证书相关的配置.
本篇将专门介绍 nginx 的配置

1.配置负载均衡代理 http 功能

生产环境建议 go 服务使用nginx作为前置服务代理,做好负载均衡,接口访问日志也有 nginx 记录,go 应用程序只负责记录业务日志即可。

  1. #注意,upstream 部分放置在 server 块之外,至少需要一个服务器ip。
  2. upstream goskeleton_list {
  3. # 设置负载均衡模式为ip算法模式,这样不同的客户端每次请求都会与第一次建立对话的后端服务器进行交互
  4. ip_hash;
  5. # 如果是域名访问的站点,nginx和go服务在同一台机器,
  6. # 这里不要配置为 127.0.0.1:端口 ,会影响获取客户端ip的准确性
  7. server 192.168.251.149:20202 ;
  8. server 192.168.251.149:20203 ;
  9. }
  10. server{
  11. #监听端口
  12. listen 80 ;
  13. # 站点域名,没有的话,写项目名称即可
  14. server_name www.ginskeleton.com ;
  15. root /home/wwwroot/goproject2020/goskeleton/public ;
  16. index index.htm index.html ;
  17. charset utf-8 ;
  18. # 使用 nginx 直接接管静态资源目录
  19. # 由于 ginskeleton 把路由(public)地址绑定到了同名称的目录 public ,所以我们就用 nginx 接管这个资源路由
  20. location ~ /public/(.*) {
  21. # 使用我们已经定义好的 root 目录,然后截取用户请求时,public 后面的所有地址,直接响应资源,不存在就返回404
  22. try_files /$1 =404;
  23. }
  24. location ~ / {
  25. # 静态资源、目录交给ngixn本身处理,动态路由请求执行后续的代理代码
  26. try_files $uri $uri/ @goskeleton;
  27. }
  28. location @goskeleton {
  29. # 配置nginx直接拦截 options 请求,避免这种没有意义的请求继续转发给后端go服务,
  30. if ($request_method = 'OPTIONS') {
  31. add_header 'Content-Type' 'text/plain, charset=utf-8' ;
  32. add_header 'Access-Control-Allow-Credentials' 'true' ;
  33. add_header 'Access-Control-Allow-Headers' 'Access-Control-Allow-Headers,Authorization,User-Agent, Keep-Alive, Content-Type, X-Requested-With,X-CSRF-Token,AccessToken,Token' ;
  34. add_header 'Access-Control-Allow-Methods' 'GET, POST, DELETE, PUT, PATCH, OPTIONS' ;
  35. add_header 'Access-Control-Allow-Origin' '*' ;
  36. add_header 'Access-Control-Expose-Headers' 'Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type' ;
  37. add_header 'Content-Length' '0' ;
  38. return 204 ;
  39. }
  40. #将客户端的ip和头域信息一并转发到后端服务器
  41. proxy_set_header Host $http_host;
  42. proxy_set_header X-Real-IP $remote_addr;
  43. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  44. # 转发Cookie,设置 SameSite
  45. proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";
  46. # 最后,执行代理访问真实服务器
  47. proxy_pass http://goskeleton_list ;
  48. }
  49. # 以下是静态资源缓存配置
  50. location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
  51. {
  52. expires 30d;
  53. }
  54. location ~ .*\.(js|css)?$
  55. {
  56. expires 12h;
  57. }
  58. location ~ /\.
  59. {
  60. deny all;
  61. }
  62. }

直接在 nginx配置跨域的好处:
1.nginx直接拦截、响应了 OPTIONS请求,避免继续转发给后端 go 服务,虽然对项目来说,性能的提升是微乎其微的,但是对于追求干净、简洁的开发者来说,去除了影响视觉得 OPTIONS.
2.具体效果如下:
options效果.png

2.配置 websocket

如果你的 websocket 服务是通过 nginx 代理访问的,那么需要在 nginx 的配置项需要进行如下设置

  1. upstream ws_list {
  2. ip_hash;
  3. server 192.168.251.149:20175 ;
  4. #server 192.168.251.149:20176 ;
  5. }
  6. server {
  7. listen 20175;
  8. server_name localhost;
  9. location / {
  10. proxy_http_version 1.1;
  11. proxy_set_header Upgrade websocket;
  12. proxy_set_header Connection Upgrade;
  13. proxy_read_timeout 60s ;
  14. proxy_set_header Host $http_host;
  15. proxy_set_header X-Real-IP $remote_addr;
  16. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  17. proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";
  18. proxy_pass http://ws_list ;
  19. }
  20. location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
  21. {
  22. expires 30d;
  23. }
  24. location ~ .*\.(js|css)?$
  25. {
  26. expires 12h;
  27. }
  28. location ~ /\.
  29. {
  30. deny all;
  31. }
  32. }

3.配置 https 功能

1.基于 http 内容稍作修改即可.
2.相关域名、云服务器都必须备案,否则无法通过域名访问,但是仍然可以通过 http://云服务器ip 访问,只不过通过ip访问会浏览器地址栏会提示不安全.

  1. #注意,upstream 部分放置在 server 块之外,至少需要一个服务器ip。
  2. upstream goskeleton_list {
  3. # 设置负载均衡模式为ip算法模式,这样不同的客户端每次请求都会与第一次建立对话的后端服务器进行交互
  4. ip_hash;
  5. server 127.0.0.1:20202 ;
  6. server 127.0.0.1:20203 ;
  7. }
  8. // 这里主要是将 http 访问重定向到 https,这样就能同时支持 http 和 https 访问
  9. server {
  10. listen 80;
  11. server_name www.ginskeleton.com;
  12. rewrite ^(.*)$ https://$host$1 permanent;
  13. }
  14. server{
  15. #监听端口
  16. listen 443 ssl ;
  17. # 站点域名,没有的话,写项目名称即可
  18. server_name www.ginskeleton.com ;
  19. root /home/wwwroot/goproject2020/goskeleton/public ;
  20. index index.html index.htm ;
  21. charset utf-8 ;
  22. # 配置 https 证书
  23. # ssl on; # 注意,在很早的低版本nginx上,此项是允许打开的,但是在高于 1.1x.x 版本要求必须关闭.
  24. # 证书的路径说明:如下写法表述证书路径位于nginx.conf 文件同目录,
  25. #例如我的路径:/usr/local/nginx/conf/nginx.conf
  26. # ginskeleton.crt 、ginskeleton.key 需要向云服务器厂商申请,后续有介绍
  27. ssl_certificate ginskeleton.crt; # 您也可以使用绝对路径指定证书
  28. ssl_certificate_key ginskeleton.key;
  29. ssl_session_timeout 5m;
  30. ssl_protocols TLSv1 TLSv1.1 TLSv1.2 SSLv2 SSLv3;
  31. ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
  32. ssl_prefer_server_ciphers on;
  33. # 使用 nginx 直接接管静态资源目录
  34. # 由于 ginskeleton 把路由(public)地址绑定到了同名称的目录 public ,所以我们就用 nginx 接管这个资源路由
  35. location ~ /public/(.*) {
  36. # 使用我们已经定义好的 root 目录,然后截取用户请求时,public 后面的所有地址,直接响应资源,不存在就返回404
  37. try_files /$1 =404;
  38. }
  39. location ~ / {
  40. # 静态资源、目录交给ngixn本身处理,动态路由请求执行后续的代理代码
  41. try_files $uri $uri/ @goskeleton;
  42. }
  43. // 这里的 @goskeleton 和 try_files 语法块的名称必须一致
  44. location @goskeleton {
  45. #将客户端的ip和头域信息一并转发到后端服务器
  46. proxy_set_header Host $http_host;
  47. proxy_set_header X-Real-IP $remote_addr;
  48. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  49. # 转发Cookie,设置 SameSite
  50. proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";
  51. # 最后,执行代理访问真实服务器
  52. proxy_pass http://goskeleton_list ;
  53. }
  54. # 以下是静态资源缓存配置
  55. location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
  56. {
  57. expires 30d;
  58. }
  59. location ~ .*\.(js|css)?$
  60. {
  61. expires 12h;
  62. }
  63. location ~ /\.
  64. {
  65. deny all;
  66. }
  67. }

4.关于 https 的简要介绍

1.首先能保证数据在传输过程中的安全性.
2.证书需要向第三方代理机构申请(华为云、阿里云、腾讯云等), 个人证书一般都会有免费一年的体验期.
3.证书申请时需要提交您的相关域名, 颁发机构会把您的域名信息和证书绑定, 最终配置在nginx, 当使用浏览器访问时, 浏览器地址栏会变成绿色安全图标.
4.本次使用的 ssl 证书是在腾讯云申请的1年免费期证书, 申请地址:https://console.cloud.tencent.com/ssl , 企业证书一年至少在 3000+ 元.
5.项目前置 nginx 服务器配置 ssl 证书通过https 协议在网络中传输数据, 当加密数据到达 nginx 时,瞬间会被 http_ssl_module 模块解密为明文,因此代理的负载均衡服务器不需要配置 ssl 选项.
6.腾讯云申请的证书合计共有4个文件,我们只需要使用其中2个即可。
证书.png