广州网站设计报价,网站开发外包业务怎么接,大连市网站推广公司,手机销售网站制作使用websocket技术实时输出系统日志到浏览器端#xff0c;实现WebLog boot-websocket-log#xff1a;
spring boot系统中使用websocket技术实时输出系统日志到浏览器端#xff0c;因为是实时输出#xff0c;所有第一时间就想到了使用webSocket,而且在spring boot中#…使用websocket技术实时输出系统日志到浏览器端实现WebLog boot-websocket-log
spring boot系统中使用websocket技术实时输出系统日志到浏览器端因为是实时输出所有第一时间就想到了使用webSocket,而且在spring boot中使用websocket超级方便阅读本文你会接触到以下关键词相关技术
WebSocketstopmp服务端
stomp协议
sockjs.min.js
stomp.min.jsstomp客户端
本文使用到的其实就是
使用spring boot自带的webSocket模块提供stomp的服务端
前端使用stomp.min.js做stomp的客户端
使用sockjs来链接
前端订阅后端日志端点的消息后端实时推送达到日志实时输出到web页面的目的 此项目使用场景 集成到已有的项目中实现项目日志文件web端浏览第一个功能 单独使用指定已有项目的日志文件位置实现项目日志web端浏览第二个功能 使用boot-websocket-log的stopmp服务推送日志其他的非web端消费 参考博文https://gitee.com/kailing/boot-websocket-log 知识补充1stomp协议
STOMP即Simple (or Streaming) Text Orientated Messaging Protocol面向消息的简单文本协议它提供了一个可互操作的连接格式允许STOMP客户端与任意STOMP消息代理Broker进行交互。STOMP协议由于设计简单易于开发客户端因此在多种语言和多种平台上得到广泛地应用。
STOMP协议的前身是TTMP协议一个简单的基于文本的协议专为消息中间件设计。
STOMP是一个非常简单和容易实现的协议其设计灵感源自于HTTP的简单性。尽管STOMP协议在服务器端的实现可能有一定的难度但客户端的实现却很容易。例如可以使用Telnet登录到任何的STOMP代理并与STOMP代理进行交互。
STOMP协议与HTTP协议很相似它基于TCP协议使用了以下命令
CONNECT SEND SUBSCRIBE UNSUBSCRIBE BEGIN COMMIT ABORT ACK NACK DISCONNECT
STOMP的客户端和服务器之间的通信是通过“帧”Frame实现的每个帧由多“行”Line组成。 第一行包含了命令然后紧跟键值对形式的Header内容。 第二行必须是空行。 第三行开始就是Body内容末尾都以空字符结尾。
例 发送消息
SEND destination:/queue/trade content-type:application/json content-length:44 {“action”:”BUY”,”ticker”:”MMM”,”shares”,44}^ 订阅消息 SUBSCRIBE id:sub-1 destination:/topic/price.stock.* ^ 服务器进行广播消息
MESSAGE message-id:nxahklf6-1 subscription:sub-1 destination:/topic/price.stock.MMM {“ticker”:”MMM”,”price”:129.45}^ 客户端 API
引入stomp.js
script typeapplication/javascript srchttp://cdn.bootcss.com/stomp.js/2.3.3/stomp.min.js/script 发起连接 客户端可以通过使用Stomp.js和sockjs-client连接
// 建立连接对象还未发起连接 var socketnew SockJS(/spring-websocket-portfolio/portfolio);
// 获取 STOMP 子协议的客户端对象 var stompClient Stomp.over(socket);
// 向服务器发起websocket连接并发送CONNECT帧 stompClient.connect( {}, function connectCallback (frame) { // 连接成功时服务器响应 CONNECTED 帧的回调方法 document.getElementById(state-info).innerHTML 连接成功; console.log(已连接【 frame 】); stompClient.subscribe(/topic/getResponse, function (response) { showResponse(response.body); }); }, function errorCallBack (error) { // 连接失败时服务器响应 ERROR 帧的回调方法 document.getElementById(state-info).innerHTML 连接失败; console.log(连接失败【 error 】); } );
stompClient.connect()方法签名
client.connect(headers, connectCallback, errorCallback); 其中 headers表示客户端的认证信息如
var headers { login: mylogin, passcode: mypasscode, // additional header client-id: my-client-id }; 若无需认证直接使用空对象 “{}” 即可
connectCallback 表示连接成功时服务器响应 CONNECTED 帧的回调方法 errorCallback 表示连接失败时服务器响应 ERROR 帧的回调方法非必须 断开连接
若要从客户端主动断开连接可调用 disconnect() 方法
client.disconnect(function () {alert(See you next time!);
};
该方法为异步进行因此包含了回调参数操作完成时自动回调 心跳机制 若使用STOMP 1.1 版本默认开启了心跳检测机制可通过client对象的heartbeat field进行配置默认值都是10000 ms
client.heartbeat.outgoing 20000; // client will send heartbeats every 20000ms client.heartbeat.incoming 0; // client does not want to receive heartbeats from the server // The heart-beating is using window.setInterval() to regularly send heart-beats and/or check server heart-beats 发送信息 连接成功后客户端可使用 send() 方法向服务器发送信息
client.send(destination url[, headers[, body]]); 其中 destination url 为服务器 controller中 MessageMapping 中匹配的URL字符串必须参数 headers 为发送信息的headerJavaScript 对象可选参数 body 为发送信息的 body字符串可选参数
例
client.send(/queue/test, {priority: 9}, Hello, STOMP); client.send(/queue/test, {}, Hello, STOMP); 订阅、接收信息
STOMP 客户端要想接收来自服务器推送的消息必须先订阅相应的URL即发送一个 SUBSCRIBE 帧然后才能不断接收来自服务器的推送消息 订阅和接收消息通过 subscribe() 方法实现
subscribe(destination url, callback[, headers])
其中 destination url 为服务器 SendTo 匹配的 URL字符串 callback 为每次收到服务器推送的消息时的回调方法该方法包含参数 message headers 为附加的headersJavaScript 对象什么作用 该方法返回一个包含了id属性的 JavaScript 对象可作为 unsubscribe() 方法的参数
例var headers {ack: client, selector: location Europe}; var callback function(message) { if (message.body) { alert(got message with body message.body) } else { alert(got empty message); } }); var subscription client.subscribe(/queue/test, callback, headers);
取消订阅 var subscription client.subscribe(...);
subscription.unsubscribe(); JSON 支持 STOMP 帧的 body 必须是 string 类型若希望接收/发送 json 对象可通过 JSON.stringify() and JSON.parse() 实现 例
var quote {symbol: APPL, value: 195.46}; client.send(/topic/stocks, {}, JSON.stringify(quote));
client.subcribe(/topic/stocks, function(message) { var quote JSON.parse(message.body); alert(quote.symbol is at quote.value); }); 事务支持 STOMP 客户端支持在发送消息时用事务进行处理 举例说明
// start the transaction // 该方法返回一个包含了事务 id、commit()、abort() 的JavaScript 对象 var tx client.begin(); // send the message in a transaction // 最关键的在于要在 headers 对象中加入事务 id若没有添加则会直接发送消息不会以事务进行处理 client.send(/queue/test, {transaction: tx.id}, message in a transaction); // commit the transaction to effectively send the message tx.commit(); // tx.abort(); Debug 信息 STOMP 客户端默认将传输过程中的所有 debug 信息以 console.log() 形式输出到客户端浏览器中也可通过以下方式输出到 DOM 中
client.debug function(str) { // str 参数即为 debug 信息 // append the debug log to a #debug div somewhere in the page using JQuery: $(#debug).append(str \n); }; 认证 这一部分内容看的不是很理解因此直接将原文放在这里了待补充。 By default, STOMP messages will be automatically acknowledged by the server before the message is delivered to the client.
The client can chose instead to handle message acknowledgement by subscribing to a destination and specify a ack header set to client or client-individual.
In that case, the client must use the message.ack() method to inform the server that it has acknowledge the message.
var subscription client.subscribe(/queue/test, function(message) { // do something with the message ... // and acknowledge it message.ack(); }, {ack: client} ); The ack() method accepts a headers argument for additional headers to acknowledge the message. For example, it is possible to acknowledge a message as part of a transaction and ask for a receipt when the ACK STOMP frame has effectively be processed by the broker: var tx client.begin(); message.ack({ transaction: tx.id, receipt: ‘my-receipt’ }); tx.commit(); The nack() method can also be used to inform STOMP 1.1 brokers that the client did not consume the message. It takes the same arguments than the ack() method.
参考博文https://blog.csdn.net/jqsad/article/details/77745379 同 HTTP 在 TCP 套接字上添加请求-响应模型层一样STOMP 在 WebSocket 之上提供了一个基于帧的线路格式层用来定义消息语义 补充知识2websocket
首先HTTP有1.1和1.0之说也就是所谓的keep-alive把多个HTTP请求合并为一个但是Websocket其实是一个新协议跟HTTP协议基本没有关系只是为了兼容现有浏览器的握手规范而已也就是说它是HTTP协议上的一种补充可以通过这样一张图理解 重点两个关键主动推送信息持久连接
二、Websocket是什么样的协议具体有什么优点首先Websocket是一个持久化的协议相对于HTTP这种非持久的协议来说。 简单的举个例子吧用目前应用比较广泛的PHP生命周期来解释。 1) HTTP的生命周期通过Request来界定也就是一个Request 一个Response那么在HTTP1.0中这次HTTP请求就结束了。 在HTTP1.1中进行了改进使得有一个keep-alive也就是说在一个HTTP连接中可以发送多个Request接收多个Response。 但是请记住 Request Response 在HTTP中永远是这样也就是说一个request只能有一个response。而且这个response也是被动的不能主动发起。
教练你BB了这么多跟Websocket有什么关系呢 _(:з」∠)_好吧我正准备说Websocket呢。。 首先Websocket是基于HTTP协议的或者说借用了HTTP的协议来完成一部分握手。 在握手阶段是一样的 -------以下涉及专业技术内容不想看的可以跳过lol:或者只看加黑内容-------- 首先我们来看个典型的Websocket握手借用Wikipedia的。。
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com熟悉HTTP的童鞋可能发现了这段类似HTTP协议的握手请求中多了几个东西。 我会顺便讲解下作用。
Upgrade: websocket
Connection: Upgrade这个就是Websocket的核心了告诉Apache、Nginx等服务器注意啦窝发起的是Websocket协议快点帮我找到对应的助理处理~不是那个老土的HTTP。
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13首先Sec-WebSocket-Key 是一个Base64 encode的值这个是浏览器随机生成的告诉服务器泥煤不要忽悠窝我要验证尼是不是真的是Websocket助理。 然后Sec_WebSocket-Protocol 是一个用户定义的字符串用来区分同URL下不同的服务所需要的协议。简单理解今晚我要服务A别搞错啦~ 最后Sec-WebSocket-Version 是告诉服务器所使用的Websocket Draft协议版本在最初的时候Websocket协议还在 Draft 阶段各种奇奇怪怪的协议都有而且还有很多期奇奇怪怪不同的东西什么Firefox和Chrome用的不是一个版本之类的当初Websocket协议太多可是一个大难题。。不过现在还好已经定下来啦~大家都使用的一个东西~ 脱水服务员我要的是13岁的噢→_→
然后服务器会返回下列东西表示已经接受到请求 成功建立Websocket啦
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk
Sec-WebSocket-Protocol: chat这里开始就是HTTP最后负责的区域了告诉客户我已经成功切换协议啦~
Upgrade: websocket
Connection: Upgrade依然是固定的告诉客户端即将升级的是Websocket协议而不是mozillasocketlurnarsocket或者shitsocket。 然后Sec-WebSocket-Accept 这个则是经过服务器确认并且加密过后的 Sec-WebSocket-Key。服务器好啦好啦知道啦给你看我的ID CARD来证明行了吧。。 后面的Sec-WebSocket-Protocol 则是表示最终使用的协议。
至此HTTP已经完成它所有工作了接下来就是完全按照Websocket协议进行了。 具体的协议就不在这阐述了。
你TMD又BBB了这么久那到底Websocket有什么鬼用http long poll或者ajax轮询不都可以实现实时信息传递么。
好好好年轻人那我们来讲一讲Websocket有什么用。 来给你吃点胡苏萝丹卜红
三、Websocket的作用 在讲Websocket之前我就顺带着讲下 long poll 和 ajax轮询 的原理。 首先是 ajax轮询 ajax轮询 的原理非常简单让浏览器隔个几秒就发送一次请求询问服务器是否有新信息。 场景再现 客户端啦啦啦有没有新信息(Request) 服务端没有Response 客户端啦啦啦有没有新信息(Request) 服务端没有。。Response 客户端啦啦啦有没有新信息(Request) 服务端你好烦啊没有啊。。Response 客户端啦啦啦有没有新消息Request 服务端好啦好啦有啦给你。Response 客户端啦啦啦有没有新消息Request 服务端。。。。。没。。。。没。。。没有Response ---- loop一直循环 long poll long poll 其实原理跟 ajax轮询 差不多都是采用轮询的方式不过采取的是阻塞模型一直打电话没收到就不挂电话也就是说客户端发起连接后如果没消息就一直不返回Response给客户端。直到有消息才返回返回完之后客户端再次建立连接周而复始。 场景再现 客户端啦啦啦有没有新信息没有的话就等有了才返回给我吧Request 服务端额。。 等待到有消息的时候。。来 给你Response 客户端啦啦啦有没有新信息没有的话就等有了才返回给我吧Request -loop
从上面可以看出其实这两种方式都是在不断地建立HTTP连接然后等待服务端处理可以体现HTTP协议的另外一个特点被动性。 何为被动性呢其实就是服务端不能主动联系客户端只能有客户端发起。 简单地说就是服务器是一个很懒的冰箱这是个梗不会、不能主动发起连接但是上司有命令如果有客户来不管多么累都要好好接待。说完这个我们再来说一说上面的缺陷原谅我废话这么多吧OAQ 从上面很容易看出来不管怎么样上面这两种都是非常消耗资源的。ajax轮询 需要服务器有很快的处理速度和资源。速度long poll 需要有很高的并发也就是说同时接待客户的能力。场地大小 所以ajax轮询 和long poll 都有可能发生这种情况。客户端啦啦啦啦有新信息么服务端月线正忙请稍后再试503 Server Unavailable客户端。。。。好吧啦啦啦有新信息么服务端月线正忙请稍后再试503 Server Unavailable然后服务端在一旁忙的要死冰箱我要更多的冰箱更多。。更多。。我错了。。这又是梗。。
言归正传我们来说Websocket吧 通过上面这个例子我们可以看出这两种方式都不是最好的方式需要很多资源。 一种需要更快的速度一种需要更多的电话。这两种都会导致电话的需求越来越高。 哦对了忘记说了HTTP还是一个无状态协议。感谢评论区的各位指出OAQ 通俗的说就是服务器因为每天要接待太多客户了是个健忘鬼你一挂电话他就把你的东西全忘光了把你的东西全丢掉了。你第二次还得再告诉服务器一遍。
所以在这种情况下出现了Websocket出现了。他解决了HTTP的这几个难题。 首先被动性当服务器完成协议升级后HTTP-Websocket服务端就可以主动推送信息给客户端啦。 所以上面的情景可以做如下修改。 客户端啦啦啦我要建立Websocket协议需要的服务chatWebsocket协议版本17HTTP Request 服务端ok确认已升级为Websocket协议HTTP Protocols Switched 客户端麻烦你有信息的时候推送给我噢。。 服务端ok有的时候会告诉你的。 服务端balabalabalabala 服务端balabalabalabala 服务端哈哈哈哈哈啊哈哈哈哈 服务端笑死我了哈哈哈哈哈哈哈
就变成了这样只需要经过一次HTTP请求就可以做到源源不断的信息传送了。在程序设计中这种设计叫做回调即你有信息了再来通知我而不是我傻乎乎的每次跑来问你 这样的协议解决了上面同步有延迟而且还非常消耗资源的这种情况。 那么为什么他会解决服务器上消耗资源的问题呢 其实我们所用的程序是要经过两层代理的即HTTP协议在Nginx等服务器的解析下然后再传送给相应的HandlerPHP等来处理。 简单地说我们有一个非常快速的接线员Nginx他负责把问题转交给相应的客服Handler处理器。 本身接线员基本上速度是足够的但是每次都卡在客服Handler了老有客服处理速度太慢。导致客服不够。 Websocket就解决了这样一个难题建立后可以直接跟接线员建立持久连接有信息的时候客服想办法通知接线员然后接线员在统一转交给客户。 这样就可以解决客服处理速度过慢的问题了。
同时在传统的方式上要不断的建立关闭HTTP协议由于HTTP是非状态性的每次都要重新传输identity info鉴别信息来告诉服务端你是谁。 虽然接线员很快速但是每次都要听这么一堆效率也会有所下降的同时还得不断把这些信息转交给客服不但浪费客服的处理时间而且还会在网路传输中消耗过多的流量/时间。 但是Websocket只需要一次HTTP握手所以说整个通讯过程是建立在一次连接/状态中也就避免了HTTP的非状态性服务端会一直知道你的信息直到你关闭请求这样就解决了接线员要反复解析HTTP协议还要查看identity info的信息。 同时由客户主动询问转换为服务器推送有信息的时候就发送当然客户端还是等主动发送信息过来的。。没有信息的时候就交给接线员Nginx不需要占用本身速度就慢的客服Handler了
参考https://www.zhihu.com/question/20215561 补充3stomp.js客户端Stomp Over Webscoket