Spring Boot RSocketRequester deal with server restart

£可爱£侵袭症+ 提交于 2020-03-22 03:49:06

问题


I have a question about Springs RSocketRequester. I have a rsocket server and client. Client connects to this server and requests @MessageMapping endpoint. It works as expected.

But what if I restart the server. How to do automatic reconnect to rsocket server from client? Thanks

Server:

@Controller
class RSC {

    @MessageMapping("pong")
    public Mono<String> pong(String m) {
        return Mono.just("PONG " + m);
    }
}

Client:

@Bean
    public RSocketRequester rSocketRequester() {
        return RSocketRequester
                .builder()
                .connectTcp("localhost", 7000)
                .block();

    }

@RestController
class RST {

    @Autowired
    private RSocketRequester requester;

    @GetMapping(path = "/ping")
    public Mono<String> ping(){
        return this.requester
                .route("pong")
                .data("TEST")
                .retrieveMono(String.class)
                .doOnNext(System.out::println);
    }
}

回答1:


You could achieve it with resumable client. This client should react on RejectedResumeException and recreate itself.

Client:

@Component
class RSocketRequesterSupplier implements Supplier<RSocketRequester> {
    private static final AtomicReference<RSocketRequester> R_SOCKET_REQUESTER =
            new AtomicReference<>();

    @Autowired
    private RSocketRequester.Builder rSocketRequesterBuilder;

    @PostConstruct
    void init() {
        rSocketRequesterBuilder
                .rsocketFactory(rsocketFactory -> rsocketFactory
                        .errorConsumer(throwable -> {
                            if (throwable instanceof RejectedResumeException) {
                                init();
                            }
                        })
                        .resume()
                        // tune it for your requirements
                        .resumeStreamTimeout(Duration.ofSeconds(1))
                        .resumeStrategy(() -> new PeriodicResumeStrategy(
                                Duration.ofSeconds(1)))
                )
                .connectTcp("localhost", 7000)
                .retryBackoff(Integer.MAX_VALUE, Duration.ofSeconds(1))
                .subscribe(R_SOCKET_REQUESTER::set);
    }

    @Override
    public RSocketRequester get() {
        return R_SOCKET_REQUESTER.get();
    }
}
@RestController
public class RST {
    @Autowired
    private RSocketRequesterSupplier rSocketRequesterSupplier;

    @GetMapping(path = "/ping")
    public Mono<String> ping() {
        return rSocketRequesterSupplier.get()
                .route("pong")
                .data("TEST")
                .retrieveMono(String.class)
                .doOnNext(System.out::println);
    }
}

Server:

@Bean
ServerRSocketFactoryProcessor serverRSocketFactoryProcessor() {
    return RSocketFactory.ServerRSocketFactory::resume;
}



回答2:


I don't think I would create a RSocketRequester bean in an application. Unlike WebClient (which has a pool of reusable connections), the RSocket requester wraps a single RSocket, i.e. a single network connection.

I think it's best to store a Mono<RSocketRequester> and subscribe to that to get an actual requester when needed. Because you don't want to create a new connection for each call, you can cache the result. Thanks to Mono retryXYZ operators, there are many ways you can refine the reconnection behavior.

You could try something like the following:

@Service
public class RSocketPingService {

    private final Mono<RSocketRequester> requesterMono;

    // Spring Boot is creating an auto-configured RSocketRequester.Builder bean
    public RSocketPingService(RSocketRequester.Builder builder) {
        this.requesterMono = builder
                .dataMimeType(MediaType.APPLICATION_CBOR)
                .connectTcp("localhost", 7000).retry(5).cache();
    }

    public Mono<String> ping() {
        return this.requesterMono.flatMap(requester -> requester.route("pong")
                .data("TEST")
                .retrieveMono(String.class));
    }


}


来源:https://stackoverflow.com/questions/58828736/spring-boot-rsocketrequester-deal-with-server-restart

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!