Spring boot Spring Boot RSocket在消息映射中发送消息
从教程代码开始,我试图编写一个服务器,在响应客户机之前将消息复制到第二个服务器 为了调试我的问题,我只尝试在服务器之间进行一次简单的乒乓交换。只有当第二台服务器响应pong消息时,第一台服务器才应回复客户端:Spring boot Spring Boot RSocket在消息映射中发送消息,spring-boot,rsocket,Spring Boot,Rsocket,从教程代码开始,我试图编写一个服务器,在响应客户机之前将消息复制到第二个服务器 为了调试我的问题,我只尝试在服务器之间进行一次简单的乒乓交换。只有当第二台服务器响应pong消息时,第一台服务器才应回复客户端: @MessageMapping("request-response") Mono<Message> requestResponse(final Message request) { // register a mono that will be co
@MessageMapping("request-response")
Mono<Message> requestResponse(final Message request) {
// register a mono that will be completed when replication to another server has happened
String uuid = UUID.randomUUID().toString();
Mono<Message> deferred = Mono.create(sink -> replicationNexus.registerRequest(uuid, sink));
// FIXME attempt to send a nested request-response message that will complete the outer message later
this.requesterMono.flatMap(requester -> requester.route("pong")
.data(uuid)
.retrieveMono(String.class))
.subscribeOn(Schedulers.elastic())
.subscribe( uuid2 -> replicationNexus.complete(uuid2, new Message(SERVER, RESPONSE)));
// return the deferred work that will be completed by the pong response
return deferred;
}
下面是一个简单的乒乓球逻辑:
@MessageMapping("pong")
public Mono<String> pong(String m) {
return Mono.just(m);
}
@MessageMapping(“pong”)
公共单声道乒乓(字符串m){
返回Mono.just(m);
}
下面是保存外部客户端响应状态的逻辑,该响应在另一台服务器响应时完成:
public class ReplicationNexus<T> {
final Map<String, MonoSink<T>> requests = new ConcurrentHashMap<>();
public void registerRequest(String v, MonoSink<T> sink) {
requests.put(v, sink);
}
public boolean complete(String uuid, T message) {
Optional<MonoSink<T>> sink = Optional.of(requests.get(uuid));
if( sink.isPresent() ){
sink.get().success(message);
}
return sink.isPresent();
}
}
公共类ReplicationNexus{
最终映射请求=新的ConcurrentHashMap();
公共无效寄存器请求(字符串v,单接收器){
请求。put(v,sink);
}
公共布尔完成(字符串uuid,T消息){
可选接收器=可选的.of(requests.get(uuid));
if(sink.isPresent()){
sink.get().success(消息);
}
返回sink.isPresent();
}
}
调试第二台服务器时,它从不运行pong方法。看起来第一台服务器实际上并没有发送内部请求消息
运行内部请求-响应交换以使用自动重新连接逻辑完成外部消息交换的正确方法是什么?不确定我是否遗漏了您问题的复杂性,但如果中间服务器只是像代理一样活动,我将从链接调用的最简单情况开始。我觉得我遗漏了这个问题的一些细微差别,所以让我们下一步继续讨论
@MessageMapping("runCommand")
suspend fun runCommandX(
request: CommandRequest,
): Mono<String> {
val uuid = UUID.randomUUID().toString()
return requesterMono
.flatMap { requester: RSocketRequester ->
requester.route("pong")
.data("TEST")
.retrieveMono(String::class.java)
}
.doOnSubscribe {
// register request with uuid
}
.doOnSuccess {
// register completion
}
.doOnError {
// register failure
}
}
@MessageMapping(“runCommand”)
暂停趣味runCommandX(
请求:CommandRequest,
):Mono{
val uuid=uuid.randomUUID().toString()
返回请求程序
.flatMap{请求者:RSocketRequester->
请求者路径(“pong”)
.数据(“测试”)
.retrieveMono(字符串::class.java)
}
doOnSubscribe先生{
//使用uuid注册请求
}
杜恩塞斯先生{
//注册完成
}
杜恩先生{
//寄存器故障
}
}
通常,如果您可以避免在典型的spring/reactive/rsocket代码中调用subscribe。您希望框架为您完成此任务。您的问题可能非常复杂,直接询问可能会更快得到答案。谢谢yuri,我将在下一步尝试。请允许我问一下,由于我不熟悉kotlin,“!!”会做什么?强制执行非空检查-抛出NPE或继续。否则你需要一个.b?.c?.D抱歉回来的延误。如果我在这里尝试你的方法,如果在flatMap中设置一个断点,doOnSubscribe,那么它们不会被调用。看起来mono flatmap很懒,没有人打电话给你?啊,是的,我没有让它着急。老实说,我几乎总是认为一个有副作用的单体在订阅之前可能是一个bug。它破坏了Rx语义IMHO。好的,我有一个很好的解决方案,包括卸载到应用程序线程来执行复制工作。我会把它贴在这里作为一个路标给其他人,然后按照你的建议在一些专门的论坛上跟进。谢谢
@MessageMapping("runCommand")
suspend fun runCommandX(
request: CommandRequest,
): Mono<String> {
val uuid = UUID.randomUUID().toString()
return requesterMono
.flatMap { requester: RSocketRequester ->
requester.route("pong")
.data("TEST")
.retrieveMono(String::class.java)
}
.doOnSubscribe {
// register request with uuid
}
.doOnSuccess {
// register completion
}
.doOnError {
// register failure
}
}