1. 需求:

  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://×××/×××/×××
  2. 这三个项目单独访问都没有问题,现在需要在容器中添加一个nginx,针对用户的请求,跳转到80端口,后端自动落到webclient容器;针对网页中接口请求,后端自动落到webapis容器;针对websocket的请求,后端落到websocket服务器上;
  3. 所有的请求都要走80端口,为了使请求准确落到不同容器,在请求URL增加标识:
    例如:
    默认请求,后端自动落到webclient容器;因为要解析不同的域名,不能修改后端收到的URL;
    URL中包含/api/的请求,后端自动落到webapis容器;真正在后端的请求URL中不能携带/api/;
    URL中包含/ws/的请求,后端自动落到websocket服务器上;真正在后端的请求URL中不能携带/ws/;

2. nginx.conf配置

  1. 文件配置
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”字段的值,相当于由客户端决定;
    }

}
  1. Nginx配置Websocket方式
    参考文档:
    https://www.sohu.com/a/328641687_470018 http://nginx.org/en/docs/http/websocket.html
  2. Nginx如何支持WebSocket
    WebSocket 和HTTP虽然是不同协议,但是两者“握手”方式兼容。通过HTTP升级机制,使用HTTP的Upgrade和Connection协议头的方式可以将连接从HTTP升级为WebSocket:
  3. docker设置nginx网站根目录 docker nginx web_nginx

  4. Http升级为WebSocket
    因为WebSocket协议是一个hop-by-hop协议(此类头部字段只对单次转发有效。会因为转发给缓存/代理服务器而失效),为了让Nginx代理服务器可以将来自客户端的Upgrade请求发送到后端服务器,要求Upgrade和Connection的头信息必须被显式的设置。可以通过下文将要讲解的修改Nginx的配置文件方式解决此问题。
  1. map是根据客户端请求中 $http_upgrade 的值来构造改变 $connection_upgrade 的值,即根据变量 $http_upgrade 的值和{} 里规则创建新的变量 $connection_upgrade并赋值。
  2. HTTP的Upgrade协议头机制用于将连接从HTTP连接升级到WebSocket连接,Upgrade机制使用了Upgrade协议头和Connection协议头;为了让Nginx可以将来自客户端的Upgrade请求发送到后端服务器,Upgrade和Connection的头信息必须被显式的设置。
  1. 官网的例子:http://nginx.org/en/docs/http/websocket.html
  2. docker设置nginx网站根目录 docker nginx web_java_02

3. 为什么HTTP Upgrade的时候,需要Connection: upgrade

可以参考文章:https://www.yuque.com/devweb/front/ztg8ur