Reactor Netty provides the easy-to-use and easy-to-configure
TcpClient
.
It hides most of the Netty functionality that is needed in order to create a TCP
client
and adds Reactive Streams backpressure.
To connect the TCP
client to a given endpoint, you must create and configure a
TcpClient
instance.
By default, the host
is localhost
and the port
is 12012
.
The following example shows how to create a TcpClient
:
link:./../../reactor-netty-examples/src/main/java/reactor/netty/examples/documentation/tcp/client/create/Application.java[role=include]
-
Creates a
TcpClient
instance that is ready for configuring. -
Connects the client in a blocking fashion and waits for it to finish initializing.
The returned Connection
offers a simple connection API, including disposeNow()
,
which shuts the client down in a blocking fashion.
To connect to a specific host
and port
, you can apply the following configuration to the TCP
client.
The following example shows how to do so:
link:./../../reactor-netty-examples/src/main/java/reactor/netty/examples/documentation/tcp/client/address/Application.java[role=include]
-
Configures the
TCP
host -
Configures the
TCP
port
By default, the initialization of the TcpClient
resources happens on demand. This means that the connect
operation
absorbs the extra time needed to initialize and load:
-
the event loop group
-
the host name resolver
-
the native transport libraries (when native transport is used)
-
the native libraries for the security (in case of
OpenSsl
)
When you need to preload these resources, you can configure the TcpClient
as follows:
link:./../../reactor-netty-examples/src/main/java/reactor/netty/examples/documentation/tcp/client/warmup/Application.java[role=include]
-
Initialize and load the event loop group, the host name resolver, the native transport libraries and the native libraries for the security
-
Host name resolution happens when connecting to the remote peer
To send data to a given endpoint, you must attach an I/O handler.
The I/O handler has access to NettyOutbound
to be able to write data.
link:./../../reactor-netty-examples/src/main/java/reactor/netty/examples/documentation/tcp/client/send/Application.java[role=include]
-
Sends
hello
string to the endpoint.
When you need more control over the writing process, as an alternative for I/O handler you may use
Connection#outbound
. As opposed to I/O handler
where the connection is closed when the provided Publisher
finishes (in case of finite Publisher
),
when using Connection#outbound
, you have to invoke explicitly
Connection#dispose
in order to close the connection.
link:./../../reactor-netty-examples/src/main/java/reactor/netty/examples/documentation/tcp/client/send/connection/Application.java[role=include]
-
Sends
hello 1
string to the endpoint. -
Sends
hello 2
string to the endpoint. -
Closes the connection once the message is sent to the endpoint.
To receive data from a given endpoint, you must attach an I/O handler.
The I/O handler has access to NettyInbound
to be able to read data. The following example shows how to do so:
link:./../../reactor-netty-examples/src/main/java/reactor/netty/examples/documentation/tcp/client/read/Application.java[role=include]
-
Receives data from a given endpoint
When you need more control over the reading process, as an alternative for I/O handler you may use
Connection#inbound
. As opposed to I/O handler
where the connection is closed when the provided Publisher
finishes (in case of finite Publisher
),
when using Connection#inbound
, you have to invoke explicitly
Connection#dispose
in order to close the connection.
link:./../../reactor-netty-examples/src/main/java/reactor/netty/examples/documentation/tcp/client/read/connection/Application.java[role=include]
-
Receives data from a given endpoint.
The following lifecycle callbacks are provided to let you extend the TcpClient
.
Callback | Description |
---|---|
|
Invoked after the remote address has been resolved successfully. |
|
Invoked when initializing the channel. |
|
Invoked when the channel is about to connect. |
|
Invoked after the channel has been connected. |
|
Invoked after the channel has been disconnected. |
|
Invoked when the remote address is about to be resolved. |
|
Invoked in case the remote address hasn’t been resolved successfully. |
The following example uses the doOnConnected
and doOnChannelInit
callbacks:
link:./../../reactor-netty-examples/src/main/java/reactor/netty/examples/documentation/tcp/client/lifecycle/Application.java[role=include]
-
Netty
pipeline is extended withReadTimeoutHandler
when the channel has been connected. -
Netty
pipeline is extended withLoggingHandler
when initializing the channel.
This section describes three kinds of configuration that you can use at the TCP level:
By default, the TCP
client is configured with the following options:
link:./../../reactor-netty-core/src/main/java/reactor/netty/tcp/TcpClientConnect.java[role=include]
If additional options are necessary or changes to the current options are needed, you can apply the following configuration:
link:./../../reactor-netty-examples/src/main/java/reactor/netty/examples/documentation/tcp/client/channeloptions/Application.java[role=include]
You can find more about Netty
channel options at the following links:
By default the TCP
client uses an “Event Loop Group”, where the number of the worker threads equals the number of
processors available to the runtime on initialization (but with a minimum value of 4). When you need a different configuration,
you can use one of the LoopResource#create
methods.
The following listing shows the default configuration for the Event Loop Group:
link:./../../reactor-netty-core/src/main/java/reactor/netty/ReactorNetty.java[role=include]
If you need changes to the these settings, you can apply the following configuration:
link:./../../reactor-netty-examples/src/main/java/reactor/netty/examples/documentation/tcp/client/eventloop/Application.java[role=include]
When you need SSL or TLS, you can apply the following configuration.
By default, if OpenSSL
is available, the
SslProvider.OPENSSL
provider is used as a provider. Otherwise, the provider is
SslProvider.JDK.
You can switch the provider by using
SslContextBuilder
or by setting -Dio.netty.handler.ssl.noOpenSsl=true
.
The following example uses SslContextBuilder
:
link:./../../reactor-netty-examples/src/main/java/reactor/netty/examples/documentation/tcp/client/security/Application.java[role=include]
By default, the TCP
client sends the remote host name as SNI
server name.
When you need to change this default setting, you can configure the TCP
client as follows:
link:./../../reactor-netty-examples/src/main/java/reactor/netty/examples/documentation/tcp/client/sni/Application.java[role=include]
The TCP client supports built-in integration with Micrometer
.
It exposes all metrics with a prefix of reactor.netty.tcp.client
.
The following table provides information for the TCP client metrics:
metric name | type | description |
---|---|---|
reactor.netty.tcp.client.data.received |
DistributionSummary |
Amount of the data received, in bytes. See [observability-metrics-data-received] |
reactor.netty.tcp.client.data.sent |
DistributionSummary |
Amount of the data sent, in bytes. See [observability-metrics-data-sent] |
reactor.netty.tcp.client.errors |
Counter |
Number of errors that occurred. See [observability-metrics-errors-count] |
reactor.netty.tcp.client.tls.handshake.time |
Timer |
Time spent for TLS handshake. See [observability-metrics-tls-handshake-time] |
reactor.netty.tcp.client.connect.time |
Timer |
Time spent for connecting to the remote address. See [observability-metrics-connect-time] |
reactor.netty.tcp.client.address.resolver |
Timer |
Time spent for resolving the address. See [observability-metrics-hostname-resolution-time] |
These additional metrics are also available:
The following example enables that integration:
link:./../../reactor-netty-examples/src/main/java/reactor/netty/examples/documentation/tcp/client/metrics/Application.java[role=include]
-
Enables the built-in integration with Micrometer
When TCP client metrics are needed for an integration with a system other than Micrometer
or you want
to provide your own integration with Micrometer
, you can provide your own metrics recorder, as follows:
link:./../../reactor-netty-examples/src/main/java/reactor/netty/examples/documentation/tcp/client/metrics/custom/Application.java[role=include]
-
Enables TCP client metrics and provides
ChannelMetricsRecorder
implementation.
The TCP
client supports Unix Domain Sockets (UDS) when native transport is in use.
The following example shows how to use UDS support:
link:./../../reactor-netty-examples/src/main/java/reactor/netty/examples/documentation/tcp/client/uds/Application.java[role=include]
-
Specifies
DomainSocketAddress
that will be used
By default, the TcpClient
uses Netty’s domain name lookup mechanism that resolves a domain name asynchronously.
This is as an alternative of the JVM’s built-in blocking resolver.
When you need to change the default settings, you can configure the TcpClient
as follows:
link:./../../reactor-netty-examples/src/main/java/reactor/netty/examples/documentation/tcp/client/resolver/Application.java[role=include]
-
The timeout of each DNS query performed by this resolver will be 500ms.
The following listing shows the available configurations:
Configuration name | Description |
---|---|
|
The max time to live of the cached DNS resource records (resolution: seconds).
If the time to live of the DNS resource record returned by the DNS server is greater
than this max time to live, this resolver ignores the time to live from
the DNS server and uses use this max time to live.
Default to |
|
The min time to live of the cached DNS resource records (resolution: seconds). If the time to live of the DNS resource record returned by the DNS server is less than this min time to live, this resolver ignores the time to live from the DNS server and uses this min time to live. Default: 0. |
|
The time to live of the cache for the failed DNS queries (resolution: seconds). Default: 0. |
|
When this setting is enabled, the resolver notifies as soon as all queries for the preferred address type are complete.
When this setting is disabled, the resolver notifies when all possible address types are complete.
This configuration is applicable for |
|
Disables the automatic inclusion of an optional record that tries to give a hint to the remote DNS server about how much data the resolver can read per response. By default, this setting is enabled. |
|
Specifies whether this resolver has to send a DNS query with the recursion desired (RD) flag set. By default, this setting is enabled. |
|
Sets a custom |
|
Sets the capacity of the datagram packet buffer (in bytes). Default: 4096. |
|
Sets the maximum allowed number of DNS queries to send when resolving a host name. Default: 16. |
|
Sets the number of dots that must appear in a name before an initial absolute query is made. Default: -1 (to determine the value from the OS on Unix or use a value of 1 otherwise). |
|
Sets the timeout of each DNS query performed by this resolver (resolution: milliseconds). Default: 5000. |
|
The list of the protocol families of the resolved address. |
|
The supplier of the local address to bind to. |
|
Enables an
|
|
Performs the communication with the DNS servers on the given
|
|
The list of search domains of the resolver. By default, the effective search domain list is populated by using the system DNS search domains. |
|
A specific logger and log level to be used by this resolver when generating detailed trace information in case of resolution failure. |
Sometimes, you may want to switch to the JVM built-in resolver. To do so, you can configure the TcpClient
as follows:
link:./../../reactor-netty-examples/src/main/java/reactor/netty/examples/documentation/tcp/client/resolver/custom/Application.java[role=include]
-
Sets the JVM built-in resolver.