Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typo3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用带有Rsocket和Spring Webflux的WebSocket仅向特定客户端发送消息_Websocket_Reactive Programming_Spring Webflux_Rsocket - Fatal编程技术网

使用带有Rsocket和Spring Webflux的WebSocket仅向特定客户端发送消息

使用带有Rsocket和Spring Webflux的WebSocket仅向特定客户端发送消息,websocket,reactive-programming,spring-webflux,rsocket,Websocket,Reactive Programming,Spring Webflux,Rsocket,我正在我的一个POC项目中尝试将Rsocket与websocket结合使用。在我的情况下,不需要用户登录。当我收到来自其他服务的消息时,我只想向某些客户发送消息。基本上,我的流程是这样的 Service A Service B |--------| websocket |------------------| Queue based comm

我正在我的一个POC项目中尝试将Rsocket与websocket结合使用。在我的情况下,不需要用户登录。当我收到来自其他服务的消息时,我只想向某些客户发送消息。基本上,我的流程是这样的

                                  Service A                               Service B   
|--------|    websocket     |------------------|   Queue based comm   |---------------| 
|  Web   |----------------->| Rsocket server   |--------------------->| Another       | 
|        |<-----------------| using Websocket  |<---------------------| service       |
|--------|    websocket     |------------------|   Queue based comm   |---------------|
服务A服务B
|--------|websocket |--------------------基于队列的通信|-------------------
|Web--------------------------->Rsocket服务器--------------------------------------------------------->另一个

||我个人还没有将RSocket与WebSocket传输一起使用,但正如RSocket规范中所述,底层传输协议甚至不应该很重要

一个RSocket组件同时是服务器和客户端。因此,当浏览器连接到RSocket“服务器”时,您可以插入
RSocketRequester
实例,然后使用该实例向“客户端”发送消息

然后,您可以将这些实例添加到本地缓存中(例如,使用您选择的键将它们放入一些全局可用的
ConcurrentHashMap
——您将知道/能够计算来自服务B的消息应该传播到哪些客户端)


然后,在从服务B接收消息的代码中,只需从本地缓存中获取符合您的条件的所有
RSocketRequester
实例并向它们发送消息。

基本上,我认为您有两个选择。第一个是过滤来自
服务B
的流量,第二个是使用@NikolaB所述的
RSocketRequester
Map

第一个选项:

数据类新闻(val类别:String,val新闻:String)
数据类PrivateNews(val目的地:字符串,val新闻:新闻)
类新闻提供者{
专用val持续时间:长=250
private val externalNewsProcessor=DirectProcessor.create().serialize()
private val sink=externalNewsProcessor.sink()
fun allNews():Flux{
回流通量
.合并(
carNews()、bikeNews()、cosmeticsNews()、,
外部新闻处理器)
.延迟要素(持续时间(百万)
}
有趣的外部新闻():Flux{
返回外部新闻处理器;
}
有趣的附加外部新闻(新闻:新闻){
下沉。下一个(新闻);
}
有趣的卡纽斯():通量{
回流通量
.只是(“新款兰博!!”、“惊人的法拉利!”、“伟大的保时捷”、“非常酷的奥迪RS4前卫”、“特斯拉i比你聪明”)
.map{News(“CAR”,it)}
.延迟要素(持续时间(百万)
.log()
}
有趣的比基尼新闻():Flux{
回流通量
.just(“专业耐力赛仍然是最大的梦想”,“巨大的圣歌快如地狱”,“砾石长途测试”)
.map{News(“BIKE”,it)}
.延迟要素(持续时间(百万)
.log()
}
有趣的美容新闻():Flux{
回流通量
.只是(“nivea-没人想听这个”,“雷索纳除臭测试”)
.map{News(“化妆品”,it)}
.延迟要素(持续时间(百万)
.log()
}
}
@RestController
@请求映射(“/sse”)
@交叉原点(“*”)
类NewsRestController(){
private val log=LoggerFactory.getLogger(NewsRestController::class.java)
val newsProvider=newsProvider()
@GetMapping(value=[“/news/{category}]”,products=[MediaType.TEXT\u EVENT\u STREAM\u value])
fun allNewsByCategory(@PathVariable category:String):流量{
log.info(“您好,按类别获取所有新闻:{}!”,类别)
返回新闻提供者
.allNews()
.filter{it.category==category}
}
}
NewsProvider
类模拟了您的
服务B
,它应该返回
Flux
。无论何时调用
addExternalNews
它都将推送
allNews
方法返回的
News
。在
NewsRestController
类中,我们按类别过滤新闻。在
localhost:8080/sse/news/CAR
上打开浏览器,仅查看汽车新闻

如果要改用RSocket,可以使用如下方法:

@MessageMapping(“新闻{category}”)
fun allNewsByCategory(@DestinationVariable category:String):流量{
log.info(“RSocket,按类别获取所有新闻:{}!”,类别)
返回新闻提供者
.allNews()
.filter{it.category==category}
}
第二选项:

让我们使用
@ConnectMapping
RSocketRequester
存储在
HashMap
中(我使用vavr.io)

@控制器
类RSocketConnectionController{
private val log=LoggerFactory.getLogger(RSocketConnectionController::class.java)
private-var-requesterMap:Map=HashMap.empty()
@同步的
private fun getRequesterMap():映射{
返回请求器映射
}
@同步的
private fun addRequester(rSocketRequester:rSocketRequester,clientId:String){
info(“添加请求者{}”,clientId)
requesterMap=requesterMap.put(clientId,rSocketRequester)
}
@同步的
private fun removeRequester(客户端ID:String){
info(“删除请求者{}”,clientId)
requesterMap=requesterMap.remove(clientId)
}
@连接映射(“客户端id”)
趣味onConnect(rSocketRequester:rSocketRequester,客户端ID:String){
val clientIdFixed=clientId.replace(“\”,“”)//检查Serializer为什么要将“添加到字符串”
//rSocketRequester.rsocket().dispose()//拒绝连接
rSocketRequester
.rsocket()
.onClose()
.subscribe(null,null{