rsocket,教你如何在Spring Boot中使用RSocket
亲爱的读者们,你是否对rsocket和教你如何在Spring Boot中使用RSocket的相关问题感到困惑?别担心,今天我将为你解答这些问题,让你对此有更清晰的认识。
Winsocket是什么
Winsocket是windows socket的简写,是指Windows下网络编程的规范。
Windows Sockets是Windows下得到广泛应用的、开放的、支持多种协议的网络编程接口。从1991年的1.0版到1995年的2.0.8版,经过不断完善并在Intel、Microsoft、Sun、SGI、Informix、Novell等公司的全力支持下,已成为Windows网络编程的事实上的标准。
Windows Sockets规范以U.C. Berkeley大学BSD UNIX中流行的Socket接口为范例定义了一套microsoft Windows下网络编程接口。
扩展资料:
Windows Sockets模型中,把所有比较靠下面的层次称为网络系统,把靠上面的层次称为WinSock应用程序,而WinSock的应用编程接口(API)位于两者之间。
动态链接库(DLL)是windows的重要特性,动态链接库是带有定义明确的接口的可执行过程的库,就像其名称所提示的那样,应用程序是在运行时动态链接这些库的,而不是在编译时静态链接。
参考资料来源:
百度百科-windows socket
教你如何在Spring Boot中使用RSocket
RSocket应用层协议支持 Reactive Streams语义,例如:用RSocket作为HTTP的一种替代方案。在本教程中,我们将看到RSocket用在spring boot中,特别是spring boot如何帮助抽象出更低级别的RSocket API。
让我们从添加spring-boot-starter-rsocket依赖开始:
这个依赖会传递性的拉取RSocket相关的依赖,比如:rsocket-core和 rsocket-transport-netty
现在继续我们的简单应用程序。为了突出RSocket提供的交互模式,我打算创建一个交易应用程序,交易应用程序包括客户端和服务器。
3.1.服务器设置
首先,我们设置由springboot应用程序引导的RSocket server服务器。因为有spring-boot-starter-rsocket dependency依赖,所以springboot会自动配置RSocket server。跟平常一样,可以用属性驱动的方式修改RSocket server默认配置值。例如:通过增加如下配置在application.properties中,来修改RSocket端口
也可以根据需要进一步修改服务器的其他属性
3.2.设置客户端
接下来,我们来设置客户端,也是一个springboot应用程序。虽然springboot自动配置大部分RSocket相关的组件,但还要自定义一些对象来完成设置。
这儿我们正在创建RSocket客户端并且配置TCP端口为:7000。注意:该服务端口我们在前面已经配置过。接下来我们定义了一个RSocket的装饰器对象RSocketRequester。这个对象在我们跟RSocket server交互时会为我们提供帮助。定义这些对象配置后,我们还只是有了一个骨架。在接下来,我们将暴露不同的交互模式,并看看springboot在这个地方提供帮助的。
我们从Request/Response开始,HTTP也使用这种通信方式,这也是最常见的、最相似的交互模式。在这种交互模式里,由客户端初始化通信并发送一个请求。之后,服务器端执行操作并返回一个响应给客户端--这时通信完成。在我们的交易应用程序里,一个客户端询问一个给定的股票的当前的市场数据。作为回复,服务器会传递请求的数据。
4.1.服务器
在服务器这边,我们首先应该创建一个controller来持有我们的处理器方法。我们会使用@MessageMapping注解来代替像SpringMVC中的@RequestMapping或者@GetMapping注解
来研究下我们的控制器。我们将使用@Controller注解来定义一个控制器来处理进入RSocket的请求。另外,注解@MessageMapping让我们定义我们感兴趣的路由和如何响应一个请求。在这个示例中,服务器监听路由currentMarketData,并响应一个单一的结果Mono<MarketData>给客户端。
4.2.客户端
接下来,我们的RSocket客户端应该询问一只股票的价格并得到一个单一的响应。为了初始化请求,我们该使用RSocketRequester类,如下:
注意:在示例中,RSocket客户端也是一个REST风格的controller,以此来访问我们的RSocket服务器。因此,我们使用@RestController和@GetMapping注解来定义我们的请求/响应端点。在端点方法中,我们使用的是类RSocketRequester并指定了路由。事实上,这个是服务器端RSocket所期望的路由,然后我们传递请求数据。最后,当调用retrieveMono()方法时,springboot会帮我们初始化一个请求/响应交互。
接下来我们将查看 Fire And Forget交互模式。正如名字提示的一样,客户端发送一个请求给服务器,但是不期望服务器的返回响应回来。在我们的交易程序中,一些客户端会作为数据资源服务,并且推送市场数据给服务器端。
5.1.服务器端
我们来创建另外一个端点在我们的服务器应用程序中,如下:
我们又一次定义了一个新的@MessageMapping路由为collectMarketData。此外, Spring Boot自动转换传入的负载为一个MarketData实例。但是,这儿最大的不同是我们返回一个Mono<Void>,因为客户端不需要服务器的返回。
5.2.客户端
来看看我们如何初始化我们的fire-and-forget模式的请求。我们将创建另外一个REST风格的端点,如下:
这儿我们指定路由和负载将是一个MarketData实例。由于我们使用send()方法来代替retrieveMono(),所有交互模式变成了fire-and-forget模式。
请求流是一种更复杂的交互模式,这个模式中客户端发送一个请求,但是在一段时间内从服务器端获取到多个响应。为了模拟这种交互模式,客户端会询问给定股票的所有市场数据。
6.1.服务器端
我们从服务器端开始。我们将添加另外一个消息映射方法,如下:
正如所见,这个处理器方法跟其他的处理器方法非常类似。不同的部分是我们返回一个Flux<MarketData>来代替Mono<MarketData>。最后我们的RSocket服务器会返回多个响应给客户端。
6.2.客户端
在客户端这边,我们该创建一个端点来初始化请求/响应通信,如下:
我们来研究下RSocket请求。首先我们定义了路由和请求负载。然后,我们定义了使用retrieveFlux()调用的响应期望。这部分决定了交互模式。另外注意:由于我们的客户端也是REST风格的服务器,客户端也定义了响应媒介类型MediaType.TEXT_EVENT_STREAM_VALUE。
这里我们给异常处理方法标记注解为@MessageExceptionHandler。作为结果,这个方法将处理所有类型的异常,因为Exception是所有其他类型的异常的超类。我们也可以明确地创建更多的不同类型的,不同的异常处理方法。这当然是请求/响应模式,并且我们返回的是Mono<MarketData>。我们期望这里的响应类型跟我们的交互模式的返回类型相匹配。
一文吃透 WebSocket 原理
踩着年末的尾巴,提前布局来年,为来年的工作做个好的铺垫,所以就开始了面试历程,因为项目中使用到了 WebSocket,面试官在深挖项目经验的时候,也难免提到 WebSocket相关的知识点,因为之前并没有考虑这么深,所以,回答的还是有所欠缺,因此,赶紧趁热再熟悉熟悉,也借此机会,整理出来供大家咀嚼,每个项目都有其值得挖掘的闪光点,要用有爱的眼睛去发现。
WebSocket是一种在单个TCP连接上进行全双工通信的协议。 WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。
在 WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。(维基百科)
WebSocket本质上一种计算机网络应用层的协议,用来弥补 http协议在持久通信能力上的不足。
WebSocket协议在2008年诞生,2011年成为国际标准。现在最新版本浏览器都已经支持了。
它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。
WebSocket的其他特点包括:
我们已经有了 HTTP协议,为什么还需要另一个协议?它能带来什么好处?
因为 HTTP协议有一个缺陷:通信只能由客户端发起,不具备服务器推送能力。
举例来说,我们想了解查询今天的实时数据,只能是客户端向服务器发出请求,服务器返回查询结果。HTTP协议做不到服务器主动向客户端推送信息。
这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。我们只能使用"轮询":每隔一段时候,就发出一个询问,了解服务器有没有新的信息。最典型的场景就是聊天室。轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP连接始终打开)。
在 WebSocket协议出现以前,创建一个和服务端进双通道通信的 web应用,需要依赖HTTP协议,进行不停的轮询,这会导致一些问题:
http协议本身是没有持久通信能力的,但是我们在实际的应用中,是很需要这种能力的,所以,为了解决这些问题, WebSocket协议由此而生,于2011年被IETF定为标准RFC6455,并被RFC7936所补充规范。并且在 HTML5标准中增加了有关 WebSocket协议的相关 api,所以只要实现了 HTML5标准的客户端,就可以与支持 WebSocket协议的服务器进行全双工的持久通信了。
WebSocket与 HTTP的关系图:
下面一张图说明了 HTTP与 WebSocket的主要区别:
不同点:
与http协议一样, WebSocket协议也需要通过已建立的TCP连接来传输数据。具体实现上是通过http协议建立通道,然后在此基础上用真正 WebSocket协议进行通信,所以WebSocket协议和http协议是有一定的交叉关系的。首先, WebSocket是一个持久化的协议,相对于 HTTP这种非持久的协议来说。简单的举个例子吧,用目前应用比较广泛的 PHP生命周期来解释。
HTTP的生命周期通过 Request来界定,也就是一个 Request一个 Response,那么在 HTTP1.0中,这次 HTTP请求就结束了。
在 HTTP1.1中进行了改进,使得有一个 keep-alive,也就是说,在一个 HTTP连接中,可以发送多个 Request,接收多个 Response。但是请记住 Request= Response,在 HTTP中永远是这样,也就是说一个 Request只能有一个 Response。而且这个 Response也是被动的,不能主动发起。首先 WebSocket是基于 HTTP协议的,或者说借用了 HTTP协议来完成一部分握手。
首先我们来看个典型的 WebSocket握手
熟悉 HTTP的童鞋可能发现了,这段类似 HTTP协议的握手请求中,多了这么几个东西。
这个就是 WebSocket的核心了,告诉 Apache、 Nginx等服务器:注意啦,我发起的请求要用 WebSocket协议,快点帮我找到对应的助理处理~而不是那个老土的 HTTP。
这里开始就是 HTTP最后负责的区域了,告诉客户,我已经成功切换协议啦~
依然是固定的,告诉客户端即将升级的是 WebSocket协议,而不是 mozillasocket,lurnarsocket或者 shitsocket。
然后, Sec-WebSocket-Accept这个则是经过服务器确认,并且加密过后的 Sec-WebSocket-Key。服务器:好啦好啦,知道啦,给你看我的 ID CARD来证明行了吧。后面的, Sec-WebSocket-Protocol则是表示最终使用的协议。至此,HTTP已经完成它所有工作了,接下来就是完全按照 WebSocket协议进行了。总结, WebSocket连接的过程是:
优点:
缺点:
心跳就是客户端定时的给服务端发送消息,证明客户端是在线的,如果超过一定的时间没有发送则就是离线了。
当客户端第一次发送请求至服务端时会携带唯一标识、以及时间戳,服务端到db或者缓存去查询改请求的唯一标识,如果不存在就存入db或者缓存中,第二次客户端定时再次发送请求依旧携带唯一标识、以及时间戳,服务端到db或者缓存去查询改请求的唯一标识,如果存在就把上次的时间戳拿取出来,使用当前时间戳减去上次的时间,得出的毫秒秒数判断是否大于指定的时间,若小于的话就是在线,否则就是离线;
通过查阅资料了解到 nginx代理的 websocket转发,无消息连接会出现超时断开问题。网上资料提到解决方案两种,一种是修改nginx配置信息,第二种是 websocket发送心跳包。下面就来总结一下本次项目实践中解决的 websocket的断线和重连这两个问题的解决方案。主动触发包括主动断开连接,客户端主动发送消息给后端
主动断开连接,根据需要使用,基本很少用到。
下面主要讲一下客户端也就是前端如何实现心跳包:
首先了解一下心跳包机制
跳包之所以叫心跳包是因为:它像心跳一样每隔固定时间发一次,以此来告诉服务器,这个客户端还活着。事实上这是为了保持长连接,至于这个包的内容,是没有什么特别规定的,不过一般都是很小的包,或者只包含包头的一个空包。
在 TCP的机制里面,本身是存在有心跳包的机制的,也就是 TCP的选项: SO_KEEPALIVE。系统默认是设置的2小时的心跳频率。但是它检查不到机器断电、网线拔出、防火墙这些断线。而且逻辑层处理断线可能也不是那么好处理。一般,如果只是用于保活还是可以的。
心跳包一般来说都是在逻辑层发送空的 echo包来实现的。下一个定时器,在一定时间间隔下发送一个空包给客户端,然后客户端反馈一个同样的空包回来,服务器如果在一定时间内收不到客户端发送过来的反馈包,那就只有认定说掉线了。
在长连接下,有可能很长一段时间都没有数据往来。理论上说,这个连接是一直保持连接的,但是实际情况中,如果中间节点出现什么故障是难以知道的。更要命的是,有的节点(防火墙)会自动把一定时间之内没有数据交互的连接给断掉。在这个时候,就需要我们的心跳包了,用于维持长连接,保活。
心跳检测步骤:
针对这种异常的中断解决方案就是处理重连,下面我们给出的重连方案是使用js库处理:引入 reconnecting-websocket.min.js,ws建立链接方法使用js库api方法:
断网监测支持使用js库: offline.min.js
以上方案,只是抛砖引玉,如果大家有更好的解决方案欢迎评论区分享交流。
WebSocket是为了在 web应用上进行双通道通信而产生的协议,相比于轮询HTTP请求的方式,WebSocket有节省服务器资源,效率高等优点。WebSocket中的掩码是为了防止早期版本中存在中间缓存污染攻击等问题而设置的,客户端向服务端发送数据需要掩码,服务端向客户端发送数据不需要掩码。WebSocket中 Sec-WebSocket-Key的生成算法是拼接服务端和客户端生成的字符串,进行SHA1哈希算法,再用base64编码。WebSocket协议握手是依靠 HTTP协议的,依靠于 HTTP响应101进行协议升级转换。
OK,本文到此结束,希望对大家有所帮助。