1. About the Documentation

This section provides a brief overview of Reactor Netty reference documentation. You do not need to read this guide in a linear fashion. Each piece stands on its own, though they often refer to other pieces.

The Reactor Netty reference guide is available as HTML documents. The latest copy is available at https://projectreactor.io/docs/netty/release/reference/index.html

Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically.

1.2. Contributing to the Documentation

The reference guide is written in Asciidoc, and you can find its sources at https://github.com/reactor/reactor-netty/tree/1.1.x/docs/asciidoc.

If you have an improvement, we will be happy to get a pull request from you!

We recommend that you check out a local copy of the repository so that you can generate the documentation by using the asciidoctor Gradle task and checking the rendering. Some of the sections rely on included files, so GitHub rendering is not always complete.

To facilitate documentation edits, most sections have a link at the end that opens an edit UI directly on GitHub for the main source file for that section. These links are only present in the HTML5 version of this reference guide. They look like the following link: Suggest Edit to About the Documentation.

1.3. Getting Help

There are several ways to reach out for help with Reactor Netty. You can:

  • Get in touch with the community on Gitter.

  • Ask a question on stackoverflow.com at reactor-netty.

  • Report bugs in Github issues. The repository is the following: reactor-netty.

All of Reactor Netty is open source, including this documentation.

2. Getting Started

This section contains information that should help you get going with Reactor Netty. It includes the following information:

2.1. Introducing Reactor Netty

Suited for Microservices Architecture, Reactor Netty offers backpressure-ready network engines for HTTP (including Websockets), TCP, and UDP.

2.2. Prerequisites

Reactor Netty runs on Java 8 and above.

It has transitive dependencies on:

  • Reactive Streams v1.0.4

  • Reactor Core v3.x

  • Netty v4.1.x

2.3. Understanding the BOM and versioning scheme

Reactor Netty is part of the Project Reactor BOM (since the Aluminium release train). This curated list groups artifacts that are meant to work well together, providing the relevant versions despite potentially divergent versioning schemes in these artifacts.

The versioning scheme has changed between 0.9.x and 1.0.x (Dysprosium and Europium).

Artifacts follow a versioning scheme of MAJOR.MINOR.PATCH-QUALIFIER while the BOM is versioned using a CalVer inspired scheme of YYYY.MINOR.PATCH-QUALIFIER, where:

  • MAJOR is the current generation of Reactor, where each new generation can bring fundamental changes to the structure of the project (which might imply a more significant migration effort)

  • YYYY is the year of the first GA release in a given release cycle (like 1.0.0 for 1.0.x)

  • .MINOR is a 0-based number incrementing with each new release cycle

    • in the case of projects, it generally reflects wider changes and can indicate a moderate migration effort

    • in the case of the BOM it allows discerning between release cycles in case two get first released the same year

  • .PATCH is a 0-based number incrementing with each service release

  • -QUALIFIER is a textual qualifier, which is omitted in the case of GA releases (see below)

The first release cycle to follow that convention is thus 2020.0.x, codename Europium. The scheme uses the following qualifiers (note the use of dash separator), in order:

  • -M1..-M9: milestones (we don’t expect more than 9 per service release)

  • -RC1..-RC9: release candidates (we don’t expect more than 9 per service release)

  • -SNAPSHOT: snapshots

  • no qualifier for GA releases

Snapshots appear higher in the order above because, conceptually, they’re always "the freshest pre-release" of any given PATCH. Even though the first deployed artifact of a PATCH cycle will always be a -SNAPSHOT, a similarly named but more up-to-date snapshot would also get released after eg. a milestone or between release candidates.

Each release cycle is also given a codename, in continuity with the previous codename-based scheme, which can be used to reference it more informally (like in discussions, blog posts, etc…​). The codenames represent what would traditionally be the MAJOR.MINOR number. They (mostly) come from the Periodic Table of Elements, in increasing alphabetical order.

Up until Dysprosium, the BOM was versioned using a release train scheme with a codename followed by a qualifier, and the qualifiers were slightly different. For example: Aluminium-RELEASE (first GA release, would now be something like YYYY.0.0), Bismuth-M1, Californium-SR1 (service release would now be something like YYYY.0.1), Dysprosium-RC1, Dysprosium-BUILD-SNAPSHOT (after each patch, we’d go back to the same snapshot version. would now be something like YYYY.0.X-SNAPSHOT so we get 1 snapshot per PATCH)

2.4. Getting Reactor Netty

As mentioned earlier, the easiest way to use Reactor Netty in your core is to use the BOM and add the relevant dependencies to your project. Note that, when adding such a dependency, you must omit the version so that the version gets picked up from the BOM.

However, if you want to force the use of a specific artifact’s version, you can specify it when adding your dependency as you usually would. You can also forego the BOM entirely and specify dependencies by their artifact versions.

2.4.1. Maven Installation

The BOM concept is natively supported by Maven. First, you need to import the BOM by adding the following snippet to your pom.xml. If the top section (dependencyManagement) already exists in your pom, add only the contents.

<dependencyManagement> (1)
    <dependencies>
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-bom</artifactId>
            <version>2022.0.22</version> (2)
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
1 Notice the dependencyManagement tag. This is in addition to the regular dependencies section.
2 As of this writing, 2022.0.22 is the latest version of the BOM. Check for updates at https://github.com/reactor/reactor/releases.

Next, add your dependencies to the relevant reactor projects, as usual (except without a <version>). The following listing shows how to do so:

<dependencies>
    <dependency>
        <groupId>io.projectreactor.netty</groupId>
        <artifactId>reactor-netty-core</artifactId> (1)
        (2)
    </dependency>
</dependencies>
<dependencies>
    <dependency>
        <groupId>io.projectreactor.netty</groupId>
        <artifactId>reactor-netty-http</artifactId>
    </dependency>
</dependencies>
1 Dependency on Reactor Netty
2 No version tag here

2.4.2. Gradle Installation

The BOM concept is supported in Gradle since version 5. The following listing shows how to import the BOM and add a dependency to Reactor Netty:

dependencies {
    // import a BOM
    implementation platform('io.projectreactor:reactor-bom:2022.0.22') (1)

    // define dependencies without versions
    implementation 'io.projectreactor.netty:reactor-netty-core' (2)
    implementation 'io.projectreactor.netty:reactor-netty-http'
}
1 As of this writing, 2022.0.22 is the latest version of the BOM. Check for updates at https://github.com/reactor/reactor/releases.
2 There is no third : separated section for the version. It is taken from the BOM.

2.4.3. Milestones and Snapshots

Milestones and developer previews are distributed through the Spring Milestones repository rather than Maven Central. To add it to your build configuration file, use the following snippet:

Milestones in Maven
<repositories>
	<repository>
		<id>spring-milestones</id>
		<name>Spring Milestones Repository</name>
		<url>https://repo.spring.io/milestone</url>
	</repository>
</repositories>

For Gradle, use the following snippet:

Milestones in Gradle
repositories {
  maven { url 'https://repo.spring.io/milestone' }
  mavenCentral()
}

Similarly, snapshots are also available in a separate dedicated repository (for both Maven and Gradle):

-SNAPSHOTs in Maven
<repositories>
	<repository>
		<id>spring-snapshots</id>
		<name>Spring Snapshot Repository</name>
		<url>https://repo.spring.io/snapshot</url>
	</repository>
</repositories>
-SNAPSHOTs in Gradle
repositories {
  maven { url 'https://repo.spring.io/snapshot' }
  mavenCentral()
}

2.5. Support and policies

2.5.1. Do you have a question?

Search Stack Overflow first; discuss if necessary

If you’re unsure why something isn’t working or wondering if there is a better way of doing it please check on Stack Overflow first and if necessary start a discussion. Use relevant tags among the ones we monitor for that purpose:

If you prefer real-time discussion, we also have a few Gitter channels:

  • reactor is the historic most active one, where most of the community can help

  • reactor-core is intended for more advanced pinpointed discussions around the inner workings of the library

  • reactor-netty is intended for netty-specific questions

Refer to each project’s README for potential other sources of information.

We generally discourage opening GitHub issues for questions, in favor of the two channels above.

2.5.2. Our policy on deprecations

When dealing with deprecations, given a version A.B.C, we’ll ensure that:

  • deprecations introduced in version A.B.0 will be removed no sooner than version A.B+1.0

  • deprecations introduced in version A.B.1+ will be removed no sooner than version A.B+2.0

  • we’ll strive to mention the following in the deprecation javadoc:

    • target minimum version for removal

    • pointers to replacements for the deprecated method

    • version in which method was deprecated

This policy is officially in effect as of January 2021, for all modules in 2020.0 BOMs and newer release trains, as well as Dysprosium releases after Dysprosium-SR15.
Deprecation removal targets are not a hard commitment, and the deprecated methods could live on further than these minimum target GA versions (ie. only the most problematic deprecated methods will be removed aggressively).
That said, deprecated code that has outlived its minimum removal target version may be removed in any subsequent release (including patch releases, aka service releases) without further notice. So users should still strive to update their code as early as possible.

2.5.3. Support Timeline

Our GA release cadence is annual. The next release train is 2025. The timeline is subject to change.

The following table summarises the support dates for each individual project followed by the BOM support.

Version Initial OSS Release OSS Support End Commercial Support (*) End Published in BOM

reactor-core

3.7

2024-11-12

2026-08-31

2027-12-31

2024

3.6

2023-11-14

2025-08-31

2026-12-31

2023

3.5

2022-11-08

2024-08-31

2025-12-31

2022

3.4

2020-10-26

2024-08-31

2026-12-31

2020

reactor-netty

1.2

2024-11-12

2026-08-31

2027-12-31

2024

1.1

2022-11-08

2025-08-31

2026-12-31

2022, 2023

1.0

2020-10-26

2024-08-31

2026-12-31

2020

reactor-kafka

1.3

2020-10-26

2026-08-31

2027-12-31

2020, 2022, 2023, 2024

reactor-pool

1.1

2024-11-12

2026-08-31

2027-12-31

2024

1.0

2022-11-08

2025-08-31

2026-12-31

2022, 2023

0.2

2020-10-26

2024-08-31

2026-12-31

2020

reactor-addons

3.5

2022-11-08

2026-08-31

2027-12-31

2022, 2023, 2024

3.4

2020-10-26

2024-08-31

2026-12-31

2020

reactor-kotlin-extensions

1.2

2022-11-08

2026-08-31

2027-12-31

2022, 2023, 2024

1.1

2020-10-26

2024-08-31

2026-12-31

2020

reactor-rabbitmq

1.5

2020-10-26

2024-08-31

2026-12-31

2020

reactor-bom

2024

2024-11-12

2026-08-31

2027-12-31

:leveloffset: 1

:leveloffset!: Suggest Edit to "Getting Started"

:leveloffset: 1

:sourcedir: ./../../reactor-netty-core/src/main/java :examplesdir: ./../../reactor-netty-examples/src/main/java/reactor/netty/examples/documentation/tcp/server :javadoc: https://projectreactor.io/docs/netty/1.1.25-SNAPSHOT/api :nettyjavadoc: https://netty.io/4.1/api :wirelogger: reactor.netty.tcp.TcpServer

= TCP Server

Reactor Netty provides an easy to use and configure {javadoc}/reactor/netty/tcp/TcpServer.html[TcpServer]. It hides most of the Netty functionality that is needed to create a TCP server and adds Reactive Streams backpressure.

== Starting and Stopping

To start a TCP server, you must create and configure a {javadoc}/reactor/netty/tcp/TcpServer.html[TcpServer] instance. By default, the host is configured for any local address, and the system picks up an ephemeral port when the bind operation is invoked. The following example shows how to create and configure a TcpServer instance:

==== [source,java,indent=0] .{examplesdir}/create/Application.java ---- Unresolved directive in tcp-server.adoc - include::{examplesdir}/create/Application.java[lines=18..31] ---- <1> Creates a {javadoc}/reactor/netty/tcp/TcpServer.html[TcpServer] instance that is ready for configuring. <2> Starts the server in a blocking fashion and waits for it to finish initializing. ====

The returned {javadoc}/reactor/netty/DisposableServer.html[DisposableServer] offers a simple server API, including {javadoc}/reactor/netty/DisposableChannel.html#disposeNow-java.time.Duration-[disposeNow()], which shuts the server down in a blocking fashion.

=== Host and Port

To serve on a specific host and port, you can apply the following configuration to the TCP server:

==== [source,java,indent=0] .{examplesdir}/address/Application.java ---- Unresolved directive in tcp-server.adoc - include::{examplesdir}/address/Application.java[lines=18..33] ---- <1> Configures the TCP server host <2> Configures the TCP server port ====

To serve on multiple addresses, after having configured the TcpServer you can bind it multiple times to obtain separate DisposableServer`s. All created servers will share resources such as `LoopResources because they use the same configuration instance under the hood.

==== [source,java,indent=0] .{examplesdir}/address/MultiAddressApplication.java ---- Unresolved directive in tcp-server.adoc - include::{examplesdir}/address/MultiAddressApplication.java[lines=18..41] ---- <1> Configures the first TCP server host <2> Configures the first TCP server port <3> Configures the second TCP server host <4> Configures the second TCP server port ====

== Eager Initialization

By default, the initialization of the TcpServer resources happens on demand. This means that the bind operation absorbs the extra time needed to initialize and load:

* the event loop groups * 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 TcpServer as follows:

==== [source,java,indent=0] .{examplesdir}/warmup/Application.java ---- Unresolved directive in tcp-server.adoc - include::{examplesdir}/warmup/Application.java[lines=18..36] ---- <1> Initialize and load the event loop groups, the native transport libraries and the native libraries for the security ====

== Writing Data

In order to send data to a connected client, you must attach an I/O handler. The I/O handler has access to {javadoc}/reactor/netty/NettyOutbound.html[NettyOutbound] to be able to write data. The following example shows how to attach an I/O handler:

==== [source,java,indent=0] .{examplesdir}/send/Application.java ---- Unresolved directive in tcp-server.adoc - include::{examplesdir}/send/Application.java[lines=18..33] ---- <1> Sends hello string to the connected clients ====

== Consuming Data

In order to receive data from a connected client, you must attach an I/O handler. The I/O handler has access to {javadoc}/reactor/netty/NettyInbound.html[NettyInbound] to be able to read data. The following example shows how to use it:

==== [source,java,indent=0] .{examplesdir}/read/Application.java ---- Unresolved directive in tcp-server.adoc - include::{examplesdir}/read/Application.java[lines=18..32] ---- <1> Receives data from the connected clients ====

== Lifecycle Callbacks

The following lifecycle callbacks are provided to let you extend the TcpServer:

[width="100%",options="header"]

=======

Callback

Description

doOnBind

Invoked when the server channel is about to bind.

doOnBound

Invoked when the server channel is bound.

doOnChannelInit

Invoked when initializing the channel.

doOnConnection

Invoked when a remote client is connected

doOnUnbound

Invoked when the server channel is unbound.

=======

The following example uses the doOnConnection and doOnChannelInit callbacks:

==== [source,java,indent=0] .{examplesdir}/lifecycle/Application.java ---- Unresolved directive in tcp-server.adoc - include::{examplesdir}/lifecycle/Application.java[lines=18..39] ---- <1> Netty pipeline is extended with ReadTimeoutHandler when a remote client is connected. <2> Netty pipeline is extended with LoggingHandler when initializing the channel. ====

== TCP-level Configurations

This section describes three kinds of configuration that you can use at the TCP level:

* [server-tcp-level-configurations-channel-options] * [server-tcp-level-configurations-event-wire-logger] * [server-tcp-level-configurations-event-loop-group]

=== Setting Channel Options

By default, the TCP server is configured with the following options:

==== [source,java,indent=0] .{sourcedir}/reactor/netty/tcp/TcpServerBind.java ---- Unresolved directive in tcp-server.adoc - include::{sourcedir}/reactor/netty/tcp/TcpServerBind.java[lines=40..48] ---- ====

If additional options are necessary or changes to the current options are needed, you can apply the following configuration:

==== [source,java,indent=0] .{examplesdir}/channeloptions/Application.java ---- Unresolved directive in tcp-server.adoc - include::{examplesdir}/channeloptions/Application.java[lines=18..33] ---- ====

You can find more about Netty channel options at the following links:

* {nettyjavadoc}/io/netty/channel/ChannelOption.html[Common ChannelOption] * {nettyjavadoc}/io/netty/channel/epoll/EpollChannelOption.html[Epoll ChannelOption] * {nettyjavadoc}/io/netty/channel/kqueue/KQueueChannelOption.html[KQueue ChannelOption] * Socket Options

:formattersourcedir: ./../../reactor-netty-core/src/main/java

=== Wire Logger

Reactor Netty provides wire logging for when the traffic between the peers needs to be inspected. By default, wire logging is disabled. To enable it, you must set the logger {wirelogger} level to DEBUG and apply the following configuration:

==== [source,java,indent=0] .{examplesdir}/wiretap/Application.java ---- Unresolved directive in wire-logger.adoc - include::{examplesdir}/wiretap/Application.java[lines=18..35] ---- <1> Enables the wire logging ====

==== Wire Logger formatters Reactor Netty supports 3 different formatters:

- {javadoc}/reactor/netty/transport/logging/AdvancedByteBufFormat.html#HEX_DUMP[AdvancedByteBufFormat#HEX_DUMP] - the default

