Java 如何在RSocket服务器出现故障时恢复与RSocket的会话

Java 如何在RSocket服务器出现故障时恢复与RSocket的会话,java,spring-boot,rsocket,Java,Spring Boot,Rsocket,好的,我是RSocket的新手。我正在尝试创建一个简单的RSocket客户端和一个简单的RSocket服务器。根据我所做的研究,RSocket支持恢复: 它特别有用,因为当发送包含上一个接收帧信息的恢复帧时,客户端能够恢复连接,并且只请求尚未接收的数据,从而避免服务器上不必要的负载,避免在尝试检索已检索的数据时浪费时间 它还说,客户是负责恢复的人。我的问题是如何启用此恢复以及如何发送该恢复帧。我有功能正常的客户端和服务器,但是如果我关闭服务器并再次启动它,什么都不会发生,稍后当客户端再次尝试与它

好的,我是RSocket的新手。我正在尝试创建一个简单的RSocket客户端和一个简单的RSocket服务器。根据我所做的研究,RSocket支持恢复:

它特别有用,因为当发送包含上一个接收帧信息的恢复帧时,客户端能够恢复连接,并且只请求尚未接收的数据,从而避免服务器上不必要的负载,避免在尝试检索已检索的数据时浪费时间

它还说,客户是负责恢复的人。我的问题是如何启用此恢复以及如何发送该恢复帧。我有功能正常的客户端和服务器,但是如果我关闭服务器并再次启动它,什么都不会发生,稍后当客户端再次尝试与它抛出的服务器通信时:java.nio.channels.ClosedChannelException

这是我的客户端配置:

@Configuration
public class ClientConfiguration {

/**
 * Defining the RSocket client to use tcp transport on port 7000
 */
@Bean
public RSocket rSocket() {
    return RSocketFactory
            .connect()
            .resumeSessionDuration(Duration.ofDays(10))
            .mimeType(MimeTypeUtils.APPLICATION_JSON_VALUE, MimeTypeUtils.APPLICATION_JSON_VALUE)
            .frameDecoder(PayloadDecoder.ZERO_COPY)
            .transport(TcpClientTransport.create(7000))
            .start()
            .block();
}

/**
 * RSocketRequester bean which is a wrapper around RSocket
 * and it is used to communicate with the RSocket server
 */
@Bean
RSocketRequester rSocketRequester(RSocketStrategies rSocketStrategies) {
    return RSocketRequester.wrap(rSocket(), MimeTypeUtils.APPLICATION_JSON, MimeTypeUtils.APPLICATION_JSON, rSocketStrategies);
}
}

这是一个RestController,我从它开始与rsocket服务器通信:

@RestController
public class UserDataRestController {

private final RSocketRequester rSocketRequester;

public UserDataRestController(RSocketRequester.Builder rSocketRequester) {
    this.rSocketRequester = rSocketRequester.connectTcp("localhost", 7000).block();
}

@GetMapping(value = "/feed/{firstName}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Publisher<Person> feed(@PathVariable("firstName") String firstName) {
    return rSocketRequester
            .route("feedPersonData")
            .data(new PersonDataRequest(firstName))
            .retrieveFlux(Person.class);
}

}
@RestController
公共类UserDataRestController{
私人最终RSocketRequester RSocketRequester;
公共用户DataRestController(RSocketRequester.Builder RSocketRequester){
this.rSocketRequester=rSocketRequester.connectTcp(“localhost”,7000).block();
}
@GetMapping(value=“/feed/{firstName}”,products=MediaType.TEXT\u EVENT\u STREAM\u value)
公共发布者源(@PathVariable(“firstName”)字符串firstName){
返回rSocketRequester
.路线(“feedPersonData”)
.数据(新的个人数据请求(名字))
.检索流量(人.类);
}
}

由于会话存储在内存中,服务器重新启动后无法恢复。请参阅
io.rsocket.resume.SessionManager\sessions

但是,如果重新连接到同一台服务器,您仍然可以保护自己免受网络问题的影响。您不必发送简历框架,客户会为您发送

您应该配置服务器:

@Bean
ServerRSocketFactoryProcessor serverRSocketFactoryProcessor() {
    return RSocketFactory.ServerRSocketFactory::resume;
}
客户端
io.rsocket.RSocketFactory.ClientRSocketFactory#resume


您可以找到几乎完整的示例,@Alexander Pankin提供的代码现在已被弃用。我使用此代码在服务器上配置resume one:

@Bean
RSocketServerCustomizer rSocketResume(){
简历=
新简历()
.会期(15分钟)
.重试(
Retry.fixedDelay(Long.MAX_值,持续时间秒(5))
.dobeforetry(s->log.debug(“已断开连接。正在尝试恢复…”);
返回rSocketServer->rSocketServer.resume(resume);
}

这很有效!非常感谢。即使在服务器重新启动后,客户端也能够与服务器通信。我认为重试仅适用于客户端。