hivemq-mqtt-client icon indicating copy to clipboard operation
hivemq-mqtt-client copied to clipboard

Need to have API to override socket keepalive settings

Open JavaSaBr opened this issue 5 years ago • 5 comments

Problem or use case

In some case we need to have a possibility to setup our custom TCP keepalive settings for this client, but your code, which initializes a socket is static and I cannot modify it at all without re-building your client.

@Provides
static @NotNull Bootstrap provideBootstrap(
            final @NotNull NettyEventLoopProvider nettyEventLoopProvider,
            final @NotNull MqttChannelInitializer channelInitializer) {

        return new Bootstrap().channelFactory(nettyEventLoopProvider.getChannelFactory())
                .option(ChannelOption.SO_KEEPALIVE, true)
                .option(ChannelOption.TCP_NODELAY, true)
                .option(ChannelOption.ALLOCATOR, ByteBufAllocator.DEFAULT)
                .handler(channelInitializer);
    }

Preferred solution or suggestions

You can add some additional config or system properties to override default OS values using this code:

clientBootstrap.option(ChannelOption.SO_KEEPALIVE, true);
clientBootstrap.option(NioChannelOption.of(ExtendedSocketOptions.TCP_KEEPIDLE), keepaliveTime);
clientBootstrap.option(NioChannelOption.of(ExtendedSocketOptions.TCP_KEEPCOUNT), keepaliveProbes);
clientBootstrap.option(NioChannelOption.of(ExtendedSocketOptions.TCP_KEEPINTERVAL), keepaliveInterval);

JavaSaBr avatar Dec 16 '19 12:12 JavaSaBr

Hi @JavaSaBr Thank you for your feature request. This is definitely something we could add to the config. What would be the best way to specify the channel options? Exposing netty related classes in the API is not the best idea imho. What are your thoughts on this?

SgtSilvio avatar Dec 16 '19 17:12 SgtSilvio

Hi @SgtSilvio ,

Thanks for the quick response.

I think it should be on the client configuration level during building like:

MqttClient.builder()
            .identifier(clientId)
            .socketConfig()
            .keepAliveTime(60)
            .keepAliveInterval(20)
            .keepAliveProbes(3)
            .applySocketConfig()
            .useMqttVersion5()
            .build()
            .toAsync()

JavaSaBr avatar Dec 16 '19 17:12 JavaSaBr

I think we should allow setting socket options in a more generic way. Directly using keepAlive settings can be confused with the MQTT keep alive.

something like:

MqttClient.builder()
        .transportConfig()
            .socketOptions(Map.of("TCP_KEEPIDLE", 60, "TCP_KEEPINTERVAL", 20))
            .applyTransportConfig()
        ...

SgtSilvio avatar Dec 19 '19 14:12 SgtSilvio

I think it's a good option for me as well.

JavaSaBr avatar Dec 19 '19 14:12 JavaSaBr

This is a great feature request and a much anticipated feature !

On one side considering i.e. the AWS NLB with its 350 second TCP idle timeout (https://docs.aws.amazon.com/elasticloadbalancing/latest/network/network-load-balancers.html#connection-idle-timeout) that cannot be changed, but by either doing traffic on the application layer or - as possible with this feature - use TCP keepalives. As a side note: This is also something that could / should be done on the MQTT broker side to not having to configure all the clients.

But also considering devices optimized for power consumption with a TCP stack that does maintain a TCP connection and the required keepalives without fully waking the whole application.

frittentheke avatar May 05 '20 07:05 frittentheke