==== [source,java,indent=0] .{sourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java ---- Unresolved directive in wire-logger.adoc - include::{formattersourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java[lines=47..75] ---- ====

- {javadoc}/reactor/netty/transport/logging/AdvancedByteBufFormat.html#SIMPLE[AdvancedByteBufFormat#SIMPLE]

==== [source,java,indent=0] .{sourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java ---- Unresolved directive in wire-logger.adoc - include::{formattersourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java[lines=34..45] ---- ====

- {javadoc}/reactor/netty/transport/logging/AdvancedByteBufFormat.html#TEXTUAL[AdvancedByteBufFormat#TEXTUAL]

==== [source,java,indent=0] .{sourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java ---- Unresolved directive in wire-logger.adoc - include::{formattersourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java[lines=77..93] ---- ====

When you need to change the default formatter you can configure it as follows:

==== [source,java,indent=0] .{examplesdir}/wiretap/custom/Application.java ---- Unresolved directive in wire-logger.adoc - include::{examplesdir}/wiretap/custom/Application.java[lines=18..38] ---- <1> Enables the wire logging, {javadoc}/reactor/netty/transport/logging/AdvancedByteBufFormat.html#TEXTUAL[AdvancedByteBufFormat#TEXTUAL] is used for printing the content. ====

:eventloopsourcedir: ./../../reactor-netty-core/src/main/java

=== Event Loop Group

By default Reactor Netty 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). This “Event Loop Group” is shared between all servers and clients in one JVM. When you need a different configuration, you can use one of the {javadoc}/reactor/netty/resources/LoopResources.html[LoopResources]#create methods.

The following listing shows the default configuration for the Event Loop Group:

==== [source,java,indent=0] .{eventloopsourcedir}/reactor/netty/ReactorNetty.java ---- Unresolved directive in eventloop.adoc - include::{eventloopsourcedir}/reactor/netty/ReactorNetty.java[lines=87..121] ---- ====

If you need changes to these settings, you can apply the following configuration:

==== [source,java,indent=0] .{examplesdir}/eventloop/Application.java ---- Unresolved directive in eventloop.adoc - include::{examplesdir}/eventloop/Application.java[lines=18..38] ---- ====

==== Disposing Event Loop Group

- If you use the default Event Loop Group provided by Reactor Netty, invoke {javadoc}/reactor/netty/http/HttpResources.html[HttpResources]#disposeLoopsAndConnections/#disposeLoopsAndConnectionsLater method.

NOTE: Disposing HttpResources means that every server/client that is using it, will not be able to use it anymore!

- If you use custom LoopResources, invoke {javadoc}/reactor/netty/resources/LoopResources.html[LoopResources]#dispose/#disposeLater method.

NOTE: Disposing the custom LoopResources means that every server/client that is configured to use it, will not be able to use it anymore!

== SSL and TLS

When you need SSL or TLS, you can apply the configuration shown in the next listing. By default, if OpenSSL is available, {nettyjavadoc}/io/netty/handler/ssl/SslProvider.html#OPENSSL[SslProvider.OPENSSL] provider is used as a provider. Otherwise {nettyjavadoc}/io/netty/handler/ssl/SslProvider.html#JDK[SslProvider.JDK] is used. Switching the provider can be done through {nettyjavadoc}/io/netty/handler/ssl/SslContextBuilder.html#sslProvider-io.netty.handler.ssl.SslProvider-[SslContextBuilder] or by setting -Dio.netty.handler.ssl.noOpenSsl=true.

The following example uses SslContextBuilder:

==== [source,java,indent=0] .{examplesdir}/security/Application.java ---- Unresolved directive in tcp-server.adoc - include::{examplesdir}/security/Application.java[lines=18..40] ---- ====

=== Server Name Indication You can configure the TCP server with multiple SslContext mapped to a specific domain. An exact domain name or a domain name containing a wildcard can be used when configuring the SNI mapping.

The following example uses a domain name containing a wildcard:

==== [source,java,indent=0] .{examplesdir}/sni/Application.java ---- Unresolved directive in tcp-server.adoc - include::{examplesdir}/sni/Application.java[lines=18..47] ---- ====

== Metrics The TCP server supports built-in integration with Micrometer. It exposes all metrics with a prefix of reactor.netty.tcp.server.

The following table provides information for the TCP server metrics:

[width="100%",options="header"]

=======

metric name

type

description

reactor.netty.tcp.server.connections.total

Gauge

The number of all opened connections. See [observability-metrics-connections-total]

reactor.netty.tcp.server.data.received

DistributionSummary

Amount of the data received, in bytes. See [observability-metrics-data-received]

reactor.netty.tcp.server.data.sent

DistributionSummary

Amount of the data sent, in bytes. See [observability-metrics-data-sent]

reactor.netty.tcp.server.errors

Counter

Number of errors that occurred. See [observability-metrics-errors-count]

reactor.netty.tcp.server.tls.handshake.time

Timer

Time spent for TLS handshake. See [observability-metrics-tls-handshake-time]

=======

These additional metrics are also available:

ByteBufAllocator metrics

[width="100%",options="header"]

=======

metric name

type

description

reactor.netty.bytebuf.allocator.used.heap.memory

Gauge

The number of bytes reserved by heap buffer allocator. See [observability-metrics-used-heap-memory]

reactor.netty.bytebuf.allocator.used.direct.memory

Gauge

The number of bytes reserved by direct buffer allocator. See [observability-metrics-used-direct-memory]

reactor.netty.bytebuf.allocator.heap.arenas

Gauge

The number of heap arenas (when PooledByteBufAllocator). See [observability-metrics-heap-arenas]

reactor.netty.bytebuf.allocator.direct.arenas

Gauge

The number of direct arenas (when PooledByteBufAllocator). See [observability-metrics-direct-arenas]

reactor.netty.bytebuf.allocator.threadlocal.caches

Gauge

The number of thread local caches (when PooledByteBufAllocator). See [observability-metrics-thread-local-caches]

reactor.netty.bytebuf.allocator.small.cache.size

Gauge

The size of the small cache (when PooledByteBufAllocator). See [observability-metrics-small-cache-size]

reactor.netty.bytebuf.allocator.normal.cache.size

Gauge

The size of the normal cache (when PooledByteBufAllocator). See [observability-metrics-normal-cache-size]

reactor.netty.bytebuf.allocator.chunk.size

Gauge

The chunk size for an arena (when PooledByteBufAllocator). See [observability-metrics-chunk-size]

reactor.netty.bytebuf.allocator.active.heap.memory

Gauge

The actual bytes consumed by in-use buffers allocated from heap buffer pools (when PooledByteBufAllocator). See [observability-metrics-active-heap-memory]

reactor.netty.bytebuf.allocator.active.direct.memory

Gauge

The actual bytes consumed by in-use buffers allocated from direct buffer pools (when PooledByteBufAllocator). See [observability-metrics-active-direct-memory]

======= EventLoop metrics

[width="100%",options="header"]

=======

metric name

type

description

reactor.netty.eventloop.pending.tasks

Gauge

The number of tasks that are pending for processing on an event loop. See [observability-metrics-pending-tasks]

=======

The following example enables that integration:

==== [source,java,indent=0] .{examplesdir}/metrics/Application.java ---- Unresolved directive in tcp-server.adoc - include::{examplesdir}/metrics/Application.java[lines=18..32] ---- <1> Enables the built-in integration with Micrometer ====

When TCP server 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:

==== [source,java,indent=0] .{examplesdir}/metrics/custom/Application.java ---- Unresolved directive in tcp-server.adoc - include::{examplesdir}/metrics/custom/Application.java[lines=18..35] ---- <1> Enables TCP server metrics and provides {javadoc}/reactor/netty/channel/ChannelMetricsRecorder.html[ChannelMetricsRecorder] implementation. ====

== Tracing The TCP server supports built-in integration with Micrometer Tracing.

The following table provides information for the TCP server spans:

[width="100%",options="header"]

=======

contextual name

description

tls handshake

Information and time spent for TLS handshake. See [observability-spans-tls-handshake-span].

=======

The following example enables that integration. This concrete example uses Brave and reports the information to Zipkin. See the Micrometer Tracing documentation for OpenTelemetry setup.

==== [source,java,indent=0] .{examplesdir}/tracing/Application.java ---- Unresolved directive in tcp-server.adoc - include::{examplesdir}/tracing/Application.java[lines=18..81] ---- <1> Initializes Brave, Zipkin, and the Observation registry. <2> Enables the built-in integration with Micrometer. ====

The result in Zipkin looks like:

image::images/tcp-server-tracing.png[]

=== Access Current Observation Project Micrometer provides a library that assists with context propagation across different types of context mechanisms such as ThreadLocal, Reactor Context and others.

The following example shows how to use this library in a custom ChannelHandler:

==== [source,java,indent=0] .{examplesdir}/tracing/custom/Application.java ---- Unresolved directive in tcp-server.adoc - include::{examplesdir}/tracing/custom/Application.java[lines=18..86] ---- <1> Initializes Brave, Zipkin, and the Observation registry. <2> Enables the built-in integration with Micrometer. <3> Custom ChannelHandler that uses context propagation library. This concrete example overrides only ChannelInboundHandlerAdapter#channelActive, if it is needed, the same logic can be used for the rest of the methods. Also, this concrete example sets all ThreadLocal values for which there is a value in the given Channel, if another behaviour is needed please check context propagation library API. For example, you may want to set only some of the ThreadLocal values. ====

NOTE: When you enable Reactor Netty tracing within a framework, you may need to let Reactor Netty use the ObservationRegistry created by this framework. For this purpose you need to invoke {javadoc}/reactor/netty/Metrics.html#observationRegistry-io.micrometer.observation.ObservationRegistry-[reactor.netty.Metrics#observationRegistry]. You may also need to configure the Reactor Netty ObservationHandlers using the API provided by the framework.

== Unix Domain Sockets The TCP server supports Unix Domain Sockets (UDS) when native transport is in use.

The following example shows how to use UDS support:

==== [source,java,indent=0] .{examplesdir}/uds/Application.java ---- Unresolved directive in tcp-server.adoc - include::{examplesdir}/uds/Application.java[lines=18..33] ---- <1> Specifies DomainSocketAddress that will be used ====

:leveloffset: 3 Suggest Edit to "[tcp-server]"

:leveloffset: 1

:sourcedir: ./../../reactor-netty-core/src/main/java :examplesdir: ./../../reactor-netty-examples/src/main/java/reactor/netty/examples/documentation/tcp/client :javadoc: https://projectreactor.io/docs/netty/1.1.25-SNAPSHOT/api :nettyjavadoc: https://netty.io/4.1/api :wirelogger: reactor.netty.tcp.TcpClient

= TCP Client

Reactor Netty provides the easy-to-use and easy-to-configure {javadoc}/reactor/netty/tcp/TcpClient.html[TcpClient]. It hides most of the Netty functionality that is needed in order to create a TCP client and adds Reactive Streams backpressure.

== Connect and Disconnect

To connect the TCP client to a given endpoint, you must create and configure a {javadoc}/reactor/netty/tcp/TcpClient.html[TcpClient] instance. By default, the host is localhost and the port is 12012. The following example shows how to create a TcpClient:

==== [source,java,indent=0] .{examplesdir}/create/Application.java ---- Unresolved directive in tcp-client.adoc - include::{examplesdir}/create/Application.java[lines=18..31] ---- <1> Creates a {javadoc}/reactor/netty/tcp/TcpClient.html[TcpClient] instance that is ready for configuring. <2> Connects the client in a blocking fashion and waits for it to finish initializing. ====

The returned {javadoc}/reactor/netty/Connection.html[Connection] offers a simple connection API, including {javadoc}/reactor/netty/DisposableChannel.html#disposeNow-java.time.Duration-[disposeNow()], which shuts the client down in a blocking fashion.

=== Host and Port

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:

==== [source,java,indent=0] .{examplesdir}/address/Application.java ---- Unresolved directive in tcp-client.adoc - include::{examplesdir}/address/Application.java[lines=18..33] ---- <1> Configures the TCP host <2> Configures the TCP port ====

NOTE: The port can be specified also with PORT environment variable.

== Eager Initialization

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:

==== [source,java,indent=0] .{examplesdir}/warmup/Application.java ---- Unresolved directive in tcp-client.adoc - include::{examplesdir}/warmup/Application.java[lines=18..39] ---- <1> Initialize and load the event loop group, the host name resolver, the native transport libraries and the native libraries for the security <2> Host name resolution happens when connecting to the remote peer ====

== Writing Data

To send data to a given endpoint, you must attach an I/O handler. The I/O handler has access to {javadoc}/reactor/netty/NettyOutbound.html[NettyOutbound] to be able to write data.

==== [source,java,indent=0] .{examplesdir}/send/Application.java ---- Unresolved directive in tcp-client.adoc - include::{examplesdir}/send/Application.java[lines=18..35] ---- <1> 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 {javadoc}/reactor/netty/Connection.html#outbound--[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 {javadoc}/reactor/netty/Connection.html#outbound--[Connection#outbound], you have to invoke explicitly Connection#dispose in order to close the connection.

==== [source,java,indent=0] .{examplesdir}/send/connection/Application.java ---- Unresolved directive in tcp-client.adoc - include::{examplesdir}/send/connection/Application.java[lines=18..44] ---- <1> Sends hello 1 string to the endpoint. <2> Sends hello 2 string to the endpoint. <3> Closes the connection once the message is sent to the endpoint. ====

== Consuming Data

To receive data from a given endpoint, you must attach an I/O handler. The I/O handler has access to {javadoc}/reactor/netty/NettyInbound.html[NettyInbound] to be able to read data. The following example shows how to do so:

==== [source,java,indent=0] .{examplesdir}/read/Application.java ---- Unresolved directive in tcp-client.adoc - include::{examplesdir}/read/Application.java[lines=18..34] ---- <1> 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 {javadoc}/reactor/netty/Connection.html#inbound--[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 {javadoc}/reactor/netty/Connection.html#inbound--[Connection#inbound], you have to invoke explicitly Connection#dispose in order to close the connection.

==== [source,java,indent=0] .{examplesdir}/read/connection/Application.java ---- Unresolved directive in tcp-client.adoc - include::{examplesdir}/read/connection/Application.java[lines=18..38] ---- <1> Receives data from a given endpoint. ====

== Lifecycle Callbacks

The following lifecycle callbacks are provided to let you extend the TcpClient.

[width="100%",options="header"]

=======

Callback

Description

doAfterResolve

Invoked after the remote address has been resolved successfully.

doOnChannelInit

Invoked when initializing the channel.

doOnConnect

Invoked when the channel is about to connect.

doOnConnected

Invoked after the channel has been connected.

doOnDisconnected

Invoked after the channel has been disconnected.

doOnResolve

Invoked when the remote address is about to be resolved.

doOnResolveError

Invoked in case the remote address hasn’t been resolved successfully.

=======

The following example uses the doOnConnected and doOnChannelInit callbacks:

==== [source,java,indent=0] .{examplesdir}/lifecycle/Application.java ---- Unresolved directive in tcp-client.adoc - include::{examplesdir}/lifecycle/Application.java[lines=18..41] ---- <1> Netty pipeline is extended with ReadTimeoutHandler when the channel has been connected. <2> Netty pipeline is extended with LoggingHandler when initializing the channel. ====

== TCP-level Configurations

This section describes three kinds of configuration that you can use at the TCP level:

* [client-tcp-level-configurations-channel-options] * [client-tcp-level-configurations-event-wire-logger] * [client-tcp-level-configurations-event-loop-group]

=== Channel Options

By default, the TCP client is configured with the following options:

==== [source,java,indent=0] .{sourcedir}/reactor/netty/tcp/TcpClientConnect.java ---- Unresolved directive in tcp-client.adoc - include::{sourcedir}/reactor/netty/tcp/TcpClientConnect.java[lines=35..40] ---- ====

If additional options are necessary or changes to the current options are needed, you can apply the following configuration:

==== [source,java,indent=0] .{examplesdir}/channeloptions/Application.java ---- Unresolved directive in tcp-client.adoc - include::{examplesdir}/channeloptions/Application.java[lines=18..35] ---- ====

You can find more about Netty channel options at the following links:

* {nettyjavadoc}/io/netty/channel/ChannelOption.html[Common ChannelOption] * {nettyjavadoc}/io/netty/channel/epoll/EpollChannelOption.html[Epoll ChannelOption] * {nettyjavadoc}/io/netty/channel/kqueue/KQueueChannelOption.html[KQueue ChannelOption] * Socket Options

:formattersourcedir: ./../../reactor-netty-core/src/main/java

=== Wire Logger

Reactor Netty provides wire logging for when the traffic between the peers needs to be inspected. By default, wire logging is disabled. To enable it, you must set the logger {wirelogger} level to DEBUG and apply the following configuration:

==== [source,java,indent=0] .{examplesdir}/wiretap/Application.java ---- Unresolved directive in wire-logger.adoc - include::{examplesdir}/wiretap/Application.java[lines=18..35] ---- <1> Enables the wire logging ====

==== Wire Logger formatters Reactor Netty supports 3 different formatters:

- {javadoc}/reactor/netty/transport/logging/AdvancedByteBufFormat.html#HEX_DUMP[AdvancedByteBufFormat#HEX_DUMP] - the default

==== [source,java,indent=0] .{sourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java ---- Unresolved directive in wire-logger.adoc - include::{formattersourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java[lines=47..75] ---- ====

- {javadoc}/reactor/netty/transport/logging/AdvancedByteBufFormat.html#SIMPLE[AdvancedByteBufFormat#SIMPLE]

==== [source,java,indent=0] .{sourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java ---- Unresolved directive in wire-logger.adoc - include::{formattersourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java[lines=34..45] ---- ====

- {javadoc}/reactor/netty/transport/logging/AdvancedByteBufFormat.html#TEXTUAL[AdvancedByteBufFormat#TEXTUAL]

==== [source,java,indent=0] .{sourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java ---- Unresolved directive in wire-logger.adoc - include::{formattersourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java[lines=77..93] ---- ====

When you need to change the default formatter you can configure it as follows:

==== [source,java,indent=0] .{examplesdir}/wiretap/custom/Application.java ---- Unresolved directive in wire-logger.adoc - include::{examplesdir}/wiretap/custom/Application.java[lines=18..38] ---- <1> Enables the wire logging, {javadoc}/reactor/netty/transport/logging/AdvancedByteBufFormat.html#TEXTUAL[AdvancedByteBufFormat#TEXTUAL] is used for printing the content. ====

:eventloopsourcedir: ./../../reactor-netty-core/src/main/java

=== Event Loop Group

By default Reactor Netty 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). This “Event Loop Group” is shared between all servers and clients in one JVM. When you need a different configuration, you can use one of the {javadoc}/reactor/netty/resources/LoopResources.html[LoopResources]#create methods.

The following listing shows the default configuration for the Event Loop Group:

==== [source,java,indent=0] .{eventloopsourcedir}/reactor/netty/ReactorNetty.java ---- Unresolved directive in eventloop.adoc - include::{eventloopsourcedir}/reactor/netty/ReactorNetty.java[lines=87..121] ---- ====

If you need changes to these settings, you can apply the following configuration:

==== [source,java,indent=0] .{examplesdir}/eventloop/Application.java ---- Unresolved directive in eventloop.adoc - include::{examplesdir}/eventloop/Application.java[lines=18..38] ---- ====

==== Disposing Event Loop Group

- If you use the default Event Loop Group provided by Reactor Netty, invoke {javadoc}/reactor/netty/http/HttpResources.html[HttpResources]#disposeLoopsAndConnections/#disposeLoopsAndConnectionsLater method.

NOTE: Disposing HttpResources means that every server/client that is using it, will not be able to use it anymore!

- If you use custom LoopResources, invoke {javadoc}/reactor/netty/resources/LoopResources.html[LoopResources]#dispose/#disposeLater method.

NOTE: Disposing the custom LoopResources means that every server/client that is configured to use it, will not be able to use it anymore!

== Connection Pool By default, TcpClient (TcpClient.create()) uses a shared ConnectionProvider. This ConnectionProvider is configured to create a “fixed” connection pool per remote host (a remote host implies the combination of a hostname and its associated port number) with:

* 500 as the maximum number of active channels * 1000 as the maximum number of further channel acquisition attempts allowed to be kept in a pending state * The rest of the configurations are the defaults (check the system properties or the builder configurations below)

This means that the implementation creates a new channel if someone tries to acquire a channel as long as less than 500 have been created and are managed by the pool. When the maximum number of channels in the pool is reached, up to 1000 new attempts to acquire a channel are delayed (pending) until a channel is closed (and thus a slot is free and a new connection can be opened), and further attempts are declined with an error.

NOTE: Connections used by the TcpClient are never returned to the pool, but closed. When a connection is closed, a slot is freed in the pool and thus a new connection can be opened when needed. This behaviour is specific only for TcpClient and is intentional because only the user/framework knows if the actual protocol is compatible with reusing connections. (opposed to HttpClient where the protocol is known and Reactor Netty can return the connection to the pool when this is possible)

==== [source,java,indent=0] ../../../reactor-netty-core/src/main/java/reactor/netty/ReactorNetty.java ---- / * Default max connections. Fallback to * 2 * available number of processors (but with a minimum value of 16) */ public static final String POOL_MAX_CONNECTIONS = "reactor.netty.pool.maxConnections"; / * Default acquisition timeout (milliseconds) before error. If -1 will never wait to * acquire before opening a new * connection in an unbounded fashion. Fallback 45 seconds */ public static final String POOL_ACQUIRE_TIMEOUT = "reactor.netty.pool.acquireTimeout"; ---- ====

When you need to change the default settings, you can configure the ConnectionProvider as follows:

==== [source,java,indent=0] .{examplesdir}/pool/config/Application.java ---- Unresolved directive in tcp-client-conn-provider.adoc - include::{examplesdir}/pool/config/Application.java[lines=18..41] ---- <1> Configures the maximum time for the pending acquire operation to 60 seconds. ====

The following listing shows the available configurations: [width="100%",options="header"]

=======

Configuration name

Description

disposeInactivePoolsInBackground

When this option is enabled, connection pools are regularly checked in the background, and those that are empty and been inactive for a specified time become eligible for disposal. By default, this background disposal of inactive pools is disabled.

disposeTimeout

When ConnectionProvider#dispose() or ConnectionProvider#disposeLater() is called, trigger a graceful shutdown for the connection pools, with this grace period timeout. From there on, all calls for acquiring a connection will fail fast with an exception. However, for the provided Duration, pending acquires will get a chance to be served. Note: The rejection of new acquires and the grace timer start immediately, irrespective of subscription to the Mono returned by ConnectionProvider#disposeLater(). Subsequent calls return the same Mono, effectively getting notifications from the first graceful shutdown call and ignoring subsequently provided timeouts. By default, dispose timeout is not specified.

maxConnections

The maximum number of connections (per connection pool) before start pending. Default to 2 * available number of processors (but with a minimum value of 16).

metrics

Enables/disables built-in integration with Micrometer. ConnectionProvider.MeterRegistrar can be provided for integration with another metrics system. By default, metrics are not enabled.

pendingAcquireMaxCount

The maximum number of extra attempts at acquiring a connection to keep in a pending queue. If -1 is specified, the pending queue does not have upper limit. Default to 2 * max connections.

pendingAcquireTimeout

The maximum time before which a pending acquire must complete, or a TimeoutException is thrown (resolution: ms). If -1 is specified, no such timeout is applied. Default: 45 seconds.

=======

If you need to disable the connection pool, you can apply the following configuration:

==== [source,java,indent=0] .{examplesdir}/pool/Application.java ---- Unresolved directive in tcp-client-conn-provider.adoc - include::{examplesdir}/pool/Application.java[lines=18..35] ---- ====

=== Disposing Connection Pool

- If you use the default ConnectionProvider provided by Reactor Netty, invoke {javadoc}/reactor/netty/http/HttpResources.html[HttpResources]#disposeLoopsAndConnections/#disposeLoopsAndConnectionsLater method.

NOTE: Disposing HttpResources means that every client that is using it, will not be able to use it anymore!

- If you use custom ConnectionProvider, invoke {javadoc}/reactor/netty/resources/ConnectionProvider.html[ConnectionProvider]#dispose/#disposeLater/#disposeWhen method.

NOTE: Disposing the custom ConnectionProvider means that every client that is configured to use it, will not be able to use it anymore!

=== Metrics The pooled ConnectionProvider supports built-in integration with Micrometer. It exposes all metrics with a prefix of reactor.netty.connection.provider.

Pooled ConnectionProvider metrics

[width="100%",options="header"]

=======

metric name

type

description

reactor.netty.connection.provider.total.connections

Gauge

The number of all connections, active or idle. See [observability-metrics-total-connections]

reactor.netty.connection.provider.active.connections

Gauge

The number of the connections that have been successfully acquired and are in active use. See [observability-metrics-active-connections]

reactor.netty.connection.provider.max.connections

Gauge

The maximum number of active connections that are allowed. See [observability-metrics-max-connections]

reactor.netty.connection.provider.idle.connections

Gauge

The number of the idle connections. See [observability-metrics-idle-connections]

reactor.netty.connection.provider.pending.connections

Gauge

The number of requests that are waiting for a connection. See [observability-metrics-pending-connections]

reactor.netty.connection.provider.pending.connections.time

Timer

Time spent in pending acquire a connection from the connection pool. See [observability-metrics-pending-connections-time]

reactor.netty.connection.provider.max.pending.connections

Gauge

The maximum number of requests that will be queued while waiting for a ready connection. See [observability-metrics-max-pending-connections]

=======

The following example enables that integration:

==== [source,java,indent=0] .{examplesdir}/pool/metrics/Application.java ---- Unresolved directive in tcp-client-conn-provider.adoc - include::{examplesdir}/pool/metrics/Application.java[lines=18..45] ---- <1> Enables the built-in integration with Micrometer ====

== SSL and TLS

When you need SSL or TLS, you can apply the following configuration. By default, if OpenSSL is available, the {nettyjavadoc}/io/netty/handler/ssl/SslProvider.html#OPENSSL[SslProvider.OPENSSL] provider is used as a provider. Otherwise, the provider is {nettyjavadoc}/io/netty/handler/ssl/SslProvider.html#JDK[SslProvider.JDK]. You can switch the provider by using {nettyjavadoc}/io/netty/handler/ssl/SslContextBuilder.html#sslProvider-io.netty.handler.ssl.SslProvider-[SslContextBuilder] or by setting -Dio.netty.handler.ssl.noOpenSsl=true.

The following example uses SslContextBuilder:

==== [source,java,indent=0] .{examplesdir}/security/Application.java ---- Unresolved directive in tcp-client.adoc - include::{examplesdir}/security/Application.java[lines=18..37] ---- ====

=== Server Name Indication 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:

==== [source,java,indent=0] .{examplesdir}/sni/Application.java ---- Unresolved directive in tcp-client.adoc - include::{examplesdir}/sni/Application.java[lines=18..41] ---- ====

== Proxy Support

Reactor Netty supports the proxy functionality provided by Netty and provides a way to specify non proxy hosts through the {javadoc}/reactor/netty/tcp/ProxyProvider.html[ProxyProvider] builder.

Netty’s HTTP proxy support always uses CONNECT method in order to establish a tunnel to the specified proxy regardless of the scheme that is used http or https. (More information: Netty enforce HTTP proxy to support HTTP CONNECT method). Some proxies might not support CONNECT method when the scheme is http or might need to be configured in order to support this way of communication. Sometimes this might be the reason for not being able to connect to the proxy. Consider checking the proxy documentation whether it supports or needs an additional configuration in order to support CONNECT method.

The following example uses ProxyProvider:

==== [source,java,indent=0] .{examplesdir}/proxy/Application.java ---- Unresolved directive in proxy.adoc - include::{examplesdir}/proxy/Application.java[lines=18..42] ---- <1> Configures the connection establishment timeout to 20 seconds. ====

== Metrics 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:

[width="100%",options="header"]

=======

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:

Pooled ConnectionProvider metrics

[width="100%",options="header"]

=======

metric name

type

description

reactor.netty.connection.provider.total.connections

Gauge

The number of all connections, active or idle. See [observability-metrics-total-connections]

reactor.netty.connection.provider.active.connections

Gauge

The number of the connections that have been successfully acquired and are in active use. See [observability-metrics-active-connections]

reactor.netty.connection.provider.max.connections

Gauge

The maximum number of active connections that are allowed. See [observability-metrics-max-connections]

reactor.netty.connection.provider.idle.connections

Gauge

The number of the idle connections. See [observability-metrics-idle-connections]

reactor.netty.connection.provider.pending.connections

Gauge

The number of requests that are waiting for a connection. See [observability-metrics-pending-connections]

reactor.netty.connection.provider.pending.connections.time

Timer

Time spent in pending acquire a connection from the connection pool. See [observability-metrics-pending-connections-time]

reactor.netty.connection.provider.max.pending.connections

Gauge

The maximum number of requests that will be queued while waiting for a ready connection. See [observability-metrics-max-pending-connections]

=======

ByteBufAllocator metrics

[width="100%",options="header"]

=======

metric name

type

description

reactor.netty.bytebuf.allocator.used.heap.memory

Gauge

The number of bytes reserved by heap buffer allocator. See [observability-metrics-used-heap-memory]

reactor.netty.bytebuf.allocator.used.direct.memory

Gauge

The number of bytes reserved by direct buffer allocator. See [observability-metrics-used-direct-memory]

reactor.netty.bytebuf.allocator.heap.arenas

Gauge

The number of heap arenas (when PooledByteBufAllocator). See [observability-metrics-heap-arenas]

reactor.netty.bytebuf.allocator.direct.arenas

Gauge

The number of direct arenas (when PooledByteBufAllocator). See [observability-metrics-direct-arenas]

reactor.netty.bytebuf.allocator.threadlocal.caches

Gauge

The number of thread local caches (when PooledByteBufAllocator). See [observability-metrics-thread-local-caches]

reactor.netty.bytebuf.allocator.small.cache.size

Gauge

The size of the small cache (when PooledByteBufAllocator). See [observability-metrics-small-cache-size]

reactor.netty.bytebuf.allocator.normal.cache.size

Gauge

The size of the normal cache (when PooledByteBufAllocator). See [observability-metrics-normal-cache-size]

reactor.netty.bytebuf.allocator.chunk.size

Gauge

The chunk size for an arena (when PooledByteBufAllocator). See [observability-metrics-chunk-size]

reactor.netty.bytebuf.allocator.active.heap.memory

Gauge

The actual bytes consumed by in-use buffers allocated from heap buffer pools (when PooledByteBufAllocator). See [observability-metrics-active-heap-memory]

reactor.netty.bytebuf.allocator.active.direct.memory

Gauge

The actual bytes consumed by in-use buffers allocated from direct buffer pools (when PooledByteBufAllocator). See [observability-metrics-active-direct-memory]

======= EventLoop metrics

[width="100%",options="header"]

=======

metric name

type

description

reactor.netty.eventloop.pending.tasks

Gauge

The number of tasks that are pending for processing on an event loop. See [observability-metrics-pending-tasks]

=======

The following example enables that integration:

==== [source,java,indent=0] .{examplesdir}/metrics/Application.java ---- Unresolved directive in tcp-client.adoc - include::{examplesdir}/metrics/Application.java[lines=18..34] ---- <1> 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:

==== [source,java,indent=0] .{examplesdir}/metrics/custom/Application.java ---- Unresolved directive in tcp-client.adoc - include::{examplesdir}/metrics/custom/Application.java[lines=18..37] ---- <1> Enables TCP client metrics and provides {javadoc}/reactor/netty/channel/ChannelMetricsRecorder.html[ChannelMetricsRecorder] implementation. ====

== Tracing The TCP client supports built-in integration with Micrometer Tracing.

The following table provides information for the TCP client spans:

[width="100%",options="header"]

=======

contextual name

description

hostname resolution

Information and time spent for resolving the address. See [observability-spans-hostname-resolution-span].

connect

Information and time spent for connecting to the remote address. See [observability-spans-connect-span].

tls handshake

Information and time spent for TLS handshake. See [observability-spans-tls-handshake-span].

=======

The following example enables that integration. This concrete example uses Brave and reports the information to Zipkin. See the Micrometer Tracing documentation for OpenTelemetry setup.

==== [source,java,indent=0] .{examplesdir}/tracing/Application.java ---- Unresolved directive in tcp-client.adoc - include::{examplesdir}/tracing/Application.java[lines=18..81] ---- <1> Initializes Brave, Zipkin, and the Observation registry. <2> Enables the built-in integration with Micrometer. ====

The result in Zipkin looks like:

image::images/tcp-client-tracing.png[]

=== Access Current Observation Project Micrometer provides a library that assists with context propagation across different types of context mechanisms such as ThreadLocal, Reactor Context and others.

The following example shows how to use this library in a custom ChannelHandler:

==== [source,java,indent=0] .{examplesdir}/tracing/custom/Application.java ---- Unresolved directive in tcp-client.adoc - include::{examplesdir}/tracing/custom/Application.java[lines=18..80] ---- <1> Initializes Brave, Zipkin, and the Observation registry. <2> Enables the built-in integration with Micrometer. <3> Custom ChannelHandler that uses context propagation library. This concrete example overrides only ChannelOutboundHandlerAdapter#connect, if it is needed, the same logic can be used for the rest of the methods. Also, this concrete example sets all ThreadLocal values for which there is a value in the given Channel, if another behaviour is needed please check context propagation library API. For example, you may want to set only some of the ThreadLocal values. ====

NOTE: When you enable Reactor Netty tracing within a framework, you may need to let Reactor Netty use the ObservationRegistry created by this framework. For this purpose you need to invoke {javadoc}/reactor/netty/Metrics.html#observationRegistry-io.micrometer.observation.ObservationRegistry-[reactor.netty.Metrics#observationRegistry]. You may also need to configure the Reactor Netty ObservationHandlers using the API provided by the framework.

== Unix Domain Sockets The TCP client supports Unix Domain Sockets (UDS) when native transport is in use.

The following example shows how to use UDS support:

==== [source,java,indent=0] .{examplesdir}/uds/Application.java ---- Unresolved directive in tcp-client.adoc - include::{examplesdir}/uds/Application.java[lines=18..33] ---- <1> Specifies DomainSocketAddress that will be used ====

== Host Name Resolution 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:

==== [source,java,indent=0] .{examplesdir}/resolver/Application.java ---- Unresolved directive in tcp-client.adoc - include::{examplesdir}/resolver/Application.java[lines=18..36] ---- <1> The timeout of each DNS query performed by this resolver will be 500ms. ====

The following listing shows the available configurations. Additionally, TCP fallback is enabled by default.

[width="100%",options="header"]

=======

Configuration name

Description

bindAddressSupplier

The supplier of the local address to bind to.

cacheMaxTimeToLive

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 Integer.MAX_VALUE.

cacheMinTimeToLive

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.

cacheNegativeTimeToLive

The time to live of the cache for the failed DNS queries (resolution: seconds). Default: 0.

completeOncePreferredResolved

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 DnsNameResolver#resolveAll(String). By default, this setting is enabled.

disableOptionalRecord

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.

disableRecursionDesired

Specifies whether this resolver has to send a DNS query with the recursion desired (RD) flag set. By default, this setting is enabled.

dnsAddressResolverGroupProvider

Sets a custom function to create a DnsAddressResolverGroup given a DnsNameResolverBuilder

hostsFileEntriesResolver

Sets a custom {nettyjavadoc}/io/netty/resolver/HostsFileEntriesResolver.html[HostsFileEntriesResolver] to be used for hosts file entries. Default: {nettyjavadoc}/io/netty/resolver/DefaultHostsFileEntriesResolver.html[DefaultHostsFileEntriesResolver].

maxPayloadSize

Sets the capacity of the datagram packet buffer (in bytes). Default: 4096.

maxQueriesPerResolve

Sets the maximum allowed number of DNS queries to send when resolving a host name. Default: 16.

ndots

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).

queryTimeout

Sets the timeout of each DNS query performed by this resolver (resolution: milliseconds). Default: 5000.

resolveCache

The cache to use to store resolved DNS entries.

resolvedAddressTypes

The list of the protocol families of the resolved address.

retryTcpOnTimeout

Specifies whether this resolver will also fallback to TCP if a timeout is detected. By default, the resolver will only try to use TCP if the response is marked as truncated.

roundRobinSelection

Enables an {nettyjavadoc}/io/netty/resolver/AddressResolverGroup.html[AddressResolverGroup] of {nettyjavadoc}/io/netty/resolver/dns/DnsNameResolver.html[DnsNameResolver] that supports random selection of destination addresses if multiple are provided by the nameserver. See {nettyjavadoc}/io/netty/resolver/dns/RoundRobinDnsAddressResolverGroup.html[RoundRobinDnsAddressResolverGroup]. Default: {nettyjavadoc}/io/netty/resolver/dns/DnsAddressResolverGroup.html[DnsAddressResolverGroup]

runOn

Performs the communication with the DNS servers on the given {javadoc}/reactor/netty/resources/LoopResources.html[LoopResources]. By default, the LoopResources specified on the client level are used.

searchDomains

The list of search domains of the resolver. By default, the effective search domain list is populated by using the system DNS search domains.

trace

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:

==== [source,java,indent=0] .{examplesdir}/resolver/custom/Application.java ---- Unresolved directive in tcp-client.adoc - include::{examplesdir}/resolver/custom/Application.java[lines=18..37] ---- <1> Sets the JVM built-in resolver. ====

:leveloffset: 3 Suggest Edit to "[tcp-client]"

:leveloffset: 1

:sourcedir: ./../../reactor-netty-http/src/main/java :examplesdir: ./../../reactor-netty-examples/src/main/java/reactor/netty/examples/documentation/http/server :javadoc: https://projectreactor.io/docs/netty/1.1.25-SNAPSHOT/api :nettyjavadoc: https://netty.io/4.1/api :wirelogger: reactor.netty.http.server.HttpServer

= HTTP Server

Reactor Netty provides the easy-to-use and easy-to-configure {javadoc}/reactor/netty/http/server/HttpServer.html[HttpServer] class. It hides most of the Netty functionality that is needed in order to create a HTTP server and adds Reactive Streams backpressure.

== Starting and Stopping

To start an HTTP server, you must create and configure a {javadoc}/reactor/netty/http/server/HttpServer.html[HttpServer] instance. By default, the host is configured for any local address, and the system picks up an ephemeral port when the bind operation is invoked. The following example shows how to create an HttpServer instance:

==== [source,java,indent=0] .{examplesdir}/create/Application.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/create/Application.java[lines=18..31] ---- <1> Creates an {javadoc}/reactor/netty/http/server/HttpServer.html[HttpServer] instance ready for configuring. <2> Starts the server in a blocking fashion and waits for it to finish initializing. ====

The returned {javadoc}/reactor/netty/DisposableServer.html[DisposableServer] offers a simple server API, including {javadoc}/reactor/netty/DisposableChannel.html#disposeNow-java.time.Duration-[disposeNow()], which shuts the server down in a blocking fashion.

=== Host and Port

To serve on a specific host and port, you can apply the following configuration to the HTTP server:

==== [source,java,indent=0] .{examplesdir}/address/Application.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/address/Application.java[lines=18..33] ---- <1> Configures the HTTP server host <2> Configures the HTTP server port ====

To serve on multiple addresses, after having configured the HttpServer you can bind it multiple times to obtain separate DisposableServer`s. All created servers will share resources such as `LoopResources because they use the same configuration instance under the hood.

==== [source,java,indent=0] .{examplesdir}/address/MultiAddressApplication.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/address/MultiAddressApplication.java[lines=18..41] ---- <1> Configures the first HTTP server host <2> Configures the first HTTP server port <3> Configures the second HTTP server host <4> Configures the second HTTP server port ====

== Eager Initialization

By default, the initialization of the HttpServer resources happens on demand. This means that the bind operation absorbs the extra time needed to initialize and load:

* the event loop groups * 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 HttpServer as follows:

==== [source,java,indent=0] .{examplesdir}/warmup/Application.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/warmup/Application.java[lines=18..36] ---- <1> Initialize and load the event loop groups, the native transport libraries and the native libraries for the security ====

== Routing HTTP

Defining routes for the HTTP server requires configuring the provided {javadoc}/reactor/netty/http/server/HttpServerRoutes.html[HttpServerRoutes] builder. The following example shows how to do so:

==== [source,java,indent=0] .{examplesdir}/routing/Application.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/routing/Application.java[lines=18..41] ---- <1> Serves a GET request to /hello and returns Hello World! <2> Serves a POST request to /echo and returns the received request body as a response. <3> Serves a GET request to /path/{param} and returns the value of the path parameter. <4> Serves websocket to /ws and returns the received incoming data as outgoing data. ====

NOTE: The server routes are unique and only the first matching in order of declaration is invoked.

=== SSE

The following code shows how you can configure the HTTP server to serve Server-Sent Events:

==== [source,java,indent=0] .{examplesdir}/sse/Application.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/sse/Application.java[lines=18..76] ---- ====

=== Static Resources

The following code shows how you can configure the HTTP server to serve static resources:

==== [source,java,indent=0] .{examplesdir}/staticresources/Application.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/staticresources/Application.java[lines=18..37] ---- ====

== Writing Data

To send data to a connected client, you must attach an I/O handler by using either {javadoc}/reactor/netty/http/server/HttpServer.html#handle-java.util.function.BiFunction-[handle(…​)] or {javadoc}/reactor/netty/http/server/HttpServer.html#route-java.util.function.Consumer-[route(…​)]. The I/O handler has access to {javadoc}/reactor/netty/http/server/HttpServerResponse.html[HttpServerResponse], to be able to write data. The following example uses the handle(…​) method:

==== [source,java,indent=0] .{examplesdir}/send/Application.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/send/Application.java[lines=18..33] ---- <1> Sends hello string to the connected clients ====

=== Adding Headers and Other Metadata

When you send data to the connected clients, you may need to send additional headers, cookies, status code, and other metadata. You can provide this additional metadata by using {javadoc}/reactor/netty/http/server/HttpServerResponse.html[HttpServerResponse]. The following example shows how to do so:

==== [source,java,indent=0] .{examplesdir}/send/headers/Application.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/send/headers/Application.java[lines=18..40] ---- ====

=== Compression

You can configure the HTTP server to send a compressed response, depending on the request header Accept-Encoding.

Reactor Netty provides three different strategies for compressing the outgoing data:

* compress(boolean): Depending on the boolean that is provided, the compression is enabled (true) or disabled (false). * compress(int): The compression is performed once the response size exceeds the given value (in bytes). * compress(BiPredicate<HttpServerRequest, HttpServerResponse>): The compression is performed if the predicate returns true.

The following example uses the compress method (set to true) to enable compression:

==== [source,java,indent=0] .{examplesdir}/compression/Application.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/compression/Application.java[lines=18..38] ---- ====

== Consuming Data

To receive data from a connected client, you must attach an I/O handler by using either {javadoc}/reactor/netty/http/server/HttpServer.html#handle-java.util.function.BiFunction-[handle(…​)] or {javadoc}/reactor/netty/http/server/HttpServer.html#route-java.util.function.Consumer-[route(…​)]. The I/O handler has access to {javadoc}/reactor/netty/http/server/HttpServerRequest.html[HttpServerRequest], to be able to read data.

The following example uses the handle(…​) method:

==== [source,java,indent=0] .{examplesdir}/read/Application.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/read/Application.java[lines=18..32] ---- <1> Receives data from the connected clients ====

=== Reading Headers, URI Params, and other Metadata

When you receive data from the connected clients, you might need to check request headers, parameters, and other metadata. You can obtain this additional metadata by using {javadoc}/reactor/netty/http/server/HttpServerRequest.html[HttpServerRequest]. The following example shows how to do so:

==== [source,java,indent=0] .{examplesdir}/read/headers/Application.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/read/headers/Application.java[lines=18..40] ---- ====

=== Reading Post Form or Multipart Data

When you receive data from the connected clients, you might want to access POST form (application/x-www-form-urlencoded) or multipart (multipart/form-data) data. You can obtain this data by using {javadoc}/reactor/netty/http/server/HttpServerRequest.html[HttpServerRequest].

==== [source,java,indent=0] .{examplesdir}/multipart/Application.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/multipart/Application.java[lines=18..36] ---- <1> Receives POST form/multipart data. ====

When you need to change the default settings, you can configure the HttpServer or you can provide a configuration per request:

==== [source,java,indent=0] .{examplesdir}/multipart/custom/Application.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/multipart/custom/Application.java[lines=18..37] ---- <1> Configuration on the HttpServer that specifies that the data is stored on disk only. <2> Configuration per request that specifies that if the data size exceed the specified size, the data is stored on the disk. ====

The following listing shows the available configurations:

[width="100%",options="header"]

=======

Configuration name

Description

baseDirectory

Configures the directory where to store the data on the disk. Default to generated temp directory.

charset

Configures the Charset for the data. Default to StandardCharsets#UTF_8.

maxInMemorySize

Configures the maximum in-memory size per data i.e. the data is written on disk if the size is greater than maxInMemorySize, else it is in memory. If set to -1 the entire contents is stored in memory. If set to 0 the entire contents is stored on disk. Default to 16kb.

maxSize

Configures the maximum size per data. When the limit is reached, an exception is raised. If set to -1 this means no limitation. Default to -1 - unlimited.

scheduler

Configures the scheduler to be used for offloading disk operations in the decoding phase. Default to Schedulers#boundedElastic()

streaming

When set to true, the data is streamed directly from the parsed input buffer stream, which means it is not stored either in memory or file. When false, parts are backed by in-memory and/or file storage. Default to false. NOTE that with streaming enabled, the provided data might not be in a complete state i.e. HttpData#isCompleted() has to be checked. Also note that enabling this property effectively ignores maxInMemorySize, baseDirectory, and scheduler.

=======

==== Obtaining the Remote (Client) Address

In addition to the metadata that you can obtain from the request, you can also receive the host (server) address, the remote (client) address and the scheme. Depending on the chosen factory method, you can retrieve the information directly from the channel or by using the Forwarded or X-Forwarded- HTTP request headers. The following example shows how to do so:

==== [source,java,indent=0] .{examplesdir}/clientaddress/Application.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/clientaddress/Application.java[lines=18..38] ---- <1> Specifies that the information about the connection is to be obtained from the Forwarded and X-Forwarded- HTTP request headers, if possible. <2> Returns the address of the remote (client) peer. ====

It is also possible to customize the behavior of the Forwarded or X-Forwarded-* header handler. The following example shows how to do so:

==== [source,java,indent=0] .{examplesdir}/clientaddress/CustomForwardedHeaderHandlerApplication.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/clientaddress/CustomForwardedHeaderHandlerApplication.java[lines=18..52] ---- <1> Add a custom header handler. <2> Returns the address of the remote (client) peer. ====

=== HTTP Request Decoder

By default, Netty configures some restrictions for the incoming requests, such as:

* The maximum length of the initial line. * The maximum length of all headers. * The maximum length of the content or each chunk.

For more information, see {nettyjavadoc}/io/netty/handler/codec/http/HttpRequestDecoder.html[HttpRequestDecoder] and {nettyjavadoc}/io/netty/handler/codec/http/HttpServerUpgradeHandler.html[HttpServerUpgradeHandler]

By default, the HTTP server is configured with the following settings:

==== [source,java,indent=0] .{sourcedir}/reactor/netty/http/HttpDecoderSpec.java ---- Unresolved directive in http-server.adoc - include::{sourcedir}/reactor/netty/http/HttpDecoderSpec.java[lines=28..40] ---- ==== ==== [source,java,indent=0] .{sourcedir}/reactor/netty/http/server/HttpRequestDecoderSpec.java ---- Unresolved directive in http-server.adoc - include::{sourcedir}/reactor/netty/http/server/HttpRequestDecoderSpec.java[lines=42..47] ---- ====

When you need to change these default settings, you can configure the HTTP server as follows:

==== [source,java,indent=0] .{examplesdir}/requestdecoder/Application.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/requestdecoder/Application.java[lines=18..34] ---- <1> The maximum length of all headers will be 16384. When this value is exceeded, a {nettyjavadoc}/io/netty/handler/codec/TooLongFrameException.html[TooLongFrameException] is raised. ====

== Lifecycle Callbacks

The following lifecycle callbacks are provided to let you extend the HttpServer:

[width="100%",options="header"]

=======

Callback

Description

doOnBind

Invoked when the server channel is about to bind.

doOnBound

Invoked when the server channel is bound.

doOnChannelInit

Invoked when initializing the channel.

doOnConnection

Invoked when a remote client is connected

doOnUnbound

Invoked when the server channel is unbound.

=======

The following example uses the doOnConnection and doOnChannelInit callbacks:

==== [source,java,indent=0] .{examplesdir}/lifecycle/Application.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/lifecycle/Application.java[lines=18..39] ---- <1> Netty pipeline is extended with ReadTimeoutHandler when a remote client is connected. <2> Netty pipeline is extended with LoggingHandler when initializing the channel. ====

== TCP-level Configuration

When you need to change configuration on the TCP level, you can use the following snippet to extend the default TCP server configuration:

==== [source,java,indent=0] .{examplesdir}/channeloptions/Application.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/channeloptions/Application.java[lines=18..33] ---- ====

See [tcp-server] for more detail about TCP-level configuration.

:formattersourcedir: ./../../reactor-netty-core/src/main/java

=== Wire Logger

Reactor Netty provides wire logging for when the traffic between the peers needs to be inspected. By default, wire logging is disabled. To enable it, you must set the logger {wirelogger} level to DEBUG and apply the following configuration:

==== [source,java,indent=0] .{examplesdir}/wiretap/Application.java ---- Unresolved directive in wire-logger.adoc - include::{examplesdir}/wiretap/Application.java[lines=18..35] ---- <1> Enables the wire logging ====

==== Wire Logger formatters Reactor Netty supports 3 different formatters:

- {javadoc}/reactor/netty/transport/logging/AdvancedByteBufFormat.html#HEX_DUMP[AdvancedByteBufFormat#HEX_DUMP] - the default

==== [source,java,indent=0] .{sourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java ---- Unresolved directive in wire-logger.adoc - include::{formattersourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java[lines=47..75] ---- ====

- {javadoc}/reactor/netty/transport/logging/AdvancedByteBufFormat.html#SIMPLE[AdvancedByteBufFormat#SIMPLE]

==== [source,java,indent=0] .{sourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java ---- Unresolved directive in wire-logger.adoc - include::{formattersourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java[lines=34..45] ---- ====

- {javadoc}/reactor/netty/transport/logging/AdvancedByteBufFormat.html#TEXTUAL[AdvancedByteBufFormat#TEXTUAL]

==== [source,java,indent=0] .{sourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java ---- Unresolved directive in wire-logger.adoc - include::{formattersourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java[lines=77..93] ---- ====

When you need to change the default formatter you can configure it as follows:

==== [source,java,indent=0] .{examplesdir}/wiretap/custom/Application.java ---- Unresolved directive in wire-logger.adoc - include::{examplesdir}/wiretap/custom/Application.java[lines=18..38] ---- <1> Enables the wire logging, {javadoc}/reactor/netty/transport/logging/AdvancedByteBufFormat.html#TEXTUAL[AdvancedByteBufFormat#TEXTUAL] is used for printing the content. ====

:eventloopsourcedir: ./../../reactor-netty-core/src/main/java

=== Event Loop Group

By default Reactor Netty 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). This “Event Loop Group” is shared between all servers and clients in one JVM. When you need a different configuration, you can use one of the {javadoc}/reactor/netty/resources/LoopResources.html[LoopResources]#create methods.

The following listing shows the default configuration for the Event Loop Group:

==== [source,java,indent=0] .{eventloopsourcedir}/reactor/netty/ReactorNetty.java ---- Unresolved directive in eventloop.adoc - include::{eventloopsourcedir}/reactor/netty/ReactorNetty.java[lines=87..121] ---- ====

If you need changes to these settings, you can apply the following configuration:

==== [source,java,indent=0] .{examplesdir}/eventloop/Application.java ---- Unresolved directive in eventloop.adoc - include::{examplesdir}/eventloop/Application.java[lines=18..38] ---- ====

==== Disposing Event Loop Group

- If you use the default Event Loop Group provided by Reactor Netty, invoke {javadoc}/reactor/netty/http/HttpResources.html[HttpResources]#disposeLoopsAndConnections/#disposeLoopsAndConnectionsLater method.

NOTE: Disposing HttpResources means that every server/client that is using it, will not be able to use it anymore!

- If you use custom LoopResources, invoke {javadoc}/reactor/netty/resources/LoopResources.html[LoopResources]#dispose/#disposeLater method.

NOTE: Disposing the custom LoopResources means that every server/client that is configured to use it, will not be able to use it anymore!

== SSL and TLS

When you need SSL or TLS, you can apply the configuration shown in the next example. By default, if OpenSSL is available, {nettyjavadoc}/io/netty/handler/ssl/SslProvider.html#OPENSSL[SslProvider.OPENSSL] provider is used as a provider. Otherwise {nettyjavadoc}/io/netty/handler/ssl/SslProvider.html#JDK[SslProvider.JDK] is used. You can switch the provider by using {nettyjavadoc}/io/netty/handler/ssl/SslContextBuilder.html#sslProvider-io.netty.handler.ssl.SslProvider-[SslContextBuilder] or by setting -Dio.netty.handler.ssl.noOpenSsl=true.

The following example uses SslContextBuilder:

==== [source,java,indent=0] .{examplesdir}/security/Application.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/security/Application.java[lines=18..39] ---- ====

=== Server Name Indication You can configure the HTTP server with multiple SslContext mapped to a specific domain. An exact domain name or a domain name containing a wildcard can be used when configuring the SNI mapping.

The following example uses a domain name containing a wildcard:

==== [source,java,indent=0] .{examplesdir}/sni/Application.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/sni/Application.java[lines=18..47] ---- ====

== HTTP Access Log

You can enable the HTTP access log either programmatically or by configuration. By default, it is disabled.

You can use -Dreactor.netty.http.server.accessLogEnabled=true to enable the HTTP access log by configuration.

You can use the following configuration (for Logback or similar logging frameworks) to have a separate HTTP access log file:

==== [source,xml] ---- <appender name="accessLog" class="ch.qos.logback.core.FileAppender"> <file>access_log.log</file> <encoder> <pattern>%msg%n</pattern> </encoder> </appender> <appender name="async" class="ch.qos.logback.classic.AsyncAppender"> <appender-ref ref="accessLog" /> </appender>

<logger name="reactor.netty.http.server.AccessLog" level="INFO" additivity="false"> <appender-ref ref="async"/> </logger> ---- ====

The following example enables it programmatically: ==== [source,java,indent=0] .{examplesdir}/accessLog/Application.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/accessLog/Application.java[lines=18..32] ---- ====

Calling this method takes precedence over the system property configuration.

By default, the logging format is Common Log Format, but you can specify a custom one as a parameter, as in the following example: ==== [source,java,indent=0] .{examplesdir}/accessLog/CustomLogAccessFormatApplication.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/accessLog/CustomLogAccessFormatApplication.java[lines=18..33] ---- ====

You can also filter HTTP access logs by using the AccessLogFactory#createFilter method, as in the following example: ==== [source,java,indent=0] .{examplesdir}/accessLog/FilterLogAccessApplication.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/accessLog/FilterLogAccessApplication.java[lines=18..34] ---- ====

Note that this method can take a custom format parameter too, as in this example: ==== [source,java,indent=0] .{examplesdir}/accessLog/CustomFormatAndFilterAccessLogApplication.java.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/accessLog/CustomFormatAndFilterAccessLogApplication.java[lines=18..35] ---- <1> Specifies the filter predicate to use <2> Specifies the custom format to apply

====

== HTTP/2

By default, the HTTP server supports HTTP/1.1. If you need HTTP/2, you can get it through configuration. In addition to the protocol configuration, if you need H2 but not H2C (cleartext), you must also configure SSL.

NOTE: As Application-Layer Protocol Negotiation (ALPN) is not supported “out-of-the-box” by JDK8 (although some vendors backported ALPN to JDK8), you need an additional dependency to a native library that supports it — for example, netty-tcnative-boringssl-static.

The following listing presents a simple H2 example:

==== [source,java,indent=0] .{examplesdir}/http2/H2Application.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/http2/H2Application.java[lines=18..44] ---- <1> Configures the server to support only HTTP/2 <2> Configures SSL ====

The application should now behave as follows:

==== [source,bash] ---- $ curl --http2 https://localhost:8080 -i HTTP/2 200

hello ---- ====

The following listing presents a simple H2C example:

==== [source,java,indent=0] .{examplesdir}/http2/H2CApplication.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/http2/H2CApplication.java[lines=18..41] ---- ====

The application should now behave as follows:

==== [source,bash] ---- $ curl --http2-prior-knowledge http://localhost:8080 -i HTTP/2 200

hello ---- ====

=== Protocol Selection

==== [source,java,indent=0] .{sourcedir}/reactor/netty/http/HttpProtocol.java ---- Unresolved directive in http-server.adoc - include::{sourcedir}/reactor/netty/http/HttpProtocol.java[lines=24..52] ---- ====

== Metrics The HTTP server supports built-in integration with Micrometer. It exposes all metrics with a prefix of reactor.netty.http.server.

The following table provides information for the HTTP server metrics:

[width="100%",options="header"]

=======

metric name

type

description

reactor.netty.http.server.streams.active

Gauge

The number of active HTTP/2 streams. See [observability-metrics-streams-active]

reactor.netty.http.server.connections.active

Gauge

The number of http connections currently processing requests. See [observability-metrics-connections-active]

reactor.netty.http.server.connections.total

Gauge

The number of all opened connections. See [observability-metrics-connections-total]

reactor.netty.http.server.data.received

DistributionSummary

Amount of the data received, in bytes. See [observability-metrics-data-received]

reactor.netty.http.server.data.sent

DistributionSummary

Amount of the data sent, in bytes. See [observability-metrics-data-sent]

reactor.netty.http.server.errors

Counter

Number of errors that occurred. See [observability-metrics-errors-count]

reactor.netty.http.server.data.received.time

Timer

Time spent in consuming incoming data. See [observability-metrics-http-server-data-received-time]

reactor.netty.http.server.data.sent.time

Timer

Time spent in sending outgoing data. See [observability-metrics-http-server-data-sent-time]

reactor.netty.http.server.response.time

Timer

Total time for the request/response See [observability-metrics-http-server-response-time]

=======

These additional metrics are also available:

ByteBufAllocator metrics

[width="100%",options="header"]

=======

metric name

type

description

reactor.netty.bytebuf.allocator.used.heap.memory

Gauge

The number of bytes reserved by heap buffer allocator. See [observability-metrics-used-heap-memory]

reactor.netty.bytebuf.allocator.used.direct.memory

Gauge

The number of bytes reserved by direct buffer allocator. See [observability-metrics-used-direct-memory]

reactor.netty.bytebuf.allocator.heap.arenas

Gauge

The number of heap arenas (when PooledByteBufAllocator). See [observability-metrics-heap-arenas]

reactor.netty.bytebuf.allocator.direct.arenas

Gauge

The number of direct arenas (when PooledByteBufAllocator). See [observability-metrics-direct-arenas]

reactor.netty.bytebuf.allocator.threadlocal.caches

Gauge

The number of thread local caches (when PooledByteBufAllocator). See [observability-metrics-thread-local-caches]

reactor.netty.bytebuf.allocator.small.cache.size

Gauge

The size of the small cache (when PooledByteBufAllocator). See [observability-metrics-small-cache-size]

reactor.netty.bytebuf.allocator.normal.cache.size

Gauge

The size of the normal cache (when PooledByteBufAllocator). See [observability-metrics-normal-cache-size]

reactor.netty.bytebuf.allocator.chunk.size

Gauge

The chunk size for an arena (when PooledByteBufAllocator). See [observability-metrics-chunk-size]

reactor.netty.bytebuf.allocator.active.heap.memory

Gauge

The actual bytes consumed by in-use buffers allocated from heap buffer pools (when PooledByteBufAllocator). See [observability-metrics-active-heap-memory]

reactor.netty.bytebuf.allocator.active.direct.memory

Gauge

The actual bytes consumed by in-use buffers allocated from direct buffer pools (when PooledByteBufAllocator). See [observability-metrics-active-direct-memory]

======= EventLoop metrics

[width="100%",options="header"]

=======

metric name

type

description

reactor.netty.eventloop.pending.tasks

Gauge

The number of tasks that are pending for processing on an event loop. See [observability-metrics-pending-tasks]

=======

The following example enables that integration:

==== [source,java,indent=0] .{examplesdir}/metrics/Application.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/metrics/Application.java[lines=18..52] ---- <1> Applies upper limit for the meters with URI tag <2> Templated URIs will be used as an URI tag value when possible <3> Enables the built-in integration with Micrometer ====

NOTE: In order to avoid a memory and CPU overhead of the enabled metrics, it is important to convert the real URIs to templated URIs when possible. Without a conversion to a template-like form, each distinct URI leads to the creation of a distinct tag, which takes a lot of memory for the metrics.

NOTE: Always apply an upper limit for the meters with URI tags. Configuring an upper limit on the number of meters can help in cases when the real URIs cannot be templated. You can find more information at maximumAllowableTags.

When HTTP server 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:

==== [source,java,indent=0] .{examplesdir}/metrics/custom/Application.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/metrics/custom/Application.java[lines=18..41] ---- <1> Enables HTTP server metrics and provides {javadoc}/reactor/netty/http/server/HttpServerMetricsRecorder.html[HttpServerMetricsRecorder] implementation. ====

== Tracing The HTTP server supports built-in integration with Micrometer Tracing.

The following table provides information for the HTTP server spans:

[width="100%",options="header"]

=======

contextual name

description

<HTTP METHOD>_<URI>

Information and total time for the request. See [observability-spans-http-server-response-span].

=======

The following example enables that integration. This concrete example uses Brave and reports the information to Zipkin. See the Micrometer Tracing documentation for OpenTelemetry setup.

==== [source,java,indent=0] .{examplesdir}/tracing/Application.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/tracing/Application.java[lines=18..91] ---- <1> Initializes Brave, Zipkin, and the Observation registry. <2> Templated URIs are used as an URI tag value when possible. <3> Enables the built-in integration with Micrometer. ====

The result in Zipkin looks like:

image::images/http-server-tracing.png[]

=== Access Current Observation Project Micrometer provides a library that assists with context propagation across different types of context mechanisms such as ThreadLocal, Reactor Context and others.

The following example shows how to use this library in a custom ChannelHandler:

==== [source,java,indent=0] .{examplesdir}/tracing/custom/Application.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/tracing/custom/Application.java[lines=18..85] ---- <1> Initializes Brave, Zipkin, and the Observation registry. <2> Templated URIs are used as an URI tag value when possible. <3> Enables the built-in integration with Micrometer. <4> Custom ChannelHandler that uses context propagation library. This concrete example overrides only ChannelOutboundHandlerAdapter#write, if it is needed, the same logic can be used for the rest of the methods. Also, this concrete example sets all ThreadLocal values for which there is a value in the given Channel, if another behaviour is needed please check context propagation library API. For example, you may want to set only some of the ThreadLocal values. ====

NOTE: When you enable Reactor Netty tracing within a framework, you may need to let Reactor Netty use the ObservationRegistry created by this framework. For this purpose you need to invoke {javadoc}/reactor/netty/Metrics.html#observationRegistry-io.micrometer.observation.ObservationRegistry-[reactor.netty.Metrics#observationRegistry]. You may also need to configure the Reactor Netty ObservationHandlers using the API provided by the framework.

== Unix Domain Sockets The HTTP server supports Unix Domain Sockets (UDS) when native transport is in use.

The following example shows how to use UDS support:

==== [source,java,indent=0] .{examplesdir}/uds/Application.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/uds/Application.java[lines=18..33] ---- <1> Specifies DomainSocketAddress that will be used ====

== Timeout Configuration This section describes various timeout configuration options that can be used in HttpServer. Configuring a proper timeout may improve or solve issues in the communication process. The configuration options can be grouped as follows:

* [http-server-request-timeout] * [http-server-connection-timeout] * [http-server-ssl-tls-timeout]

=== Request Timeout The following listing shows all available request timeout configuration options.

* readTimeout - the maximum time between each network-level read operation while reading a given request content (resolution: ms) * requestTimeout - the maximum time for reading a given request content (resolution: ms).

NOTE: It is always a good practice to configure a read/request timeout.

To customize the default settings, you can configure HttpServer as follows:

==== [source,java,indent=0] .{examplesdir}/read/timeout/Application.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/read/timeout/Application.java[lines=18..36] ---- <1> Configures the read timeout to 5 second. <2> Configures the request timeout to 30 second. ====

=== Connection Timeout The following listing shows all available connection timeout configuration options.

* idleTimeout - The maximum time (resolution: ms) that this connection stays opened and waits for HTTP request. Once the timeout is reached, the connection is closed. By default, {javadoc}/reactor/netty/http/server/HttpServer.html#idleTimeout-java.time.Duration-[idleTimeout] is not specified, this indicates no timeout (i.e. infinite), which means the connection is closed only if one of the peers decides to close it explicitly.

NOTE: It is always a good practice to configure an idle timeout.

To customize the default settings, you can configure HttpServer as follows:

==== [source,java,indent=0] .{examplesdir}/idle/timeout/Application.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/idle/timeout/Application.java[lines=18..35] ---- <1> Configures the default idle timeout to 1 second. ====

=== SSL/TLS Timeout HttpServer supports the SSL/TLS functionality provided by Netty.

The following list describes the available timeout configuration options:

* handshakeTimeout - Use this option to configure the SSL handshake timeout (resolution: ms). Default: 10s.

NOTE: You should consider increasing the SSL handshake timeout when expecting slow network connections.

* closeNotifyFlushTimeout - Use this option to configure the SSL close_notify flush timeout (resolution: ms). Default: 3s. * closeNotifyReadTimeout - Use this option to configure the SSL close_notify read timeout (resolution: ms). Default: 0s.

To customize the default settings, you can configure HttpServer as follows:

==== [source,java,indent=0] .{examplesdir}/security/custom/Application.java ---- Unresolved directive in http-server.adoc - include::{examplesdir}/security/custom/Application.java[lines=18..44] ---- <1> Configures the SSL handshake timeout to 30 seconds. <2> Configures the SSL close_notify flush timeout to 10 seconds. <3> Configures the SSL close_notify read timeout to 10 seconds. ====

:leveloffset: 3 Suggest Edit to "[http-server]"

:leveloffset: 1

:sourcedir: ./../../reactor-netty-http/src/main/java :examplesdir: ./../../reactor-netty-examples/src/main/java/reactor/netty/examples/documentation/http/client :javadoc: https://projectreactor.io/docs/netty/1.1.25-SNAPSHOT/api :nettyjavadoc: https://netty.io/4.1/api :wirelogger: reactor.netty.http.client.HttpClient

= HTTP Client

Reactor Netty provides the easy-to-use and easy-to-configure {javadoc}/reactor/netty/http/client/HttpClient.html[HttpClient]. It hides most of the Netty functionality that is required to create an HTTP client and adds Reactive Streams backpressure.

== Connect

To connect the HTTP client to a given HTTP endpoint, you must create and configure a {javadoc}/reactor/netty/http/client/HttpClient.html[HttpClient] instance. By default, the host is configured for localhost and the port is 80. The following example shows how to do so:

==== [source,java,indent=0] .{examplesdir}/connect/Application.java ---- Unresolved directive in http-client.adoc - include::{examplesdir}/connect/Application.java[lines=18..30] ---- <1> Creates a {javadoc}/reactor/netty/http/client/HttpClient.html[HttpClient] instance ready for configuring. <2> Specifies that GET method will be used. <3> Specifies the path. <4> Obtains the response {javadoc}/reactor/netty/http/client/HttpClientResponse.html[HttpClientResponse] ====

The following example uses WebSocket:

==== [source,java,indent=0] .{examplesdir}/websocket/Application.java ---- Unresolved directive in http-client.adoc - include::{examplesdir}/websocket/Application.java[lines=18..42] ---- ====

=== Host and Port

In order to connect to a specific host and port, you can apply the following configuration to the HTTP client:

==== [source,java,indent=0] .{examplesdir}/address/Application.java ---- Unresolved directive in http-client.adoc - include::{examplesdir}/address/Application.java[lines=18..33] ---- <1> Configures the HTTP host <2> Configures the HTTP port ====

NOTE: The port can be specified also with PORT environment variable.

== Eager Initialization

By default, the initialization of the HttpClient resources happens on demand. This means that the first request 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 HttpClient as follows:

==== [source,java,indent=0] .{examplesdir}/warmup/Application.java ---- Unresolved directive in http-client.adoc - include::{examplesdir}/warmup/Application.java[lines=18..36] ---- <1> Initialize and load the event loop group, the host name resolver, the native transport libraries and the native libraries for the security <2> Host name resolution happens with the first request. In this example, a connection pool is used, so with the first request the connection to the URL is established, the subsequent requests to the same URL reuse the connections from the pool. ====

== Writing Data

To send data to a given HTTP endpoint, you can provide a Publisher by using the {javadoc}/reactor/netty/http/client/HttpClient.RequestSender.html#send-org.reactivestreams.Publisher-[send(Publisher)] method. By default, Transfer-Encoding: chunked is applied for those HTTP methods for which a request body is expected. Content-Length provided through request headers disables Transfer-Encoding: chunked, if necessary. The following example sends hello:

==== [source,java,indent=0] .{examplesdir}/send/Application.java ---- Unresolved directive in http-client.adoc - include::{examplesdir}/send/Application.java[lines=18..33] ---- <1> Sends a hello string to the given HTTP endpoint ====

=== Adding Headers and Other Metadata

When sending data to a given HTTP endpoint, you may need to send additional headers, cookies and other metadata. You can use the following configuration to do so:

==== [source,java,indent=0] .{examplesdir}/send/headers/Application.java ---- Unresolved directive in http-client.adoc - include::{examplesdir}/send/headers/Application.java[lines=18..36] ---- <1> Disables Transfer-Encoding: chunked and provides Content-Length header. ====

==== Compression

You can enable compression on the HTTP client, which means the request header Accept-Encoding is added to the request headers. The following example shows how to do so:

==== [source,java,indent=0] .{examplesdir}/compression/Application.java ---- Unresolved directive in http-client.adoc - include::{examplesdir}/compression/Application.java[lines=18..32] ---- ====

==== Auto-Redirect Support

You can configure the HTTP client to enable auto-redirect support.

Reactor Netty provides two different strategies for auto-redirect support:

* followRedirect(boolean): Specifies whether HTTP auto-redirect support is enabled for statuses `301

302

303

307

308`. When it is 303 status code, GET method is used for the redirect. * followRedirect(BiPredicate<HttpClientRequest, HttpClientResponse>): Enables auto-redirect support if the supplied predicate matches.

The following example uses followRedirect(true):

==== [source,java,indent=0] .{examplesdir}/redirect/Application.java ---- Unresolved directive in http-client.adoc - include::{examplesdir}/redirect/Application.java[lines=18..32] ---- ====

== Consuming Data

To receive data from a given HTTP endpoint, you can use one of the methods from {javadoc}/reactor/netty/http/client/HttpClient.ResponseReceiver.html[HttpClient.ResponseReceiver]. The following example uses the responseContent method:

==== [source,java,indent=0] .{examplesdir}/read/Application.java ---- Unresolved directive in http-client.adoc - include::{examplesdir}/read/Application.java[lines=18..33] ---- <1> Receives data from a given HTTP endpoint <2> Aggregates the data <3> Transforms the data as string ====

=== Reading Headers and Other Metadata

When receiving data from a given HTTP endpoint, you can check response headers, status code, and other metadata. You can obtain this additional metadata by using {javadoc}/reactor/netty/http/client/HttpClientResponse.html[HttpClientResponse]. The following example shows how to do so.

==== [source,java,indent=0] .{examplesdir}/read/status/Application.java ---- Unresolved directive in http-client.adoc - include::{examplesdir}/read/status/Application.java[lines=18..34] ---- <1> Obtains the status code. ====

=== HTTP Response Decoder

By default, Netty configures some restrictions for the incoming responses, such as:

* The maximum length of the initial line. * The maximum length of all headers. * The maximum length of the content or each chunk.

For more information, see {nettyjavadoc}/io/netty/handler/codec/http/HttpResponseDecoder.html[HttpResponseDecoder]

By default, the HTTP client is configured with the following settings:

==== [source,java,indent=0] .{sourcedir}/reactor/netty/http/HttpDecoderSpec.java ---- Unresolved directive in http-client.adoc - include::{sourcedir}/reactor/netty/http/HttpDecoderSpec.java[lines=28..40] ---- ==== ==== [source,java,indent=0] .{sourcedir}/reactor/netty/http/client/HttpResponseDecoderSpec.java ---- Unresolved directive in http-client.adoc - include::{sourcedir}/reactor/netty/http/client/HttpResponseDecoderSpec.java[lines=42..50] ---- ====

When you need to change these default settings, you can configure the HTTP client as follows:

==== [source,java,indent=0] .{examplesdir}/responsedecoder/Application.java ---- Unresolved directive in http-client.adoc - include::{examplesdir}/responsedecoder/Application.java[lines=18..35] ---- <1> The maximum length of all headers will be 16384. When this value is exceeded, a {nettyjavadoc}/io/netty/handler/codec/TooLongFrameException.html[TooLongFrameException] is raised. ====

== Lifecycle Callbacks

The following lifecycle callbacks are provided to let you extend the HttpClient.

[width="100%",options="header"]

=======

Callback

Description

doAfterRequest

Invoked when the request has been sent.

doAfterResolve

Invoked after the remote address has been resolved successfully.

doAfterResponseSuccess

Invoked after the response has been fully received.

doOnChannelInit

Invoked when initializing the channel.

doOnConnect

Invoked when the channel is about to connect.

doOnConnected

Invoked after the channel has been connected.

doOnDisconnected

Invoked after the channel has been disconnected.

doOnError

Invoked when the request has not been sent and when the response has not been fully received.

doOnRedirect

Invoked when the response headers have been received, and the request is about to be redirected.

doOnRequest

Invoked when the request is about to be sent.

doOnRequestError

Invoked when the request has not been sent.

doOnResolve

Invoked when the remote address is about to be resolved.

doOnResolveError

Invoked in case the remote address hasn’t been resolved successfully.

doOnResponse

Invoked after the response headers have been received.

doOnResponseError

Invoked when the response has not been fully received.

=======

The following example uses the doOnConnected and doOnChannelInit callbacks:

==== [source,java,indent=0] .{examplesdir}/lifecycle/Application.java ---- Unresolved directive in http-client.adoc - include::{examplesdir}/lifecycle/Application.java[lines=18..39] ---- <1> Netty pipeline is extended with ReadTimeoutHandler when the channel has been connected. <2> Netty pipeline is extended with LoggingHandler when initializing the channel. ====

== TCP-level Configuration

When you need configurations on a TCP level, you can use the following snippet to extend the default TCP client configuration (add an option, bind address etc.):

==== [source,java,indent=0] .{examplesdir}/channeloptions/Application.java ---- Unresolved directive in http-client.adoc - include::{examplesdir}/channeloptions/Application.java[lines=18..54] ---- <1> Configures the connection establishment timeout to 10 seconds. <2> Enables TCP keepalive. This means that TCP starts sending keepalive probes when a connection is idle for some time. <3> The connection needs to remain idle for 5 minutes before TCP starts sending keepalive probes. <4> Configures the time between individual keepalive probes to 1 minute. <5> Configures the maximum number of TCP keepalive probes to 8. ====

See [tcp-client] for more about TCP level configurations.

:formattersourcedir: ./../../reactor-netty-core/src/main/java

=== Wire Logger

Reactor Netty provides wire logging for when the traffic between the peers needs to be inspected. By default, wire logging is disabled. To enable it, you must set the logger {wirelogger} level to DEBUG and apply the following configuration:

==== [source,java,indent=0] .{examplesdir}/wiretap/Application.java ---- Unresolved directive in wire-logger.adoc - include::{examplesdir}/wiretap/Application.java[lines=18..35] ---- <1> Enables the wire logging ====

==== Wire Logger formatters Reactor Netty supports 3 different formatters:

- {javadoc}/reactor/netty/transport/logging/AdvancedByteBufFormat.html#HEX_DUMP[AdvancedByteBufFormat#HEX_DUMP] - the default

==== [source,java,indent=0] .{sourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java ---- Unresolved directive in wire-logger.adoc - include::{formattersourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java[lines=47..75] ---- ====

- {javadoc}/reactor/netty/transport/logging/AdvancedByteBufFormat.html#SIMPLE[AdvancedByteBufFormat#SIMPLE]

==== [source,java,indent=0] .{sourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java ---- Unresolved directive in wire-logger.adoc - include::{formattersourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java[lines=34..45] ---- ====

- {javadoc}/reactor/netty/transport/logging/AdvancedByteBufFormat.html#TEXTUAL[AdvancedByteBufFormat#TEXTUAL]

==== [source,java,indent=0] .{sourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java ---- Unresolved directive in wire-logger.adoc - include::{formattersourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java[lines=77..93] ---- ====

When you need to change the default formatter you can configure it as follows:

==== [source,java,indent=0] .{examplesdir}/wiretap/custom/Application.java ---- Unresolved directive in wire-logger.adoc - include::{examplesdir}/wiretap/custom/Application.java[lines=18..38] ---- <1> Enables the wire logging, {javadoc}/reactor/netty/transport/logging/AdvancedByteBufFormat.html#TEXTUAL[AdvancedByteBufFormat#TEXTUAL] is used for printing the content. ====

:eventloopsourcedir: ./../../reactor-netty-core/src/main/java

=== Event Loop Group

By default Reactor Netty 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). This “Event Loop Group” is shared between all servers and clients in one JVM. When you need a different configuration, you can use one of the {javadoc}/reactor/netty/resources/LoopResources.html[LoopResources]#create methods.

The following listing shows the default configuration for the Event Loop Group:

==== [source,java,indent=0] .{eventloopsourcedir}/reactor/netty/ReactorNetty.java ---- Unresolved directive in eventloop.adoc - include::{eventloopsourcedir}/reactor/netty/ReactorNetty.java[lines=87..121] ---- ====

If you need changes to these settings, you can apply the following configuration:

==== [source,java,indent=0] .{examplesdir}/eventloop/Application.java ---- Unresolved directive in eventloop.adoc - include::{examplesdir}/eventloop/Application.java[lines=18..38] ---- ====

==== Disposing Event Loop Group

- If you use the default Event Loop Group provided by Reactor Netty, invoke {javadoc}/reactor/netty/http/HttpResources.html[HttpResources]#disposeLoopsAndConnections/#disposeLoopsAndConnectionsLater method.

NOTE: Disposing HttpResources means that every server/client that is using it, will not be able to use it anymore!

- If you use custom LoopResources, invoke {javadoc}/reactor/netty/resources/LoopResources.html[LoopResources]#dispose/#disposeLater method.

NOTE: Disposing the custom LoopResources means that every server/client that is configured to use it, will not be able to use it anymore!

== Connection Pool By default, HttpClient (HttpClient.create()) uses a shared ConnectionProvider. This ConnectionProvider is configured to create a “fixed” connection pool per remote host (a remote host implies the combination of a hostname and its associated port number) with:

* 500 as the maximum number of active channels * 1000 as the maximum number of further channel acquisition attempts allowed to be kept in a pending state * The rest of the configurations are the defaults (check the system properties or the builder configurations below)

This means that the implementation creates a new channel if someone tries to acquire a channel as long as less than 500 have been created and are managed by the pool. When the maximum number of channels in the pool is reached, up to 1000 new attempts to acquire a channel are delayed (pending) until a channel is returned to the pool again, and further attempts are declined with an error.

==== [source,java,indent=0] ../../../reactor-netty-core/src/main/java/reactor/netty/ReactorNetty.java ---- / * Default max connections. Fallback to * 2 * available number of processors (but with a minimum value of 16) / public static final String POOL_MAX_CONNECTIONS = "reactor.netty.pool.maxConnections"; / * Default acquisition timeout (milliseconds) before error. If -1 will never wait to * acquire before opening a new * connection in an unbounded fashion. Fallback 45 seconds */ public static final String POOL_ACQUIRE_TIMEOUT = "reactor.netty.pool.acquireTimeout"; / * Default max idle time, fallback - max idle time is not specified. * <p><strong>Note:</strong> This configuration is not applicable for {@link reactor.netty.tcp.TcpClient}. * A TCP connection is always closed and never returned to the pool. */ public static final String POOL_MAX_IDLE_TIME = "reactor.netty.pool.maxIdleTime"; / * Default max life time, fallback - max life time is not specified. * <p><strong>Note:</strong> This configuration is not applicable for {@link reactor.netty.tcp.TcpClient}. * A TCP connection is always closed and never returned to the pool. */ public static final String POOL_MAX_LIFE_TIME = "reactor.netty.pool.maxLifeTime"; / * Default leasing strategy (fifo, lifo), fallback to fifo. * <ul> * <li>fifo - The connection selection is first in, first out</li> * <li>lifo - The connection selection is last in, first out</li> * </ul> * <p><strong>Note:</strong> This configuration is not applicable for {@link reactor.netty.tcp.TcpClient}. * A TCP connection is always closed and never returned to the pool. */ public static final String POOL_LEASING_STRATEGY = "reactor.netty.pool.leasingStrategy"; / * Default {@code getPermitsSamplingRate} (between 0d and 1d (percentage)) * to be used with a {@link SamplingAllocationStrategy}. * This strategy wraps a {@link PoolBuilder#sizeBetween(int, int) sizeBetween} {@link AllocationStrategy} * and samples calls to {@link AllocationStrategy#getPermits(int)}. * Fallback - sampling is not enabled. */ public static final String POOL_GET_PERMITS_SAMPLING_RATE = "reactor.netty.pool.getPermitsSamplingRate"; /* * Default {@code returnPermitsSamplingRate} (between 0d and 1d (percentage)) * to be used with a {@link SamplingAllocationStrategy}. * This strategy wraps a {@link PoolBuilder#sizeBetween(int, int) sizeBetween} {@link AllocationStrategy} * and samples calls to {@link AllocationStrategy#returnPermits(int)}. * Fallback - sampling is not enabled. */ public static final String POOL_RETURN_PERMITS_SAMPLING_RATE = "reactor.netty.pool.returnPermitsSamplingRate"; ---- ====

When you need to change the default settings, you can configure the ConnectionProvider as follows:

==== [source,java,indent=0] .{examplesdir}/pool/config/Application.java ---- Unresolved directive in http-client-conn-provider.adoc - include::{examplesdir}/pool/config/Application.java[lines=18..50] ---- <1> Configures the maximum time for a connection to stay idle to 20 seconds. <2> Configures the maximum time for a connection to stay alive to 60 seconds. <3> Configures the maximum time for the pending acquire operation to 60 seconds. <4> Every two minutes, the connection pool is regularly checked for connections that are applicable for removal. ====

NOTE: Notice that only the default HttpClient (HttpClient.create()) uses 500 as the maximum number of active channels. In the example above, when instantiating a custom ConnectionProvider, we are changing this value to 50 using maxConnections. Also, if you don’t set this parameter the default maxConnections is used (2 * available number of processors).

The following listing shows the available configurations: [width="100%",options="header"]

=======

Configuration name

Description

disposeInactivePoolsInBackground

When this option is enabled, connection pools are regularly checked in the background, and those that are empty and been inactive for a specified time become eligible for disposal. Connection pool is considered empty when there are no active connections, idle connections and pending acquisitions. By default, this background disposal of inactive pools is disabled.

disposeTimeout

When ConnectionProvider#dispose() or ConnectionProvider#disposeLater() is called, trigger a graceful shutdown for the connection pools, with this grace period timeout. From there on, all calls for acquiring a connection will fail fast with an exception. However, for the provided Duration, pending acquires will get a chance to be served. Note: The rejection of new acquires and the grace timer start immediately, irrespective of subscription to the Mono returned by ConnectionProvider#disposeLater(). Subsequent calls return the same Mono, effectively getting notifications from the first graceful shutdown call and ignoring subsequently provided timeouts. By default, dispose timeout is not specified.

evictInBackground

When this option is enabled, each connection pool regularly checks for connections that are eligible for removal according to eviction criteria like maxIdleTime. By default, this background eviction is disabled.

fifo

Configure the connection pool so that if there are idle connections (i.e. pool is under-utilized), the next acquire operation will get the Least Recently Used connection (LRU, i.e. the connection that was released first among the current idle connections). Default leasing strategy.

lifo

Configure the connection pool so that if there are idle connections (i.e. pool is under-utilized), the next acquire operation will get the Most Recently Used connection (MRU, i.e. the connection that was released last among the current idle connections).

maxConnections

The maximum number of connections (per connection pool) before start pending. Default to 2 * available number of processors (but with a minimum value of 16).

maxIdleTime

The time after which the channel is eligible to be closed when idle (resolution: ms). Default: max idle time is not specified.

maxLifeTime

The total life time after which the channel is eligible to be closed (resolution: ms). Default: max life time is not specified.

metrics

Enables/disables built-in integration with Micrometer. ConnectionProvider.MeterRegistrar can be provided for integration with another metrics system. By default, metrics are not enabled.

pendingAcquireMaxCount

The maximum number of extra attempts at acquiring a connection to keep in a pending queue. If -1 is specified, the pending queue does not have upper limit. Default to 2 * max connections.

pendingAcquireTimeout

The maximum time before which a pending acquire must complete, or a TimeoutException is thrown (resolution: ms). If -1 is specified, no such timeout is applied. Default: 45 seconds.

=======

NOTE: When you expect a high load, be cautious with a connection pool with a very high value for maximum connections. You might experience reactor.netty.http.client.PrematureCloseException exception with a root cause "Connect Timeout" due to too many concurrent connections opened/acquired.

If you need to disable the connection pool, you can apply the following configuration:

==== [source,java,indent=0] .{examplesdir}/pool/Application.java ---- Unresolved directive in http-client-conn-provider.adoc - include::{examplesdir}/pool/Application.java[lines=18..49] ---- ====

=== Disposing Connection Pool

- If you use the default ConnectionProvider provided by Reactor Netty, invoke {javadoc}/reactor/netty/http/HttpResources.html[HttpResources]#disposeLoopsAndConnections/#disposeLoopsAndConnectionsLater method.

NOTE: Disposing HttpResources means that every client that is using it, will not be able to use it anymore!

- If you use custom ConnectionProvider, invoke {javadoc}/reactor/netty/resources/ConnectionProvider.html[ConnectionProvider]#dispose/#disposeLater/#disposeWhen method.

NOTE: Disposing the custom ConnectionProvider means that every client that is configured to use it, will not be able to use it anymore!

=== Metrics The pooled ConnectionProvider supports built-in integration with Micrometer. It exposes all metrics with a prefix of reactor.netty.connection.provider.

Pooled ConnectionProvider metrics

[width="100%",options="header"]

=======

metric name

type

description

reactor.netty.connection.provider.total.connections

Gauge

The number of all connections, active or idle. See [observability-metrics-total-connections]

reactor.netty.connection.provider.active.connections

Gauge

The number of the connections that have been successfully acquired and are in active use. See [observability-metrics-active-connections]

reactor.netty.connection.provider.max.connections

Gauge

The maximum number of active connections that are allowed. See [observability-metrics-max-connections]

reactor.netty.connection.provider.idle.connections

Gauge

The number of the idle connections. See [observability-metrics-idle-connections]

reactor.netty.connection.provider.pending.connections

Gauge

The number of requests that are waiting for a connection. See [observability-metrics-pending-connections]

reactor.netty.connection.provider.pending.connections.time

Timer

Time spent in pending acquire a connection from the connection pool. See [observability-metrics-pending-connections-time]

reactor.netty.connection.provider.max.pending.connections

Gauge

The maximum number of requests that will be queued while waiting for a ready connection. See [observability-metrics-max-pending-connections]

=======

The following table provides information for the HTTP client metrics when it is configured to serve HTTP/2 traffic:

[width="100%",options="header"]

=======

metric name

type

description

reactor.netty.connection.provider.active.streams

Gauge

The number of the active HTTP/2 streams. See [observability-metrics-active-streams]

reactor.netty.connection.provider.pending.streams

Gauge

The number of requests that are waiting for opening HTTP/2 stream. See [observability-metrics-pending-streams]

=======

The following example enables that integration:

==== [source,java,indent=0] .{examplesdir}/pool/metrics/Application.java ---- Unresolved directive in http-client-conn-provider.adoc - include::{examplesdir}/pool/metrics/Application.java[lines=18..45] ---- <1> Enables the built-in integration with Micrometer ====

== SSL and TLS When you need SSL or TLS, you can apply the configuration shown in the next example. By default, if OpenSSL is available, a {nettyjavadoc}/io/netty/handler/ssl/SslProvider.html#OPENSSL[SslProvider.OPENSSL] provider is used as a provider. Otherwise, a {nettyjavadoc}/io/netty/handler/ssl/SslProvider.html#JDK[SslProvider.JDK] provider is used You can switch the provider by using {nettyjavadoc}/io/netty/handler/ssl/SslContextBuilder.html#sslProvider-io.netty.handler.ssl.SslProvider-[SslContextBuilder] or by setting -Dio.netty.handler.ssl.noOpenSsl=true. The following example uses SslContextBuilder:

==== [source,java,indent=0] .{examplesdir}/security/Application.java ---- Unresolved directive in http-client.adoc - include::{examplesdir}/security/Application.java[lines=18..35] ---- ====

=== Server Name Indication By default, the HTTP client sends the remote host name as SNI server name. When you need to change this default setting, you can configure the HTTP client as follows:

==== [source,java,indent=0] .{examplesdir}/sni/Application.java ---- Unresolved directive in http-client.adoc - include::{examplesdir}/sni/Application.java[lines=18..39] ---- ====

== Retry Strategies By default, the HTTP client retries the request once if it was aborted on the TCP level.

== HTTP/2

By default, the HTTP client supports HTTP/1.1. If you need HTTP/2, you can get it through configuration. In addition to the protocol configuration, if you need H2 but not H2C (cleartext), you must also configure SSL.

NOTE: As Application-Layer Protocol Negotiation (ALPN) is not supported “out-of-the-box” by JDK8 (although some vendors backported ALPN to JDK8), you need an additional dependency to a native library that supports it — for example, netty-tcnative-boringssl-static.

The following listing presents a simple H2 example:

==== [source,java,indent=0] .{examplesdir}/http2/H2Application.java ---- Unresolved directive in http-client.adoc - include::{examplesdir}/http2/H2Application.java[lines=18..42] ---- <1> Configures the client to support only HTTP/2 <2> Configures SSL ====

The following listing presents a simple H2C example:

==== [source,java,indent=0] .{examplesdir}/http2/H2CApplication.java ---- Unresolved directive in http-client.adoc - include::{examplesdir}/http2/H2CApplication.java[lines=18..41] ---- ====

=== Protocol Selection

==== [source,java,indent=0] .{sourcedir}/reactor/netty/http/HttpProtocol.java ---- Unresolved directive in http-client.adoc - include::{sourcedir}/reactor/netty/http/HttpProtocol.java[lines=24..52] ---- ====

== Proxy Support

Reactor Netty supports the proxy functionality provided by Netty and provides a way to specify non proxy hosts through the {javadoc}/reactor/netty/tcp/ProxyProvider.html[ProxyProvider] builder.

Netty’s HTTP proxy support always uses CONNECT method in order to establish a tunnel to the specified proxy regardless of the scheme that is used http or https. (More information: Netty enforce HTTP proxy to support HTTP CONNECT method). Some proxies might not support CONNECT method when the scheme is http or might need to be configured in order to support this way of communication. Sometimes this might be the reason for not being able to connect to the proxy. Consider checking the proxy documentation whether it supports or needs an additional configuration in order to support CONNECT method.

The following example uses ProxyProvider:

==== [source,java,indent=0] .{examplesdir}/proxy/Application.java ---- Unresolved directive in proxy.adoc - include::{examplesdir}/proxy/Application.java[lines=18..42] ---- <1> Configures the connection establishment timeout to 20 seconds. ====

== Metrics The HTTP client supports built-in integration with Micrometer. It exposes all metrics with a prefix of reactor.netty.http.client.

The following table provides information for the HTTP client metrics:

[width="100%",options="header"]

=======

metric name

type

description

reactor.netty.http.client.data.received

DistributionSummary

Amount of the data received, in bytes. See [observability-metrics-data-received]

reactor.netty.http.client.data.sent

DistributionSummary

Amount of the data sent, in bytes. See [observability-metrics-data-sent]

reactor.netty.http.client.errors

Counter

Number of errors that occurred. See [observability-metrics-errors-count]

reactor.netty.http.client.tls.handshake.time

Timer

Time spent for TLS handshake. See [observability-metrics-tls-handshake-time]

reactor.netty.http.client.connect.time

Timer

Time spent for connecting to the remote address. See [observability-metrics-connect-time]

reactor.netty.http.client.address.resolver

Timer

Time spent for resolving the address. See [observability-metrics-hostname-resolution-time]

reactor.netty.http.client.data.received.time

Timer

Time spent in consuming incoming data. See [observability-metrics-http-client-data-received-time]

reactor.netty.http.client.data.sent.time

Timer

Time spent in sending outgoing data. See [observability-metrics-http-client-data-sent-time]

reactor.netty.http.client.response.time

Timer

Total time for the request/response See [observability-metrics-http-client-response-time]

=======

These additional metrics are also available:

Pooled ConnectionProvider metrics

[width="100%",options="header"]

=======

metric name

type

description

reactor.netty.connection.provider.total.connections

Gauge

The number of all connections, active or idle. See [observability-metrics-total-connections]

reactor.netty.connection.provider.active.connections

Gauge

The number of the connections that have been successfully acquired and are in active use. See [observability-metrics-active-connections]

reactor.netty.connection.provider.max.connections

Gauge

The maximum number of active connections that are allowed. See [observability-metrics-max-connections]

reactor.netty.connection.provider.idle.connections

Gauge

The number of the idle connections. See [observability-metrics-idle-connections]

reactor.netty.connection.provider.pending.connections

Gauge

The number of requests that are waiting for a connection. See [observability-metrics-pending-connections]

reactor.netty.connection.provider.pending.connections.time

Timer

Time spent in pending acquire a connection from the connection pool. See [observability-metrics-pending-connections-time]

reactor.netty.connection.provider.max.pending.connections

Gauge

The maximum number of requests that will be queued while waiting for a ready connection. See [observability-metrics-max-pending-connections]

=======

The following table provides information for the HTTP client metrics when it is configured to serve HTTP/2 traffic:

[width="100%",options="header"]

=======

metric name

type

description

reactor.netty.connection.provider.active.streams

Gauge

The number of the active HTTP/2 streams. See [observability-metrics-active-streams]

reactor.netty.connection.provider.pending.streams

Gauge

The number of requests that are waiting for opening HTTP/2 stream. See [observability-metrics-pending-streams]

=======

ByteBufAllocator metrics

[width="100%",options="header"]

=======

metric name

type

description

reactor.netty.bytebuf.allocator.used.heap.memory

Gauge

The number of bytes reserved by heap buffer allocator. See [observability-metrics-used-heap-memory]

reactor.netty.bytebuf.allocator.used.direct.memory

Gauge

The number of bytes reserved by direct buffer allocator. See [observability-metrics-used-direct-memory]

reactor.netty.bytebuf.allocator.heap.arenas

Gauge

The number of heap arenas (when PooledByteBufAllocator). See [observability-metrics-heap-arenas]

reactor.netty.bytebuf.allocator.direct.arenas

Gauge

The number of direct arenas (when PooledByteBufAllocator). See [observability-metrics-direct-arenas]

reactor.netty.bytebuf.allocator.threadlocal.caches

Gauge

The number of thread local caches (when PooledByteBufAllocator). See [observability-metrics-thread-local-caches]

reactor.netty.bytebuf.allocator.small.cache.size

Gauge

The size of the small cache (when PooledByteBufAllocator). See [observability-metrics-small-cache-size]

reactor.netty.bytebuf.allocator.normal.cache.size

Gauge

The size of the normal cache (when PooledByteBufAllocator). See [observability-metrics-normal-cache-size]

reactor.netty.bytebuf.allocator.chunk.size

Gauge

The chunk size for an arena (when PooledByteBufAllocator). See [observability-metrics-chunk-size]

reactor.netty.bytebuf.allocator.active.heap.memory

Gauge

The actual bytes consumed by in-use buffers allocated from heap buffer pools (when PooledByteBufAllocator). See [observability-metrics-active-heap-memory]

reactor.netty.bytebuf.allocator.active.direct.memory

Gauge

The actual bytes consumed by in-use buffers allocated from direct buffer pools (when PooledByteBufAllocator). See [observability-metrics-active-direct-memory]

======= EventLoop metrics

[width="100%",options="header"]

=======

metric name

type

description

reactor.netty.eventloop.pending.tasks

Gauge

The number of tasks that are pending for processing on an event loop. See [observability-metrics-pending-tasks]

=======

The following example enables that integration:

==== [source,java,indent=0] .{examplesdir}/metrics/Application.java ---- Unresolved directive in http-client.adoc - include::{examplesdir}/metrics/Application.java[lines=18..51] ---- <1> Applies upper limit for the meters with URI tag <2> Templated URIs will be used as a URI tag value when possible <3> Enables the built-in integration with Micrometer ====

NOTE: In order to avoid a memory and CPU overhead of the enabled metrics, it is important to convert the real URIs to templated URIs when possible. Without a conversion to a template-like form, each distinct URI leads to the creation of a distinct tag, which takes a lot of memory for the metrics.

NOTE: Always apply an upper limit for the meters with URI tags. Configuring an upper limit on the number of meters can help in cases when the real URIs cannot be templated. You can find more information at maximumAllowableTags.

When HTTP 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:

==== [source,java,indent=0] .{examplesdir}/metrics/custom/Application.java ---- Unresolved directive in http-client.adoc - include::{examplesdir}/metrics/custom/Application.java[lines=18..35] ---- <1> Enables HTTP client metrics and provides {javadoc}/reactor/netty/http/client/HttpClientMetricsRecorder.html[HttpClientMetricsRecorder] implementation. ====

== Tracing The HTTP client supports built-in integration with Micrometer Tracing.

The following table provides information for the HTTP client spans:

[width="100%",options="header"]

=======

contextual name

description

HTTP <HTTP METHOD>

Information and total time for the request. See [observability-spans-http-client-response-span].

hostname resolution

Information and time spent for resolving the address. See [observability-spans-hostname-resolution-span].

connect

Information and time spent for connecting to the remote address. See [observability-spans-connect-span].

tls handshake

Information and time spent for TLS handshake. See [observability-spans-tls-handshake-span].

=======

The following example enables that integration. This concrete example uses Brave and reports the information to Zipkin. See the Micrometer Tracing documentation for OpenTelemetry setup.

==== [source,java,indent=0] .{examplesdir}/tracing/Application.java ---- Unresolved directive in http-client.adoc - include::{examplesdir}/tracing/Application.java[lines=18..90] ---- <1> Initializes Brave, Zipkin, and the Observation registry. <2> Templated URIs are used as an URI tag value when possible. <3> Enables the built-in integration with Micrometer. ====

The result in Zipkin looks like:

image::images/http-client-tracing.png[]

=== Access Current Observation Project Micrometer provides a library that assists with context propagation across different types of context mechanisms such as ThreadLocal, Reactor Context and others.

The following example shows how to use this library in a custom ChannelHandler:

==== [source,java,indent=0] .{examplesdir}/tracing/custom/Application.java ---- Unresolved directive in http-client.adoc - include::{examplesdir}/tracing/custom/Application.java[lines=18..85] ---- <1> Initializes Brave, Zipkin, and the Observation registry. <2> Templated URIs are used as an URI tag value when possible. <3> Enables the built-in integration with Micrometer. <4> Custom ChannelHandler that uses context propagation library. This concrete example overrides only ChannelOutboundHandlerAdapter#write, if it is needed, the same logic can be used for the rest of the methods. Also, this concrete example sets all ThreadLocal values for which there is a value in the given Channel, if another behaviour is needed please check context propagation library API. For example, you may want to set only some of the ThreadLocal values. ====

NOTE: When you enable Reactor Netty tracing within a framework, you may need to let Reactor Netty use the ObservationRegistry created by this framework. For this purpose you need to invoke {javadoc}/reactor/netty/Metrics.html#observationRegistry-io.micrometer.observation.ObservationRegistry-[reactor.netty.Metrics#observationRegistry]. You may also need to configure the Reactor Netty ObservationHandlers using the API provided by the framework.

== Unix Domain Sockets The HTTP client supports Unix Domain Sockets (UDS) when native transport is in use.

The following example shows how to use UDS support:

==== [source,java,indent=0] .{examplesdir}/uds/Application.java ---- Unresolved directive in http-client.adoc - include::{examplesdir}/uds/Application.java[lines=18..33] ---- <1> Specifies DomainSocketAddress that will be used ====

== Host Name Resolution By default, the HttpClient 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 HttpClient as follows:

==== [source,java,indent=0] .{examplesdir}/resolver/Application.java ---- Unresolved directive in http-client.adoc - include::{examplesdir}/resolver/Application.java[lines=18..39] ---- <1> The timeout of each DNS query performed by this resolver will be 500ms. ====

The following listing shows the available configurations. Additionally, TCP fallback is enabled by default.

[width="100%",options="header"]

=======

Configuration name

Description

bindAddressSupplier

The supplier of the local address to bind to.

cacheMaxTimeToLive

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 this max time to live. Default to Integer.MAX_VALUE.

cacheMinTimeToLive

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.

cacheNegativeTimeToLive

The time to live of the cache for the failed DNS queries (resolution: seconds). Default: 0.

completeOncePreferredResolved

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 DnsNameResolver#resolveAll(String). By default, this setting is enabled.

disableOptionalRecord

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.

disableRecursionDesired

Specifies whether this resolver has to send a DNS query with the recursion desired (RD) flag set. By default, this setting is enabled.

dnsAddressResolverGroupProvider

Sets a custom function to create a DnsAddressResolverGroup given a DnsNameResolverBuilder

hostsFileEntriesResolver

Sets a custom {nettyjavadoc}/io/netty/resolver/HostsFileEntriesResolver.html[HostsFileEntriesResolver] to be used for hosts file entries. Default: {nettyjavadoc}/io/netty/resolver/DefaultHostsFileEntriesResolver.html[DefaultHostsFileEntriesResolver].

maxPayloadSize

Sets the capacity of the datagram packet buffer (in bytes). Default: 4096.

maxQueriesPerResolve

Sets the maximum allowed number of DNS queries to send when resolving a host name. Default: 16.

ndots

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).

queryTimeout

Sets the timeout of each DNS query performed by this resolver (resolution: milliseconds). Default: 5000.

resolveCache

The cache to use to store resolved DNS entries.

resolvedAddressTypes

The list of the protocol families of the resolved address.

retryTcpOnTimeout

Specifies whether this resolver will also fallback to TCP if a timeout is detected. By default, the resolver will only try to use TCP if the response is marked as truncated.

roundRobinSelection

Enables an {nettyjavadoc}/io/netty/resolver/AddressResolverGroup.html[AddressResolverGroup] of {nettyjavadoc}/io/netty/resolver/dns/DnsNameResolver.html[DnsNameResolver] that supports random selection of destination addresses if multiple are provided by the nameserver. See {nettyjavadoc}/io/netty/resolver/dns/RoundRobinDnsAddressResolverGroup.html[RoundRobinDnsAddressResolverGroup]. Default: {nettyjavadoc}/io/netty/resolver/dns/DnsAddressResolverGroup.html[DnsAddressResolverGroup]

runOn

Performs the communication with the DNS servers on the given {javadoc}/reactor/netty/resources/LoopResources.html[LoopResources]. By default, the LoopResources specified on the client level are used.

searchDomains

The list of search domains of the resolver. By default, the effective search domain list is populated by using the system DNS search domains.

trace

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 HttpClient as follows:

==== [source,java,indent=0] .{examplesdir}/resolver/custom/Application.java ---- Unresolved directive in http-client.adoc - include::{examplesdir}/resolver/custom/Application.java[lines=18..38] ---- <1> Sets the JVM built-in resolver. ====

== Timeout Configuration This section describes various timeout configuration options that can be used in HttpClient. Configuring a proper timeout may improve or solve issues in the communication process. The configuration options can be grouped as follows:

* [connection-pool-timeout] * [http-client-timeout] [response-timeout] [connection-timeout] [ssl-tls-timeout] [proxy-timeout] [dns-timeout]

=== Connection Pool Timeout By default, HttpClient uses a connection pool. When a request is completed successfully and if the connection is not scheduled for closing, the connection is returned to the connection pool and can thus be reused for processing another request. The connection may be reused immediately for another request or may stay idle in the connection pool for some time.

The following list describes the available timeout configuration options:

* maxIdleTime - The maximum time (resolution: ms) that this connection stays idle in the connection pool. By default, {javadoc}/reactor/netty/resources/ConnectionProvider.ConnectionPoolSpec.html#maxIdleTime-java.time.Duration-[maxIdleTime] is not specified.

NOTE: When you configure maxIdleTime, you should consider the idle timeout configuration on the target server. Choose a configuration that is equal to or less than the one on the target server. By doing so, you can reduce the I/O issues caused by a connection closed by the target server.

* maxLifeTime - The maximum time (resolution: ms) that this connection stays alive. By default, {javadoc}/reactor/netty/resources/ConnectionProvider.ConnectionPoolSpec.html#maxLifeTime-java.time.Duration-[maxLifeTime] is not specified. * pendingAcquireTimeout - The maximum time (resolution: ms) after which a pending acquire operation must complete, or a PoolAcquireTimeoutException is thrown. Default: 45s.

By default, these timeouts are checked on connection release or acquire operations and, if some timeout is reached, the connection is closed and removed from the connection pool. However, you can also configure the connection pool, by setting evictInBackground, to perform periodic checks on connections.

To customize the default settings, you can configure HttpClient as follows:

==== [source,java,indent=0] .{examplesdir}/pool/Application.java ---- Unresolved directive in http-client.adoc - include::{examplesdir}/pool/config/Application.java[lines=18..50] ---- <1> Configures the maximum time for a connection to stay idle to 20 seconds. <2> Configures the maximum time for a connection to stay alive to 60 seconds. <3> Configures the maximum time for the pending acquire operation to 60 seconds. <4> Every two minutes, the connection pool is regularly checked for connections that are applicable for removal. ====

=== HttpClient Timeout This section provides information for the various timeout configuration options at the HttpClient level.

NOTE: Reactor Netty uses Reactor Core as its Reactive Streams implementation, and you may want to use the timeout operator that Mono and Flux provide. Keep in mind, however, that it is better to use the more specific timeout configuration options available in Reactor Netty, since they provide more control for a specific purpose and use case. By contrast, the timeout operator can only apply to the operation as a whole, from establishing the connection to the remote peer to receiving the response.

==== Response Timeout HttpClient provides an API for configuring a default response timeout for all requests. You can change this default response timeout through an API for a specific request. By default, {javadoc}/reactor/netty/http/client/HttpClient.html#responseTimeout-java.time.Duration-[responseTimeout] is not specified.

NOTE: It is always a good practice to configure a response timeout.

To customize the default settings, you can configure HttpClient as follows:

==== [source,java,indent=0] .{examplesdir}/read/timeout/Application.java ---- Unresolved directive in http-client.adoc - include::{examplesdir}/read/timeout/Application.java[lines=18..55] ---- <1> Configures the default response timeout to 1 second. <2> Configures a response timeout for a specific request to 2 seconds. ====

==== Connection Timeout The following listing shows all available connection timeout configuration options, but some of them may apply only to a specific transport.

* CONNECT_TIMEOUT_MILLIS - If the connection establishment attempt to the remote peer does not finish within the configured connect timeout (resolution: ms), the connection establishment attempt fails. Default: 30s. * SO_KEEPALIVE - When the connection stays idle for some time (the time is implementation dependent, but the default is typically two hours), TCP automatically sends a keepalive probe to the remote peer. By default, SO_KEEPALIVE is not enabled. When you run with Epoll/NIO (since Java 11 on Mac or Linux) transport, you may also configure: TCP_KEEPIDLE - The maximum time (resolution: seconds) that this connection stays idle before TCP starts sending keepalive probes, if SO_KEEPALIVE has been set. The maximum time is implementation dependent, but the default is typically two hours. TCP_KEEPINTVL (Epoll)/TCP_KEEPINTERVAL (NIO) - The time (resolution: seconds) between individual keepalive probes. TCP_KEEPCNT (Epoll)/TCP_KEEPCOUNT (NIO) - The maximum number of keepalive probes TCP should send before dropping the connection.

NOTE: Sometimes, between the client and the server, you may have a network component that silently drops the idle connections without sending a response. From the Reactor Netty point of view, in this use case, the remote peer just does not respond. To be able to handle such a use case you may consider configuring SO_KEEPALIVE.

To customize the default settings, you can configure HttpClient as follows:

==== [source,java,indent=0] .{examplesdir}/channeloptions/Application.java ---- Unresolved directive in http-client.adoc - include::{examplesdir}/channeloptions/Application.java[lines=18..54] ---- <1> Configures the connection establishment timeout to 10 seconds. <2> Enables TCP keepalive. This means that TCP starts sending keepalive probes when a connection is idle for some time. <3> The connection needs to remain idle for 5 minutes before TCP starts sending keepalive probes. <4> Configures the time between individual keepalive probes to 1 minute. <5> Configures the maximum number of TCP keepalive probes to 8. ====

==== SSL/TLS Timeout HttpClient supports the SSL/TLS functionality provided by Netty.

The following list describes the available timeout configuration options:

* handshakeTimeout - Use this option to configure the SSL handshake timeout (resolution: ms). Default: 10s.

NOTE: You should consider increasing the SSL handshake timeout when expecting slow network connections.

* closeNotifyFlushTimeout - Use this option to configure the SSL close_notify flush timeout (resolution: ms). Default: 3s. * closeNotifyReadTimeout - Use this option to configure the SSL close_notify read timeout (resolution: ms). Default: 0s.

To customize the default settings, you can configure HttpClient as follows:

==== [source,java,indent=0] .{examplesdir}/security/custom/Application.java ---- Unresolved directive in http-client.adoc - include::{examplesdir}/security/custom/Application.java[lines=18..45] ---- <1> Configures the SSL handshake timeout to 30 seconds. <2> Configures the SSL close_notify flush timeout to 10 seconds. <3> Configures the SSL close_notify read timeout to 10 seconds. ====

==== Proxy Timeout HttpClient supports the proxy functionality provided by Netty and provides a way to specify the {javadoc}/reactor/netty/transport/ProxyProvider.Builder.html#connectTimeoutMillis-long-[connection establishment timeout]. If the connection establishment attempt to the remote peer does not finish within the timeout, the connection establishment attempt fails. Default: 10s.

To customize the default settings, you can configure HttpClient as follows:

==== [source,java,indent=0] .{examplesdir}/proxy/Application.java ---- Unresolved directive in http-client.adoc - include::{examplesdir}/proxy/Application.java[lines=18..42] ---- <1> Configures the connection establishment timeout to 20 seconds. ====

==== Host Name Resolution Timeout By default, the HttpClient uses Netty’s domain name lookup mechanism to resolve a domain name asynchronously.

The following list describes the available timeout configuration options:

* cacheMaxTimeToLive - The maximum 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 maximum time to live, this resolver ignores the time to live from the DNS server and uses this maximum time to live. Default: Integer.MAX_VALUE. * cacheMinTimeToLive - The minimum 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 minimum time to live, this resolver ignores the time to live from the DNS server and uses this minimum time to live. Default: 0s. * cacheNegativeTimeToLive - The time to live of the cache for the failed DNS queries (resolution: seconds). Default: 0s. * queryTimeout - Sets the timeout of each DNS query performed by this resolver (resolution: milliseconds). Default: 5s.

To customize the default settings, you can configure HttpClient as follows:

==== [source,java,indent=0] .{examplesdir}/resolver/Application.java ---- Unresolved directive in http-client.adoc - include::{examplesdir}/resolver/Application.java[lines=18..39] ---- <1> The timeout of each DNS query performed by this resolver will be 500ms. ====

:leveloffset: 3 Suggest Edit to "[http-client]"

:leveloffset: 1

:sourcedir: ./../../reactor-netty-core/src/main/java :examplesdir: ./../../reactor-netty-examples/src/main/java/reactor/netty/examples/documentation/udp/server :javadoc: https://projectreactor.io/docs/netty/1.1.25-SNAPSHOT/api :nettyjavadoc: https://netty.io/4.1/api :wirelogger: reactor.netty.udp.UdpServer

= UDP Server

Reactor Netty provides the easy-to-use and easy-to-configure {javadoc}/reactor/netty/udp/UdpServer.html[UdpServer]. It hides most of the Netty functionality that is required to create a UDP server and adds Reactive Streams backpressure.

== Starting and Stopping

To start a UDP server, a {javadoc}/reactor/netty/udp/UdpServer.html[UdpServer] instance has to be created and configured. By default, the host is configured to be localhost and the port is 12012. The following example shows how to create and start a UDP server:

==== [source,java,indent=0] .{examplesdir}/create/Application.java ---- Unresolved directive in udp-server.adoc - include::{examplesdir}/create/Application.java[lines=18..32] ---- <1> Creates a {javadoc}/reactor/netty/udp/UdpServer.html[UdpServer] instance that is ready for configuring. <2> Starts the server in a blocking fashion and waits for it to finish initializing. ====

The returned {javadoc}/reactor/netty/Connection.html[Connection] offers a simple server API, including {javadoc}/reactor/netty/DisposableChannel.html#disposeNow-java.time.Duration-[disposeNow()], which shuts the server down in a blocking fashion.

=== Host and Port

In order to serve on a specific host and port, you can apply the following configuration to the UDP server:

==== [source,java,indent=0] .{examplesdir}/address/Application.java ---- Unresolved directive in udp-server.adoc - include::{examplesdir}/address/Application.java[lines=18..34] ---- <1> Configures the UDP server host <2> Configures the UDP server port ====

NOTE: The port can be specified also with PORT environment variable.

== Eager Initialization

By default, the initialization of the UdpServer resources happens on demand. This means that the bind operation absorbs the extra time needed to initialize and load:

* the event loop group * the native transport libraries (when native transport is used)

When you need to preload these resources, you can configure the UdpServer as follows:

==== [source,java,indent=0] .{examplesdir}/warmup/Application.java ---- Unresolved directive in udp-server.adoc - include::{examplesdir}/warmup/Application.java[lines=18..51] ---- <1> Initialize and load the event loop group and the native transport libraries ====

== Writing Data

To send data to the remote peer, you must attach an I/O handler. The I/O handler has access to {javadoc}/reactor/netty/udp/UdpOutbound.html[UdpOutbound], to be able to write data. The following example shows how to send hello:

==== [source,java,indent=0] .{examplesdir}/send/Application.java ---- Unresolved directive in udp-server.adoc - include::{examplesdir}/send/Application.java[lines=18..51] ---- <1> Sends a hello string to the remote peer ====

== Consuming Data

To receive data from a remote peer, you must attach an I/O handler. The I/O handler has access to {javadoc}/reactor/netty/udp/UdpInbound.html[UdpInbound], to be able to read data. The following example shows how to consume data:

==== [source,java,indent=0] .{examplesdir}/read/Application.java ---- Unresolved directive in udp-server.adoc - include::{examplesdir}/read/Application.java[lines=18..47] ---- <1> Receives data from the remote peer ====

== Lifecycle Callbacks

The following lifecycle callbacks are provided to let you extend the UdpServer:

[width="100%",options="header"]

=======

Callback

Description

doOnBind

Invoked when the server channel is about to bind.

doOnBound

Invoked when the server channel is bound.

doOnChannelInit

Invoked when initializing the channel.

doOnUnbound

Invoked when the server channel is unbound.

=======

The following example uses the doOnBound and doOnChannelInit callbacks:

==== [source,java,indent=0] .{examplesdir}/lifecycle/Application.java ---- Unresolved directive in udp-server.adoc - include::{examplesdir}/lifecycle/Application.java[lines=18..39] ---- <1> Netty pipeline is extended with LineBasedFrameDecoder when the server channel is bound. <2> Netty pipeline is extended with LoggingHandler when initializing the channel. ====

== Connection Configuration

This section describes three kinds of configuration that you can use at the UDP level:

* [server-udp-connection-configurations-channel-options] * [server-udp-connection-configurations-wire-logger] * [server-udp-connection-configurations-event-loop-group]

=== Channel Options

By default, the UDP server is configured with the following options:

==== [source,java,indent=0] .{sourcedir}/reactor/netty/udp/UdpServerBind.java ---- Unresolved directive in udp-server.adoc - include::{sourcedir}/reactor/netty/udp/UdpServerBind.java[lines=40..44] ---- ====

If you need additional options or need to change the current options, you can apply the following configuration:

==== [source,java,indent=0] .{examplesdir}/channeloptions/Application.java ---- Unresolved directive in udp-server.adoc - include::{examplesdir}/channeloptions/Application.java[lines=18..34] ---- ====

For more information about Netty channel options, see the following links:

* {nettyjavadoc}/io/netty/channel/ChannelOption.html[Common ChannelOption] * {nettyjavadoc}/io/netty/channel/epoll/EpollChannelOption.html[Epoll ChannelOption] * {nettyjavadoc}/io/netty/channel/kqueue/KQueueChannelOption.html[KQueue ChannelOption] * Socket Options

:formattersourcedir: ./../../reactor-netty-core/src/main/java

=== Wire Logger

Reactor Netty provides wire logging for when the traffic between the peers needs to be inspected. By default, wire logging is disabled. To enable it, you must set the logger {wirelogger} level to DEBUG and apply the following configuration:

==== [source,java,indent=0] .{examplesdir}/wiretap/Application.java ---- Unresolved directive in wire-logger.adoc - include::{examplesdir}/wiretap/Application.java[lines=18..35] ---- <1> Enables the wire logging ====

==== Wire Logger formatters Reactor Netty supports 3 different formatters:

- {javadoc}/reactor/netty/transport/logging/AdvancedByteBufFormat.html#HEX_DUMP[AdvancedByteBufFormat#HEX_DUMP] - the default

==== [source,java,indent=0] .{sourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java ---- Unresolved directive in wire-logger.adoc - include::{formattersourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java[lines=47..75] ---- ====

- {javadoc}/reactor/netty/transport/logging/AdvancedByteBufFormat.html#SIMPLE[AdvancedByteBufFormat#SIMPLE]

==== [source,java,indent=0] .{sourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java ---- Unresolved directive in wire-logger.adoc - include::{formattersourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java[lines=34..45] ---- ====

- {javadoc}/reactor/netty/transport/logging/AdvancedByteBufFormat.html#TEXTUAL[AdvancedByteBufFormat#TEXTUAL]

==== [source,java,indent=0] .{sourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java ---- Unresolved directive in wire-logger.adoc - include::{formattersourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java[lines=77..93] ---- ====

When you need to change the default formatter you can configure it as follows:

==== [source,java,indent=0] .{examplesdir}/wiretap/custom/Application.java ---- Unresolved directive in wire-logger.adoc - include::{examplesdir}/wiretap/custom/Application.java[lines=18..38] ---- <1> Enables the wire logging, {javadoc}/reactor/netty/transport/logging/AdvancedByteBufFormat.html#TEXTUAL[AdvancedByteBufFormat#TEXTUAL] is used for printing the content. ====

:eventloopsourcedir: ./../../reactor-netty-core/src/main/java

=== Event Loop Group

By default Reactor Netty 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). This “Event Loop Group” is shared between all servers and clients in one JVM. When you need a different configuration, you can use one of the {javadoc}/reactor/netty/resources/LoopResources.html[LoopResources]#create methods.

The following listing shows the default configuration for the Event Loop Group:

==== [source,java,indent=0] .{eventloopsourcedir}/reactor/netty/ReactorNetty.java ---- Unresolved directive in eventloop.adoc - include::{eventloopsourcedir}/reactor/netty/ReactorNetty.java[lines=87..121] ---- ====

If you need changes to these settings, you can apply the following configuration:

==== [source,java,indent=0] .{examplesdir}/eventloop/Application.java ---- Unresolved directive in eventloop.adoc - include::{examplesdir}/eventloop/Application.java[lines=18..38] ---- ====

==== Disposing Event Loop Group

- If you use the default Event Loop Group provided by Reactor Netty, invoke {javadoc}/reactor/netty/http/HttpResources.html[HttpResources]#disposeLoopsAndConnections/#disposeLoopsAndConnectionsLater method.

NOTE: Disposing HttpResources means that every server/client that is using it, will not be able to use it anymore!

- If you use custom LoopResources, invoke {javadoc}/reactor/netty/resources/LoopResources.html[LoopResources]#dispose/#disposeLater method.

NOTE: Disposing the custom LoopResources means that every server/client that is configured to use it, will not be able to use it anymore!

== Metrics The UDP server supports built-in integration with Micrometer. It exposes all metrics with a prefix of reactor.netty.udp.server.

The following table provides information for the UDP server metrics:

[width="100%",options="header"]

=======

metric name

type

description

reactor.netty.udp.server.data.received

DistributionSummary

Amount of the data received, in bytes. See [observability-metrics-data-received]

reactor.netty.udp.server.data.sent

DistributionSummary

Amount of the data sent, in bytes. See [observability-metrics-data-sent]

reactor.netty.udp.server.errors

Counter

Number of errors that occurred. See [observability-metrics-errors-count]

=======

These additional metrics are also available:

ByteBufAllocator metrics

[width="100%",options="header"]

=======

metric name

type

description

reactor.netty.bytebuf.allocator.used.heap.memory

Gauge

The number of bytes reserved by heap buffer allocator. See [observability-metrics-used-heap-memory]

reactor.netty.bytebuf.allocator.used.direct.memory

Gauge

The number of bytes reserved by direct buffer allocator. See [observability-metrics-used-direct-memory]

reactor.netty.bytebuf.allocator.heap.arenas

Gauge

The number of heap arenas (when PooledByteBufAllocator). See [observability-metrics-heap-arenas]

reactor.netty.bytebuf.allocator.direct.arenas

Gauge

The number of direct arenas (when PooledByteBufAllocator). See [observability-metrics-direct-arenas]

reactor.netty.bytebuf.allocator.threadlocal.caches

Gauge

The number of thread local caches (when PooledByteBufAllocator). See [observability-metrics-thread-local-caches]

reactor.netty.bytebuf.allocator.small.cache.size

Gauge

The size of the small cache (when PooledByteBufAllocator). See [observability-metrics-small-cache-size]

reactor.netty.bytebuf.allocator.normal.cache.size

Gauge

The size of the normal cache (when PooledByteBufAllocator). See [observability-metrics-normal-cache-size]

reactor.netty.bytebuf.allocator.chunk.size

Gauge

The chunk size for an arena (when PooledByteBufAllocator). See [observability-metrics-chunk-size]

reactor.netty.bytebuf.allocator.active.heap.memory

Gauge

The actual bytes consumed by in-use buffers allocated from heap buffer pools (when PooledByteBufAllocator). See [observability-metrics-active-heap-memory]

reactor.netty.bytebuf.allocator.active.direct.memory

Gauge

The actual bytes consumed by in-use buffers allocated from direct buffer pools (when PooledByteBufAllocator). See [observability-metrics-active-direct-memory]

======= EventLoop metrics

[width="100%",options="header"]

=======

metric name

type

description

reactor.netty.eventloop.pending.tasks

Gauge

The number of tasks that are pending for processing on an event loop. See [observability-metrics-pending-tasks]

=======

The following example enables that integration:

==== [source,java,indent=0] .{examplesdir}/metrics/Application.java ---- Unresolved directive in udp-server.adoc - include::{examplesdir}/metrics/Application.java[lines=18..34] ---- <1> Enables the built-in integration with Micrometer ====

When UDP server 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:

==== [source,java,indent=0] .{examplesdir}/metrics/custom/Application.java ---- Unresolved directive in udp-server.adoc - include::{examplesdir}/metrics/custom/Application.java[lines=18..35] ---- <1> Enables UDP server metrics and provides {javadoc}/reactor/netty/channel/ChannelMetricsRecorder.html[ChannelMetricsRecorder] implementation. ====

== Unix Domain Sockets The UdpServer supports Unix Domain Datagram Sockets (UDS) when native transport is in use.

The following example shows how to use UDS support:

==== [source,java,indent=0] .{examplesdir}/uds/Application.java ---- Unresolved directive in udp-server.adoc - include::{examplesdir}/uds/Application.java[lines=18..48] ---- <1> Specifies DomainSocketAddress that will be used ====

:leveloffset: 3 Suggest Edit to "[udp-server]"

:leveloffset: 1

:sourcedir: ./../../reactor-netty-core/src/main/java :examplesdir: ./../../reactor-netty-examples/src/main/java/reactor/netty/examples/documentation/udp/client :javadoc: https://projectreactor.io/docs/netty/1.1.25-SNAPSHOT/api :nettyjavadoc: https://netty.io/4.1/api :wirelogger: reactor.netty.udp.UdpClient

= UDP Client

Reactor Netty provides the easy-to-use and easy-to-configure {javadoc}/reactor/netty/udp/UdpClient.html[UdpClient]. It hides most of the Netty functionality that is required to create a UDP client and adds Reactive Streams backpressure.

== Connecting and Disconnecting

To connect the UDP client to a given endpoint, you must create and configure a {javadoc}/reactor/netty/udp/UdpClient.html[UdpClient] instance. By default, the host is configured for localhost and the port is 12012. The following example shows how to create and connect a UDP client:

==== [source,java,indent=0] .{examplesdir}/create/Application.java ---- Unresolved directive in udp-client.adoc - include::{examplesdir}/create/Application.java[lines=18..32] ---- <1> Creates a {javadoc}/reactor/netty/udp/UdpClient.html[UdpClient] instance that is ready for configuring. <2> Connects the client in a blocking fashion and waits for it to finish initializing. ====

The returned {javadoc}/reactor/netty/Connection.html[Connection] offers a simple connection API, including {javadoc}/reactor/netty/DisposableChannel.html#disposeNow-java.time.Duration-[disposeNow()], which shuts the client down in a blocking fashion.

=== Host and Port

To connect to a specific host and port, you can apply the following configuration to the UDP client:

==== [source,java,indent=0] .{examplesdir}/address/Application.java ---- Unresolved directive in udp-client.adoc - include::{examplesdir}/address/Application.java[lines=18..34] ---- <1> Configures the host to which this client should connect <2> Configures the port to which this client should connect ====

NOTE: The port can be specified also with PORT environment variable.

== Eager Initialization

By default, the initialization of the UdpClient 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)

When you need to preload these resources, you can configure the UdpClient as follows:

==== [source,java,indent=0] .{examplesdir}/warmup/Application.java ---- Unresolved directive in udp-client.adoc - include::{examplesdir}/warmup/Application.java[lines=18..40] ---- <1> Initialize and load the event loop group, the host name resolver, and the native transport libraries <2> Host name resolution happens when connecting to the remote peer ====

== Writing Data

To send data to a given peer, you must attach an I/O handler. The I/O handler has access to {javadoc}/reactor/netty/udp/UdpOutbound.html[UdpOutbound], to be able to write data.

The following example shows how to send hello:

==== [source,java,indent=0] .{examplesdir}/send/Application.java ---- Unresolved directive in udp-client.adoc - include::{examplesdir}/send/Application.java[lines=18..37] ---- <1> Sends hello string to the remote peer. ====

== Consuming Data

To receive data from a given peer, you must attach an I/O handler. The I/O handler has access to {javadoc}/reactor/netty/udp/UdpInbound.html[UdpInbound], to be able to read data. The following example shows how to consume data:

==== [source,java,indent=0] .{examplesdir}/read/Application.java ---- Unresolved directive in udp-client.adoc - include::{examplesdir}/read/Application.java[lines=18..35] ---- <1> Receives data from a given peer ====

== Lifecycle Callbacks

The following lifecycle callbacks are provided to let you extend the UdpClient:

[width="100%",options="header"]

=======

Callback

Description

doAfterResolve

Invoked after the remote address has been resolved successfully.

doOnChannelInit

Invoked when initializing the channel.

doOnConnect

Invoked when the channel is about to connect.

doOnConnected

Invoked after the channel has been connected.

doOnDisconnected

Invoked after the channel has been disconnected.

doOnResolve

Invoked when the remote address is about to be resolved.

doOnResolveError

Invoked in case the remote address hasn’t been resolved successfully.

=======

The following example uses the doOnConnected and doOnChannelInit callbacks:

==== [source,java,indent=0] .{examplesdir}/lifecycle/Application.java ---- Unresolved directive in udp-client.adoc - include::{examplesdir}/lifecycle/Application.java[lines=18..40] ---- <1> Netty pipeline is extended with LineBasedFrameDecoder when the channel has been connected. <2> Netty pipeline is extended with LoggingHandler when initializing the channel. ====

== Connection Configuration

This section describes three kinds of configuration that you can use at the UDP level:

* [client-udp-connection-configurations-channel-options] * [client-udp-connection-configurations-wire-logger] * [client-udp-connection-configurations-event-loop-group]

=== Channel Options

By default, the UDP client is configured with the following options:

==== [source,java,indent=0] .{sourcedir}/reactor/netty/udp/UdpClientConnect.java ---- Unresolved directive in udp-client.adoc - include::{sourcedir}/reactor/netty/udp/UdpClientConnect.java[lines=37..42] ---- ====

If you need additional options or need to change the current options, you can apply the following configuration:

==== [source,java,indent=0] .{examplesdir}/channeloptions/Application.java ---- Unresolved directive in udp-client.adoc - include::{examplesdir}/channeloptions/Application.java[lines=18..36] ---- ====

You can find more about Netty channel options at the following links:

* {nettyjavadoc}/io/netty/channel/ChannelOption.html[Common ChannelOption] * {nettyjavadoc}/io/netty/channel/epoll/EpollChannelOption.html[Epoll ChannelOption] * {nettyjavadoc}/io/netty/channel/kqueue/KQueueChannelOption.html[KQueue ChannelOption] * Socket Options

:formattersourcedir: ./../../reactor-netty-core/src/main/java

=== Wire Logger

Reactor Netty provides wire logging for when the traffic between the peers needs to be inspected. By default, wire logging is disabled. To enable it, you must set the logger {wirelogger} level to DEBUG and apply the following configuration:

==== [source,java,indent=0] .{examplesdir}/wiretap/Application.java ---- Unresolved directive in wire-logger.adoc - include::{examplesdir}/wiretap/Application.java[lines=18..35] ---- <1> Enables the wire logging ====

==== Wire Logger formatters Reactor Netty supports 3 different formatters:

- {javadoc}/reactor/netty/transport/logging/AdvancedByteBufFormat.html#HEX_DUMP[AdvancedByteBufFormat#HEX_DUMP] - the default

==== [source,java,indent=0] .{sourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java ---- Unresolved directive in wire-logger.adoc - include::{formattersourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java[lines=47..75] ---- ====

- {javadoc}/reactor/netty/transport/logging/AdvancedByteBufFormat.html#SIMPLE[AdvancedByteBufFormat#SIMPLE]

==== [source,java,indent=0] .{sourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java ---- Unresolved directive in wire-logger.adoc - include::{formattersourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java[lines=34..45] ---- ====

- {javadoc}/reactor/netty/transport/logging/AdvancedByteBufFormat.html#TEXTUAL[AdvancedByteBufFormat#TEXTUAL]

==== [source,java,indent=0] .{sourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java ---- Unresolved directive in wire-logger.adoc - include::{formattersourcedir}/reactor/netty/transport/logging/AdvancedByteBufFormat.java[lines=77..93] ---- ====

When you need to change the default formatter you can configure it as follows:

==== [source,java,indent=0] .{examplesdir}/wiretap/custom/Application.java ---- Unresolved directive in wire-logger.adoc - include::{examplesdir}/wiretap/custom/Application.java[lines=18..38] ---- <1> Enables the wire logging, {javadoc}/reactor/netty/transport/logging/AdvancedByteBufFormat.html#TEXTUAL[AdvancedByteBufFormat#TEXTUAL] is used for printing the content. ====

:eventloopsourcedir: ./../../reactor-netty-core/src/main/java

=== Event Loop Group

By default Reactor Netty 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). This “Event Loop Group” is shared between all servers and clients in one JVM. When you need a different configuration, you can use one of the {javadoc}/reactor/netty/resources/LoopResources.html[LoopResources]#create methods.

The following listing shows the default configuration for the Event Loop Group:

==== [source,java,indent=0] .{eventloopsourcedir}/reactor/netty/ReactorNetty.java ---- Unresolved directive in eventloop.adoc - include::{eventloopsourcedir}/reactor/netty/ReactorNetty.java[lines=87..121] ---- ====

If you need changes to these settings, you can apply the following configuration:

==== [source,java,indent=0] .{examplesdir}/eventloop/Application.java ---- Unresolved directive in eventloop.adoc - include::{examplesdir}/eventloop/Application.java[lines=18..38] ---- ====

==== Disposing Event Loop Group

- If you use the default Event Loop Group provided by Reactor Netty, invoke {javadoc}/reactor/netty/http/HttpResources.html[HttpResources]#disposeLoopsAndConnections/#disposeLoopsAndConnectionsLater method.

NOTE: Disposing HttpResources means that every server/client that is using it, will not be able to use it anymore!

- If you use custom LoopResources, invoke {javadoc}/reactor/netty/resources/LoopResources.html[LoopResources]#dispose/#disposeLater method.

NOTE: Disposing the custom LoopResources means that every server/client that is configured to use it, will not be able to use it anymore!

== Metrics The UDP client supports built-in integration with Micrometer. It exposes all metrics with a prefix of reactor.netty.udp.client.

The following table provides information for the UDP client metrics:

[width="100%",options="header"]

=======

metric name

type

description

reactor.netty.udp.client.data.received

DistributionSummary

Amount of the data received, in bytes. See [observability-metrics-data-received]

reactor.netty.udp.client.data.sent

DistributionSummary

Amount of the data sent, in bytes. See [observability-metrics-data-sent]

reactor.netty.udp.client.errors

Counter

Number of errors that occurred. See [observability-metrics-errors-count]

reactor.netty.udp.client.connect.time

Timer

Time spent for connecting to the remote address. See [observability-metrics-connect-time]

reactor.netty.udp.client.address.resolver

Timer

Time spent for resolving the address. See [observability-metrics-hostname-resolution-time]

=======

These additional metrics are also available:

ByteBufAllocator metrics

[width="100%",options="header"]

=======

metric name

type

description

reactor.netty.bytebuf.allocator.used.heap.memory

Gauge

The number of bytes reserved by heap buffer allocator. See [observability-metrics-used-heap-memory]

reactor.netty.bytebuf.allocator.used.direct.memory

Gauge

The number of bytes reserved by direct buffer allocator. See [observability-metrics-used-direct-memory]

reactor.netty.bytebuf.allocator.heap.arenas

Gauge

The number of heap arenas (when PooledByteBufAllocator). See [observability-metrics-heap-arenas]

reactor.netty.bytebuf.allocator.direct.arenas

Gauge

The number of direct arenas (when PooledByteBufAllocator). See [observability-metrics-direct-arenas]

reactor.netty.bytebuf.allocator.threadlocal.caches

Gauge

The number of thread local caches (when PooledByteBufAllocator). See [observability-metrics-thread-local-caches]

reactor.netty.bytebuf.allocator.small.cache.size

Gauge

The size of the small cache (when PooledByteBufAllocator). See [observability-metrics-small-cache-size]

reactor.netty.bytebuf.allocator.normal.cache.size

Gauge

The size of the normal cache (when PooledByteBufAllocator). See [observability-metrics-normal-cache-size]

reactor.netty.bytebuf.allocator.chunk.size

Gauge

The chunk size for an arena (when PooledByteBufAllocator). See [observability-metrics-chunk-size]

reactor.netty.bytebuf.allocator.active.heap.memory

Gauge

The actual bytes consumed by in-use buffers allocated from heap buffer pools (when PooledByteBufAllocator). See [observability-metrics-active-heap-memory]

reactor.netty.bytebuf.allocator.active.direct.memory

Gauge

The actual bytes consumed by in-use buffers allocated from direct buffer pools (when PooledByteBufAllocator). See [observability-metrics-active-direct-memory]

======= EventLoop metrics

[width="100%",options="header"]

=======

metric name

type

description

reactor.netty.eventloop.pending.tasks