当前位置: 首页 > news >正文

服务器对应的网站开发语言建e室内设计网全景分类

服务器对应的网站开发语言,建e室内设计网全景分类,wordpress根据字段判断,有网站怎么做企业邮箱1.概述 消息推送在日常使用中的场景比较多#xff0c;比如有人点赞了我的博客或者关注了我#xff0c;这时我就会收到一条推送消息#xff0c;以此来吸引我点击或者打开应用。消息推送的方式主要分为两种#xff1a;web消息推送和移动端消息推送。它将所要发送的信息…1.概述 消息推送在日常使用中的场景比较多比如有人点赞了我的博客或者关注了我这时我就会收到一条推送消息以此来吸引我点击或者打开应用。消息推送的方式主要分为两种web消息推送和移动端消息推送。它将所要发送的信息发送至用户当前访问的网页或者移动设备。本文主要分析在web端进行消息推送的几种方式实现用户在web端接收推送消息。 2.消息推送几种方式 web消息推送的方式主要分为两种一种是主动向服务端请求简单理解为客户端pull消息、一种是服务端推送简单理解为服务端push消息。两种方式各有利弊主动向服务端请求会按照一定周期不断去请求服务器如果客户端数量庞大会对服务端造成极大压力并且数据具有一定延时性服务端推送实时性较好但服务端需要存储客户端会话信息如果客户端数量较多服务端查询对应会话压力较大。 2.1 Pull消息 Pull消息主要是客户端发起的操作定时向服务端进行轮询获取消息轮询可分为短轮询和长轮询。 短轮询指定时间间隔由应用浏览器发送http请求服务器实时返回消息至客户端浏览器进行展示短轮询在前端一般通过JS定时器定时发送请求来实现 长轮询是对短轮询的一种优化客户端发起请求服务器不会立即返回请求结果而是将请求挂起等待一段时间如果此时间段内数据变更立即响应客户端请求若是一直无变化则等到指定的超时时间响应请求客户端重新发起长连接长轮询在nacos、Kafka、RocketMQ队列中使用较多。 2.2 Push消息 服务端向客户端推送在一定程度上能节约一部分资源常用的方式有WebSocket、SSE等还有一些通过中间件RabbitMQ来实现等。本文主要介绍利用SSE方式和WebSocket方式来推送消息具体如下 2.2.1 SSE SSE(Server-sent events)是一种用于实现服务器向客户端实时推送数据的Web技术。与传统的短轮询和长轮询相比SSE提供了更高效和实时的数据推送机制。SSE基于HTTP协议允许服务器将数据以事件流Event Stream的形式发送给客户端。客户端通过建立持久的HTTP连接并监听事件流可以实时接收服务器推送的数据。SSE的主要特点包括 简单易用SSE使用基于文本的数据格式如纯文本、JSON等使得数据的发送和解析都相对简单 单向通信SSE支持服务器向客户端的单向通信服务器可以主动推送数据给客户端而客户端只能接收数据 实时性SSE建立长时间的连接使得服务器可以实时地将数据推送给客户端而无需客户端频繁地发起请求。 SSE的整体实现思路如下它的原理其实类似于在线视频播放视频流会连续不断的推送到浏览器图如下 其实可以简单地理解为它是一种单向实时通信技术一旦客户端与服务端建立连接只能接收服务端信息不能向服务端发送信息且拥有自动重连机制客户端与服务端断开会进行自动重连websocket断开不能自动重连这是SSE优于websocket的地方。 Springboot使用SSE功能发送信息代码如下由于springboot内嵌sse模块因此不需要引入额外包 package com.eckey.lab.controller;import lombok.extern.slf4j.Slf4j; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;import java.io.IOException; import java.util.Map; import java.util.concurrent.ConcurrentHashMap;/*** Author: Marin* CreateTime: 2023-10-08 14:29* Description: TODO* Version: 1.0*/ Slf4j RestController CrossOrigin //此注解是为了解决测试过程中的跨域问题 RequestMapping(/sse) public class SSEController {/*** 使用Map对象来存放userId和对应的会话*/private static MapString, SseEmitter sseEmitterMap new ConcurrentHashMap();/*** description: 浏览器端注册将会话信息存入Map这种方式会导致一个userId只能与服务器建立一个会话生产环境慎用这种方式* author: Marin* date: 2023/10/9 16:51* param: [userId]* return: org.springframework.web.servlet.mvc.method.annotation.SseEmitter**/GetMapping(path /subscribe/{userId}, produces {MediaType.TEXT_EVENT_STREAM_VALUE})public SseEmitter subscribe(PathVariable(userId) String userId) throws IOException {// 设置超时时间0表示不过期。默认30秒超过时间未完成会抛出异常AsyncRequestTimeoutExceptionSseEmitter sseEmitter new SseEmitter(30_000L);// 设置前端的重试时间为15s如果不加这个发送一下前端就不会显示连接成功sseEmitter.send(连接成功);// 注册回调sseEmitter.onCompletion(() - {log.info(连接结束{}, userId);});sseEmitter.onError((Throwable throwable) - {log.error(连接异常:{}, throwable.getMessage());});sseEmitter.onTimeout(() - {log.warn(连接超时{}, userId);});//以userId为key如果一个用户多个设备连接会不准确sseEmitterMap.put(userId, sseEmitter);log.info(创建新的sse连接当前用户{}, userId);return sseEmitter;}/*** description: 向指定用户发送指定信息* author: Marin* date: 2023/10/9 16:53* param: [userId, message]* return: void**/GetMapping(path /sendMessage)public void sendMessage(String userId, String message) {if (sseEmitterMap.containsKey(userId)) {try {log.info(向用户{},发送消息{}, userId, message);sseEmitterMap.get(userId).send(message, MediaType.APPLICATION_JSON);} catch (IOException e) {log.error(用户[{}]推送异常:{}, userId, e.getMessage());removeUser(userId);}}}/*** description: 移除用户* author: Marin* date: 2023/10/9 16:53* param: [userId]* return: void**/private void removeUser(String userId) {sseEmitterMap.remove(userId);log.info(移除用户成功{}, userId);}/*** description: 删除与指定用户会话* author: Marin* date: 2023/10/9 16:54* param: [userId]* return: void**/GetMapping(/close/{userId})public void close(PathVariable(userId) String userId) {removeUser(userId);log.info(关闭连接成功{}, userId);} } 前端测试代码如下 !DOCTYPE html html langenheadmeta charsetUTF-8titleSseEmitter/title /headbody button onclickcloseSse()关闭连接/button div idmessage/div /body scriptlet source null;// 用时间戳模拟登录用户const userId new Date().getTime();if (window.EventSource) {// 建立连接source new EventSource(http://127.0.0.1:9090/sse/subscribe/ userId);setMessageInnerHTML(连接用户 userId);source.addEventListener(open, function(e) {setMessageInnerHTML(建立连接。。。);}, false);source.addEventListener(message, function(e) {setMessageInnerHTML(e.data);});source.addEventListener(error, function(e) {if (e.readyState EventSource.CLOSED) {setMessageInnerHTML(连接关闭);} else if (e.target.readyState EventSource.CONNECTING) { console.log(Connecting...);}else {console.log(e);}}, false);} else {setMessageInnerHTML(你的浏览器不支持SSE);}// 监听窗口关闭事件主动去关闭sse连接如果服务端设置永不过期浏览器关闭后手动清理服务端数据window.onbeforeunload function() {closeSse();};// 关闭Sse连接function closeSse() {source.close();const httpRequest new XMLHttpRequest();httpRequest.open(GET, http://127.0.0.1:9090/sse/close/ userId, true);httpRequest.send();console.log(close);}// 将消息显示在网页上function setMessageInnerHTML(innerHTML) {document.getElementById(message).innerHTML innerHTML br/;} /script/html打开前端页面会出现连接信息如下所示 调用信息发送接口跟据用户id发送指定消息如下 发送成功后前端接收并显示在页面上如下 2.2.2 WebSocket WebSocket是一种用于实现实时双向通信的Web技术它使得客户端和服务器之间的数据交换变得更加简单允许服务端主动向客户端推送数据。在WebSocket API中浏览器和服务器只需要完成一次握手两者之间就直接可以创建持久性的连接并进行双向数据传输。它与SSE在某些方面有所不同。下面是SSE和WebSocket之间的比较 数据推送方向SSE是服务器向客户端的单向通信服务器可以主动推送数据给客户端。而WebSocket是双向通信允许服务器和客户端之间进行实时的双向数据交换 连接建立SSE使用基于HTTP的长连接通过普通的HTTP请求和响应来建立连接从而实现数据的实时推送。WebSocket使用自定义的协议通过建立WebSocket连接来实现双向通信 兼容性由于SSE基于HTTP协议它可以在大多数现代浏览器中使用并且不需要额外的协议升级。WebSocket在绝大多数现代浏览器中也得到了支持但在某些特殊的网络环境下可能会遇到问题 适用场景SSE适用于服务器向客户端实时推送数据的场景如股票价格更新、新闻实时推送等。WebSocket适用于需要实时双向通信的场景如聊天应用、多人协同编辑等。 WebSocket原理图如下所示 Springboot整合websocket如下 1.引入pom dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-websocket/artifactId/dependency2.编写socket配置 package com.eckey.lab.config;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.web.servlet.ServletContextInitializer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.server.standard.ServerEndpointExporter;import javax.servlet.ServletContext; import javax.servlet.ServletException;/*** Author: Marin* CreateTime: 2023-10-08 16:26* Description: TODO* Version: 1.0*/ Slf4j Configuration public class WebSocketConfig implements ServletContextInitializer {/*** 这个bean的注册,用于扫描带有ServerEndpoint的注解成为websocket,如果你使用外置的tomcat就不需要该配置文件*/Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}Overridepublic void onStartup(ServletContext servletContext) throws ServletException {String serverInfo servletContext.getServerInfo();log.info(serverInfo:{}, serverInfo);}}3.编写SocketServer代码 package com.eckey.lab.config;import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component;import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import java.util.HashMap; import java.util.Map; import java.util.concurrent.CopyOnWriteArraySet;/*** Author: Marin* CreateTime: 2023-10-08 15:49* Description: TODO* Version: 1.0*/ Component Slf4j ServerEndpoint(/websocket/{userId}) public class WebSocketServer {//与某个客户端的连接会话需要通过它来给客户端发送数据private Session session;private static final CopyOnWriteArraySetWebSocketServer webSockets new CopyOnWriteArraySet();// 用来存在线连接数private static final MapString, Session sessionPool new HashMapString, Session();/*** 链接成功调用的方法*/OnOpenpublic void onOpen(Session session, PathParam(value userId) String userId) {try {this.session session;webSockets.add(this);sessionPool.put(userId, session);log.info(websocket消息: 有新的连接总数为: webSockets.size());} catch (Exception e) {log.error();}}/*** 收到客户端消息后调用的方法*/OnMessagepublic void onMessage(String message) {log.info(websocket消息: 收到客户端消息: message);}/*** 此为单点消息*/public void sendOneMessage(String userId, String message) {Session session sessionPool.get(userId);if (session ! null session.isOpen()) {try {log.info(websocket发送单点消息: message);session.getAsyncRemote().sendText(message);} catch (Exception e) {e.printStackTrace();}}} }4.编写controller代码 package com.eckey.lab.controller;import com.alibaba.fastjson.JSON; import com.eckey.lab.config.WebSocketServer; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*;import java.io.IOException; import java.util.HashMap;/*** Author: Marin* CreateTime: 2023-10-08 15:24* Description: TODO* Version: 1.0*/ Slf4j RestController CrossOrigin RequestMapping(/socket) public class WebSocketController {Autowiredprivate WebSocketServer webSocketServer;GetMapping(path /publish/{userId})public String publish(PathVariable(userId) String userId, String message) throws IOException {webSocketServer.sendOneMessage(userId, message);log.info(信息发送成功userId:{},message:{}, userId, message);HashMap maps new HashMap();maps.put(code, 0);maps.put(msg, success);return JSON.toJSONString(maps);}}5.测试 客户端发送消息服务接收到消息具体如下 调用服务端接口发送消息客户端接收到消息具体如下 3.小结 1.SSE方式是一种基于TCP协议的单向数据传输方式当连接建立完成只能由服务端向客户端发送信息 2.WebSocket是一种双向通信技术能够实现客户端和服务端的全双工通信它在建立连接时使用HTTP协议其它时候都是直接基于TCP协议进行通信 3.在选择SSE或者WebSocket时需要跟据场景、性能损耗进行综合考虑合理的技术选型能够有效增强服务的健壮性。 4.参考文献 1.https://zhuanlan.zhihu.com/p/634581294 2.https://juejin.cn/post/7122014462181113887 3.https://javaguide.cn/system-design/web-real-time-message-push.html 5.附录 https://gitee.com/Marinc/nacos.git
http://www.yingshimen.cn/news/5661/

