5
votes

comment configurer le délai d'inactivité de la connexion groupée dans reacteur-netty

Plus précisément, j'ai besoin de configurer le pool de connexion client http de reacteur-netty de manière à ce qu'il ferme automatiquement les connexions qui n'ont vu aucune activité dans le délai d'expiration configurable. Ces connexions sont ouvertes mais aucun octet n'a été transféré vers l'intérieur ou l'extérieur pendant un certain laps de temps (configurable).

Comment puis-je configurer le client http reactory-netty pour fermer les connexions inactives de manière préventive?


0 commentaires

4 Réponses :


1
votes

J'ai pu accomplir cela sur la branche 0.7.x en ajoutant des gestionnaires de temporisation d'écriture et de lecture netty au pipeline de canaux. Cependant, sur 0.8.x, cette approche ne fonctionne plus.

HttpClient httpClient = HttpClient
    .create((HttpClientOptions.Builder builder) -> builder
    .host(endpointUrl.getHost())
    .port(endpointUrl.getPort())
    .poolResources(PoolResources.fixed(connectionPoolName, maxConnections, timeoutPool))
    .afterChannelInit(channel -> {
        channel.pipeline()
                // The write and read timeouts are serving as generic socket idle state handlers.
                .addFirst("write_timeout", new WriteTimeoutHandler(timeoutIdle, TimeUnit.MILLISECONDS))
                .addFirst("read_timeout", new ReadTimeoutHandler(timeoutIdle, TimeUnit.MILLISECONDS));
    })
    .build());


1 commentaires

Merci pour votre réponse.



2
votes

J'ai réussi à configurer WebClient (via TcpClient sous-jacent) pour supprimer les connexions inactives à l'expiration du délai d'expiration du pool de connexions dans reacteur-netty 0.8.9

Ma solution est partiellement basée sur la documentation officielle sur IdleStateHandler étendu avec mes recherches sur la façon de l'appliquer correctement lors de la création d'une instance de HttpClient.

Voici comment j'ai fait cela:

public static WebClient createWebClient(final String baseUrl, final int idleTimeoutSec) {
    final TcpClient tcpClient = TcpClient.create(ConnectionProvider.fixed("fixed-pool"))
        .doOnConnected(conn -> {
            final ChannelPipeline pipeline = conn.channel().pipeline();
            if (pipeline.context("idleStateHandler") == null) {
                pipeline.addLast("idleStateHandler", new IdleStateHandler(0, 0, idleTimeoutSec))
                        .addLast("idleCleanupHandler", new IdleCleanupHandler());
            }
        });

    return WebClient.builder()
        .clientConnector(new ReactorClientHttpConnector(HttpClient.from(tcpClient)))
        .baseUrl(baseUrl)
        .build();
}

MISE À JOUR IMPORTANTE:

Mes tests ultérieurs ont indiqué que l'ajout de gestionnaires pendant le hook bootstrap distrait le pool et les sockets (les canaux) ne sont pas réutilisés par Connection.

La bonne façon d'ajouter les gestionnaires est:

public class IdleCleanupHandler extends ChannelDuplexHandler {
    @Override
    public void userEventTriggered(final ChannelHandlerContext ctx, final Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            final IdleState state = ((IdleStateEvent) evt).state();
            if (state == IdleState.ALL_IDLE) { // or READER_IDLE / WRITER_IDLE
                // close idling channel
                ctx.close();
            }
        } else {
            super.userEventTriggered(ctx, evt);
        }
    }
}

...

public static WebClient createWebClient(final String baseUrl, final int idleTimeoutSec) {
    final TcpClient tcpClient = TcpClient.create(ConnectionProvider.fixed("fixed-pool"))
        .bootstrap(bootstrap -> BootstrapHandlers.updateConfiguration(bootstrap, "idleTimeoutConfig",
            (connectionObserver, channel) -> {
                channel.pipeline()
                    .addLast("idleStateHandler", new IdleStateHandler(0, 0, idleTimeoutSec))
                    .addLast("idleCleanupHandler", new IdleCleanupHandler());
            }));

    return WebClient.builder()
        .clientConnector(new ReactorClientHttpConnector(HttpClient.from(tcpClient)))
        .baseUrl(baseUrl)
        .build();
}

Remarque: dans reacteur-netty 0.9.x il y aura un moyen standard de configurer le délai d'inactivité pour les connexions dans le pool de connexions, voir ce commit: https://github.com/reactor/reactor-netty/pull/792


0 commentaires

1
votes

Le moyen le plus simple de le faire dans reacteur-netty 0.9.x avec le client TCP est d'utiliser l'approche ci-dessous, je l'ai obtenu à partir du lien référencé par @ Vladimir-L. Configurez "maxIdleTime" pour votre question.

TcpClient timeoutClient = TcpClient.create(ConnectionProvider.fixed(onnectionPoolName, maxConnections, acquireTimeout,maxIdleTime));


0 commentaires

0
votes

Je suis actuellement à reacteur-netty 0.8.2 à cause de spring-boot-starter-webflux et j'ai rencontré le même problème, le pool de connexions a gardé les connexions ouvertes pendant 60 secondes après leur fin.

Avec cette approche, vous pouvez ne configurez pas le délai, mais vous pouvez le désactiver:

WebClient.builder()
    .clientConnector(new ReactorClientHttpConnector(
        HttpClient.from(TcpClient.create()).keepAlive(false)))
    .build()
    .get()
    .uri("someurl")
    .retrieve()
    .bodyToMono(String.class)


0 commentaires