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

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

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

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

      this.webSocket.onopen = this.webSocketOnOpen;

      this.webSocket.onerror = this.webSocketOnError;

      this.webSocket.onmessage = this.webSocketOnMessage;

      this.webSocket.onclose = this.webSocketClose;
    },
    webSocketOnOpen() {
      console.log("WebSocket连接成功");
    },
    webSocketOnError(res) {
      console.log("WebSocket连接发生错误");
    },
    webSocketOnMessage(res) {
      if(res.data === '1'){
        this.reload();
        console.log("刷新~~~~~")
      }
    },
    webSocketClose(res) {
      console.log("connection closed (" + res.code + ")");
    }
  }

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

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


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

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

    server {
        listen       80;
        server_name  localhost;

        location / {
            root   html;
            index  index.html index.htm;
        }
		
		location /realtime/websocket {
			proxy_pass http://jiaxun.com;
            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  /50x.html;

        location = /50x.html {
            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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

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

    private Logger log = LoggerFactory.getLogger(this.getClass());

    private static int onLineNumber;

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

    private Session session;

    @OnOpen
    public void onOpen(Session session){



        this.session = session;

        clients.put(session.getId(),this);

        getAddOnLineNumber();

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

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

    @OnClose
    public void onClose(Session session){
        clients.remove(session.getId());

        getReduceOnLineNumber();
    }

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

    public static void sendMessageAll(String message){
        for(WebSocket item:clients.values()){
            item.session.getAsyncRemote().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;

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

最后

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

你可能感兴趣的:(java,服务器)