相关文章:

  • 团队网站建设哪家便宜在网站上做教学直播平台多少钱
  • 网站建设及推广预算表西地那非是什么药
  • 中铁韩城建设公司网站手机网站后台源码
  • 网站制作软件安卓版买域名去哪个网站好
  • 上海市住房和城乡建设管理局网站白山市城乡建设局网站
  • 模拟建设官方网站网页搭建app
  • 做网站被网警找政务网站建设管理的论文
  • 吉林省现代交通建设有限公司官网站女生学什么技术最吃香
  • 英铭科技做网站和设计制作更专业跨境电商平台哪家最好
  • wordpress有名的网站江门网站建设方案推广
  • 如何做个网站做cpa深圳产品设计手绘
  • 天津工程建设网官方网站杭州seo网站推广排名
  • 大作业网站建设方案如何保存wordpress主题设置
  • 网站工商备案查询开发公司各部门职责
  • 哈尔滨建站每天三分钟新闻天下事
  • 如何做音乐网站托管经营
  • 网站为什么要备案登记网站外贸推广
  • 如皋教育门户网站建设经验北京商场面积排名
  • 酒庄企业网站网站开发学费
  • 专门做美妆的网站已备案域名交易平台
  • 专做动漫解说的网站源代码 培训 网站
  • 自己学习建设网站宁波网络营销策划
  • cn结尾的网站 做外贸网页制作最常用的软件
  • 南京 推广 网站建设网站建设推进表
  • 潍坊建设厅官方网站黄骅港鑫海化工招聘
  • 太原网站建设列表网wordpress关键词怎么设置
  • 适合个人网站广告创意设计总结
  • 食品 骏域网站建设专家微山网站建设多少钱
  • 商务网站建设实验记录系统开发费用账务处理
  • 招标网站建设什么网站做玩具的外贸