前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >websocket

websocket

作者头像
wo.
发布2021-06-15 11:05:21
1.4K0
发布2021-06-15 11:05:21
举报
文章被收录于专栏:了不得的专栏

前端页面的实时刷新一般两种思路,即拉和推的思路:

代码语言:javascript
复制
拉:前端每隔一段时间到后台请求数据;
推:后端需要推送数据时,向前端推送数据。

拉的方式比较耗费资源,因为http是无状态且单向的通讯协议,后端无法主动xia向前端发送信息,一般拉为前端不间断的向服务端发送http请求,这种方式前端和后端都比较头疼。没有特殊需求的话,一般使用推的方式。HTML5开始提供websocket解决方式,基于TCP实现客户端与服务端全双工通信。websocket只使用了一个连接,避免了连接的多次建立;且只有连接初次建立比较复杂,后期通信成本较低。

实现方式,前后端通过心跳保持长连接,当后端有数据时,调用通知方法,以消息的方式通知前端。

tomcat7以后开始提供了websocket,基于servlet容器可以使用javax.websocket,后端代码:

代码语言:javascript
复制
@Component
@ServerEndpoint("/websocket")
public class WebSocketResource implements AcknowledgingMessageListener<Integer, String> {

    private static ConcurrentMap<String, Session> socketMap = new ConcurrentHashMap<>();

    private Logger logger = LoggerFactory.getLogger(WebSocketResource.class);

 
    @OnOpen
    public void onOpen(Session session) {
        socketMap.put(session.getQueryString(), session);
    }
 
    @OnClose
    public void onClose(Session session) {
        socketMap.remove(session.getQueryString());
    }
 
    @OnMessage
    public void onMessage(String message, Session session) {
        logger.info("heat beat: " + message + "---" + session.getQueryString());
    }
 
    @OnError
    public void onError(Throwable error) {
        throw new RuntimeException(error);
    }

    @Override
    public void onMessage(ConsumerRecord<Integer, String> consumerRecord, Acknowledgment acknowledgment) {
        String message = consumerRecord.value();
        if (StringUtil.isBlank(message)) {
            return;
        }

        UnDealMsDto unDealMsDto = CommonUtil.jsonToObject(consumerRecord.value(), UnDealMsDto.class);
        sendMessages("refresh-un-deal", socketMap.get(unDealMsDto.getToken()));
    }

    private void sendMessages(String message, Session session) {
        if (StringUtil.isBlank(message) || null == session) {
            return;
        }

        try {
            socketMap.get(session.getQueryString()).getBasicRemote().sendText(message);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

此外,spring也提供了对websocket的支持,可以使用spring-websocket包实现,可以扩展 TextWebSocketHandler,spring监听到 websocket事件后会调用对应的方法。

前端以vue举例:

代码语言:javascript
复制
    initWebSocket() {
      this.websoket = new WebSocket("wss://{your.domain}/websocket?678d1a2132894c6e952bcdc9e0debac1")
      this.websoket.onopen = this.webSocketOnOpen
      this.websoket.onerror = this.webSocketOnError
      this.websoket.onmessage = this.webSocketOnMessage
      this.websoket.onclose = this.webSocketOnClose
    },
    webSocketOnOpen () {
      let me = this;
      setInterval(() => {
          me.webSocketSend(JSON.stringify({ type: "ping" }));
      }, 30000);
    },
    webSocketOnError (e) {
      console.dir(e)
    },
    webSocketOnMessage (e) {
      console.log('data:')
      console.dir(e)
    },
    webSocketSend (data) {
      this.websoket.send(data);
    },
    webSocketOnClose (e) {
      setTimeout(() => {
        this.initWebSocket();
      }, 500);
    },

需要注意的是,没有使用SSL时,协议前缀使用ws,类似http;否则使用wss,类似https。

nginx对websocket做了支持,如使用nginx转发,示例:

代码语言:javascript
复制
    proxy_redirect off;  
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_read_timeout 600;
    proxy_pass backend;
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-07-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档