一、背景
好久没有更新了,趁着元旦假,更新一波吧!最近两年来一直独自在维护公司的nginx和gateway,从docker单机版到k8s集群版,积累了不少心得体会,也踩了不少的坑,由于单篇的篇幅有限,做成一个专集记录一下吧,以免日后忘记了。
发展记录:
- 单个前端项目+单个后端项目(一台阿里云ECS服务器)
- 前端技术栈:angular8
- 后端技术栈:jdk8+springboot
- 部署方式:docker+shell脚本
- nginx: 动静分离+单个域名
- 两个前端项目+多个后端项目(一台阿里云ECS服务器)
- 前端技术栈:angular8和react
- 后端技术栈:jdk8+springboot
- 部署方式:docker+shell脚本
- nginx:动静分离+一个环境多个域名+SSL(cloud-dev.* ,cloud-demo.* ...)
- 多个前端项目+多个后端服务(多台阿里云ECS服务器)
- 前端技术:angular8、react和vue
- 后端技术:jdk8+springcloud+redis和python
- 部署方式:k8s+docker+jenkins(CI/CD)
- nginx:nginx集群+一个环境一个域名+SSL(cloud-dev.* ,cloud-st.* ,cloud-prod.*)
- 多个前端项目+多个后端(阿里云+华为云)
- 前端技术:angular8、react和vue
- 后端技术:jdk8+springcloud+redis+kafka和python
- 部署方式:k8s+docker+jenkins(CI/CD)
- nginx:nginx集群+一个环境一个域名+SSL(cloud-dev.* ,cloud-st.* ,cloud-prod.*)
二、浅谈各阶段nginx技术实现
1. 第一阶段,单机版
这个阶段是单个前端服务,单个java后端。这个比较简单,前端打包好的dist文件内的内容直接放在nginx的html文件夹下,后端服务另开一个location指向api服务。简单版配置如下:
events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; #上传大小限制 client_max_body_size 5000m; #下载大小限制 proxy_max_temp_file_size 5000m; gzip on; server { listen 80; location / { root /etc/nginx/html; index index.html index.htm; } location /api { proxy_pass http://192.168.31.162:8080/; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } }
2. 第二阶段,单机多前端
这个阶段的主要的思路就是使用目录隔离服务,实现起来也是比较简单的,可以在html目录下建立多个子目录,然后通过别名的方式代理出去;api的隔离则是通过端口进行隔离。简单版配置如下:
events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; #上传大小限制 client_max_body_size 5000m; #下载大小限制 proxy_max_temp_file_size 5000m; gzip on; ## 一、dev环境的配置 server { listen 80; listen 443 ssl; server_name cloud-dev.*****.com.cn; #charset koi8-r; ssl_certificate /etc/nginx/ssl/server.pem; ssl_certificate_key /etc/nginx/ssl/server.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; add_header Content-Security-Policy "upgrade-insecure-requests"; location /web { alias /etc/nginx/html/dev/frontend; index index.html index.htm; } location /vott { alias /etc/nginx/html/dev/vott; index index.html index.htm; } location /api { proxy_pass http://192.168.31.162:8080/; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } ## 二、demo环境的配置 server { listen 80; listen 443 ssl; server_name cloud-demo.*****.com.cn; #charset koi8-r; ssl_certificate /etc/nginx/ssl/server.pem; ssl_certificate_key /etc/nginx/ssl/server.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; add_header Content-Security-Policy "upgrade-insecure-requests"; location /web { alias /etc/nginx/html/demo/frontend; index index.html index.htm; } location /vott { alias /etc/nginx/html/demo/vott; index index.html index.htm; } location /api { proxy_pass http://192.168.31.162:8081/; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } }
三、第三阶段,分布式
第三阶段主要是由于基础开发和核心AI功能模块陆续交付,单个后端无法满足性能要求了,需要对业务进行拆分,将单机版服务拆解成分布式服务,采用springcloud,AI模块则由python来处理并暴露接口,所有的接口都需要经过业务网关gateway暴露出去,再由nginx代理指向gateway;前端需要改版了,不能再使用目录隔离了,因为不再是单机版的,解决办法是将每个前端项目配置一个nginx服务,将前端打包文件放在html目录中(静态渲染功能),每个nginx服务都用端口区分。最后用一个总网关nginx代理出去(代理功能),这个时候碰到一个问题了,每个都是html目录,单个域名无法区分了,当时没有去尝试二级域名的方式,直接使用域名进行区分。简单配置如下:
events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; #上传大小限制 client_max_body_size 5000m; #下载大小限制 proxy_max_temp_file_size 5000m; gzip on; ## 一、api的配置 server { listen 80; listen 443 ssl; server_name api-dev.*****.com.cn; #charset koi8-r; ssl_certificate /etc/nginx/ssl/server.pem; ssl_certificate_key /etc/nginx/ssl/server.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; add_header Content-Security-Policy "upgrade-insecure-requests"; location /api { proxy_pass http://192.168.31.162:8080/; } } ## 二、web的配置 server { listen 80; listen 443 ssl; server_name cloud-dev.*****.com.cn; #charset koi8-r; ssl_certificate /etc/nginx/ssl/server.pem; ssl_certificate_key /etc/nginx/ssl/server.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; add_header Content-Security-Policy "upgrade-insecure-requests"; location / { root html; proxy_pass http://192.168.31.162:81; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } ## 二、vott的配置 server { listen 80; listen 443 ssl; server_name vott-dev.*****.com.cn; #charset koi8-r; ssl_certificate /etc/nginx/ssl/server.pem; ssl_certificate_key /etc/nginx/ssl/server.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; add_header Content-Security-Policy "upgrade-insecure-requests"; location / { root html; proxy_pass http://192.168.31.162:3000; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } ## 三、viewer的配置 server { listen 80; listen 443 ssl; server_name viewer-dev.*****.com.cn; #charset koi8-r; ssl_certificate /etc/nginx/ssl/server.pem; ssl_certificate_key /etc/nginx/ssl/server.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; add_header Content-Security-Policy "upgrade-insecure-requests"; location / { root html; proxy_pass http://192.168.31.162:3006; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } }
四、第四阶段,等保要求
由于公司是做医疗项目的,密保要求很高,要通过审核就必须通过审核,然后一个域名代表一个服务,成本就增加了翻几番。为了使所有服务都通过单个域名代理出去,二级域名(前端需要建立虚拟目录)就很有必要了,具体是怎么做的,下篇见分晓。简单配置如下:
events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; #keepalive_timeout 0; keepalive_timeout 65; #上传大小限制 client_max_body_size 5000m; #下载大小限制 proxy_max_temp_file_size 5000m; gzip on; server { listen 80; listen 443 ssl; server_name cloud.imagecore.com.cn; #charset koi8-r; ssl_certificate /etc/nginx/ssl/server.pem; ssl_certificate_key /etc/nginx/ssl/server.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; add_header Content-Security-Policy "upgrade-insecure-requests"; # 后端api location /api/ { proxy_pass http://10.100.35.21:8080/api/; } location / { return 200; } # viewer location /viewer/ { root html; proxy_pass http://10.108.125.174; index index.html index.htm; } # vott location /vott/ { proxy_pass http://10.97.150.67 ; } # web location /web/ { proxy_pass http://10.110.118.87:80; } } }
三、总结
以上使用的nginx技术无非就是浅显的动静分离,目录隔离、域名隔离、端口隔离、二级域名和SSL等,基本上都是修改配置文件,基本上没有什么开发任务。虽然是这样说,一路弯弯曲曲走来躺过了好多坑了,看过帖子,找过官网,对nginx的理解和使用也提升了不少。里面有很多的优化项目和好用的功能,之后文章会一一介绍。唉,也就是做笔记了,没啥人看。自己先给自己打气,今年关注突破3000就行,目前是600多个。