SpringBoot+WebSocket通过Nginx方向代理建立连接,后端主动推送消息

时间:2025-03-19 20:32:19

       在网上了解到WebSocket走Zuul网关会被降级,从TCP降到Http,性能会下降,所以考虑使用Nginx与后端建立连接。话不多说直接上代码!!

1、前端代码。直接请求80端口

 created(){
    ();
  },
  methods: {
    reload() {
       = false;
      this.$nextTick(() => ( = true));
    },
    receiveTypeFromHeader: function(value) {
       = value;
    },
    initWebSocket() {
      //初始化weosocket
       = new WebSocket('ws://localhost/realtime/websocket');

       = ;

       = ;

       = ;

       = ;
    },
    webSocketOnOpen() {
      ("WebSocket连接成功");
    },
    webSocketOnError(res) {
      ("WebSocket连接发生错误");
    },
    webSocketOnMessage(res) {
      if( === '1'){
        ();
        ("刷新~~~~~")
      }
    },
    webSocketClose(res) {
      ("connection closed (" +  + ")");
    }
  }

2、从版本1.3.13开始,nginx实现了特殊的操作模式,如果代理服务器返回带有代码101(交换协议)的响应,则允许在客户端和代理服务器之间建立隧道,并且客户端要求通过请求中的“升级”标头。(来自于官网)Nginx官网

所以我们建立隧道,添加标识,上代码。这个****的代码格式,我付了!!


events {
    worker_connections  1024;
}


http {
    include       ;
    default_type  application/octet-stream;

	
	 map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }
	
	upstream  {
		server localhost:8082;
	}

    server {
        listen       80;
        server_name  localhost;

        location / {
            root   html;
            index   ;
        }
		
		location /realtime/websocket {
			proxy_pass ;
            proxy_http_version 1.1;
			proxy_connect_timeout 4s;              
            proxy_read_timeout 3600s;   #默认60s没有传输数据就会关闭,延长时间            
            proxy_send_timeout 12s;    
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
		}

        error_page   500 502 503 504  /;

        location = / {
            root   html;
        }
    }

}

3.后端代码

使用@ServerEndpoint创立websocket endpoint

* 使用springboot内置tomcat进行部署的话,在编写websocket具体实现类之前,
* 要注入ServerEndpointExporter,这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint。
* 而如果使用war包部署到tomcat中进行部署的话,就不必做此步骤,因为它将由容器自己提供和管理。

@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter(){
        return new ServerEndpointExporter();
    }
}
import org.;
import org.;
import ;

import .*;
import ;
import ;
import ;

@Component
@ServerEndpoint("/realtime/websocket")
public class WebSocket {

    private Logger log = (());

    private static int onLineNumber;

    private static Map<String, WebSocket> clients = new ConcurrentHashMap<>();

    private Session session;

    @OnOpen
    public void onOpen(Session session){



         = session;

        ((),this);

        getAddOnLineNumber();

        ("当前在线人数:"+getOnLineNumber());
    }

    @OnMessage
    public void onMessage(String params,Session session){
//        ("------"+());
//        params = ();
        sendMessageAll(params);
    }

    @OnClose
    public void onClose(Session session){
        (());

        getReduceOnLineNumber();
    }

    @OnError
    public void onError(Session session, Throwable error) {
        ("服务端发生了错误"+());
    }

    public static void sendMessageAll(String message){
        for(WebSocket item:()){
            ().sendText(message);
        }
    }

    private static synchronized int getAddOnLineNumber(){
        return onLineNumber++;
    }

    private static synchronized int getReduceOnLineNumber(){
        return onLineNumber--;
    }

    private static synchronized int getOnLineNumber(){
        return onLineNumber;
    }

}

消息通知,我在项目中是数据库中的存储过程跑完了,就通知前端有新数据了然后刷新组件。

大家根据业务需求去处理,下发数据直接注入一个对象

@Autowired
private WebSocket webSocket;

然后用对象去调用 (data); 就行了

最后

花落知多少,点个赞来好不好~