1. 需求:
- 使用docker-compose容器编排三个项目:
项目1:网站前端,主要功能是展示页面,如果仅仅是静态网页,可以放在nginx的html目录即可,但是有一个功能:平台需要获取客户端请求的URL,然后根据不同的域名前缀,响应不同的首页;
技术路线:spring boot项目,服务端口是8080;
容器名称是:webclient;
单独访问项目:http://webclient:8080
项目2:后端接口,主要功能是向前端网页提供接口,从登录开始,到登出接口,功能都是由这个项目提供,这是个典型的前后端分离项目;
技术路线:spring boot项目,服务端口是8080;
容器名称是:webapis;
单独访问项目:
登录接口:http://webapis:8080/api-u/login
其他接口:http://webapis:8080/api-×/×××
项目3:websocket工程,主要提供websocket服务,提供一个简单的网页,在网页里面提供websocket支持;
技术路线:spring boot项目,服务端口是8080;
容器名称是:websocket;
单独访问项目:http://websocket:8080,websocket服务:ws://×××/×××/××× - 这三个项目单独访问都没有问题,现在需要在容器中添加一个nginx,针对用户的请求,跳转到80端口,后端自动落到webclient容器;针对网页中接口请求,后端自动落到webapis容器;针对websocket的请求,后端落到websocket服务器上;
- 所有的请求都要走80端口,为了使请求准确落到不同容器,在请求URL增加标识:
例如:
默认请求,后端自动落到webclient容器;因为要解析不同的域名,不能修改后端收到的URL;
URL中包含/api/的请求,后端自动落到webapis容器;真正在后端的请求URL中不能携带/api/;
URL中包含/ws/的请求,后端自动落到websocket服务器上;真正在后端的请求URL中不能携带/ws/;
2. nginx.conf配置
- 文件配置
server {
listen 80; # 监听80端口
server_name localhost; # 名字就写localhost
location ~/ { # 默认请求处理方法
proxy_set_header Host $host; # 添加Host,设置变量是 $host,后端的请求中将不会修改成http://webclient:8080,而是会将前端的请求url直接返回给后端;
proxy_pass http://webclient:8080;
}
location ^~/api/ { # url中包含api处理方法
proxy_pass http://webapis:8080/; # 如果去掉最后的 / ,返回给后端的请求中就会自动携带api/
}
location ^~/ws/ { # url中包含ws处理方法
#添加websocket代理
proxy_pass http://websocket:8080/; # 如果去掉最后的 / ,返回给后端的请求中就会自动携带ws/
proxy_http_version 1.1; # 必须配置1.1,官网上说的,使用http/1.1;
proxy_set_header Upgrade $http_upgrade; # 为了让Nginx代理服务器可以将来自客户端的Upgrade请求发送到后端服务器,要求Upgrade和Connection的头信息必须被显式的设置
proxy_set_header Connection "Upgrade"; # 关于Connection,有两种方式,一种是直接写死,“upgrade”,强制连接升级;一种是对代理服务器的请求中“Connection”标头字段的值取决于客户端请求标头中“Upgrade”字段的值,相当于由客户端决定;
}
}
- Nginx配置Websocket方式
参考文档:
https://www.sohu.com/a/328641687_470018 http://nginx.org/en/docs/http/websocket.html - Nginx如何支持WebSocket
WebSocket 和HTTP虽然是不同协议,但是两者“握手”方式兼容。通过HTTP升级机制,使用HTTP的Upgrade和Connection协议头的方式可以将连接从HTTP升级为WebSocket: - Http升级为WebSocket
因为WebSocket协议是一个hop-by-hop协议(此类头部字段只对单次转发有效。会因为转发给缓存/代理服务器而失效),为了让Nginx代理服务器可以将来自客户端的Upgrade请求发送到后端服务器,要求Upgrade和Connection的头信息必须被显式的设置。可以通过下文将要讲解的修改Nginx的配置文件方式解决此问题。
- map是根据客户端请求中 $http_upgrade 的值来构造改变 $connection_upgrade 的值,即根据变量 $http_upgrade 的值和{} 里规则创建新的变量 $connection_upgrade并赋值。
- HTTP的Upgrade协议头机制用于将连接从HTTP连接升级到WebSocket连接,Upgrade机制使用了Upgrade协议头和Connection协议头;为了让Nginx可以将来自客户端的Upgrade请求发送到后端服务器,Upgrade和Connection的头信息必须被显式的设置。
- 官网的例子:http://nginx.org/en/docs/http/websocket.html
3. 为什么HTTP Upgrade的时候,需要Connection: upgrade
可以参考文章:https://www.yuque.com/devweb/front/ztg8ur