You're seeing the release note of an old version. Check out the latest release note.
v1.27.0
January 30, 2024
🌟 New features
-
xDS-based EndpointGroup: You can utilize xDS protocol to create
XdsEndpointGroupfor service discovery. #5342 #5336XdsBootstrap bootstrap = XdsBootstrap.of(...);
EndpointGroup endpointGroup = XdsEndpointGroup.of(boostrap.listenerRoot("my-envoy-service"));
WebClient client = WebClient.of(SessionProtocol.HTTP, endpointGroup); -
GraphQL Subscriptions over WebSocket: You can now enable GraphQL subscriptions over WebSocket for live updates to your clients. #4999 #5280
GraphqlService
.builder()
.enableWebSocket(true)
.webSocketServiceCustomizer(ws -> {
// Customize the underlying WebSocket service.
})
.build(); -
Service-specific EventLoopGroup: You can now assign a different
EventLoopGroupto each service for finer grained resource control. #4099 #5233Server
.builder()
.serviceWorkerGroup(globalServiceWorkerGroup)
.route()
.path("/user")
// Use userServiceWorkerGroup for the user service.
.serviceWorkerGroup(userServiceWorkerGroup)
.build(userService)
.route()
.path("/api")
// Use apiServiceWorkerGroup for the API service.
.serviceWorkerGroup(apiServiceWorkerGroup)
.build(apiService)
.build(); -
Thrift Service Decorators: You can now use
@Decoratorannotations to conveniently apply custom decorators to Thrift services. #4230 #5356@Decorator(ClassDecorator.class)
class MyHelloService implements HelloService.AsyncIface {
@Decorator(MethodDecorator.class)
@Override
public void hello(String name, AsyncMethodCallback<String> handler) throws TException {
...
}
} -
Sensitive Header Masking: You can now easily mask request and response headers using
HeadersSanitizer. #5175 #5188HeadersSanitizer<String> headersSanitizer =
HeadersSanitizer
.builderForText()
.sensitiveHeaders("Authorization", "API-Key", "Proxy-Authorization")
...
.build();
LogFormatter
.builderForText()
.requestHeadersSanitizer(headersSanitizer)
... -
Custom Exception Handling for gRPC clients: You can customize how your gRPC clients respond to exceptions by implementing
GrpcExceptionHandlerFunction. #5347 #5351GrpcClients
.builder("https://my-grpc-server.com")
.exceptionHandler((ctx, cause, metadata) -> {
// Handle the exception.
return Status.INTERNAL.withDescription("Something went wrong");
}) -
Kubernetes Client Integration: You can now use the popular Fabric Kubernetes client seamlessly on top of Armeria when using the
armeria-kubernetesmodule. #5167 -
WebSocket Service Fallback: You can now set up a fallback service for
WebSocketServiceto handle both WebSocket and non-WebSocket requests on the same path withWebSocketServiceBuilder.fallbackService()#5368WebSocketService webSocketService =
WebSocketService
.builder()
// The fallback service is used when the request
// is not a WebSocket request.
.fallbackService(httpService)
.build();
Server
.builder()
.service("/ws-or-http", webSocketService)
.build(); -
WebSocket Frame Aggregation: You can now enable to aggregate WebSocket continuation frames for simplified message processing using
WebSocketServiceBuilder.aggregateContinuation(). #5357WebSocketService
.builder()
// Aggregate continuation frames into a single frame.
.aggregateContinuation(true)
.build(); -
Active Connection Monitoring: You can monitor the number of active connections with
armeria.client.connections#value{state="active"}for your clients when usingConnectionPoolListener.metricCollecting()#4277 #5288ConnectionPoolListener connectionPoolListener =
ConnectionPoolListener.metricCollecting(meterRegistry);
ClientFactory clientFactory =
ClientFactory
.builder()
.connectionPoolListener(connectionPoolListener)
.build(); -
Graceful Executor Shutdown: You can now gracefully terminate a custom
ExecutorServicein sync with theServer's shutdown procedure. #5031 #5087ServerListener
.builder()
// Shutdown the executor service when the server is stopping.
.shutdownWhenStopping(preStopExecutorService)
// Shutdown the executor service when the server is stopped.
.shutdownWhenStopped(postStopExecutorService)
.build() -
Session Protocol in RoutingContext: You can now acquire
SessionProtocoldirectly fromRoutingContext.sessionProtocol()for enhanced routing andExchangeTypedecisions. -
Eureka Health Check Customization: You can override the default health check URL when registering a service with Eureka. #5369
EurekaUpdatingListener
.builder()
// Override the default health check path provided by HealthCheckService.
.healthCheckUrlPath("/healthcheck")
.build();
📈 Improvements
- Annotated services now support
HttpResultwrapped in RxJava objects. #5380 #5386 - You can now create
HttpFilewith Spring Boot nested JAR URL. #5390 #5391 WebSocketServiceis restructured as an interface, allowing for custom implementations. #5368- Introduce
PreTlsHandshakeExceptionto better report exceptions occurring before a TLS handshake initiates. #5344 - Error messages for gRPC client stub generation have been clarified. #5387
🛠️ Bug fixes
- The completions of
ClientRequestContext.whenResponseCancelling()andClientRequestContext.whenResponseCancelled()are now guaranteed even ifRequestContext.cancel()is invoked before the initialization of the timeout scheduler. #5212 - Fixed a leak within
WebSocketClientwhen an invalid response is received. #5412 json_namepseudo-option in protobuf files is now correctly respected for matching query parameters during gRPC HTTP/JSON transcoding. #5193 #5366- Implicit request objects are now correctly converted. #5389 #5393
CloseWebSocketFramewith empty reason phrases are now correctly handled. #5388Flagsnow correctly logs all messages whenRequestContextExportingAppenderis configured inlogback.xml. #5327 #5361- You no longer see
EndpointSelectionTimeoutExceptionwhenHealthCheckedEndpointGroupis initialized with duplicateEndpoints. #5343 HttpHeaders.containsBoolean()now checks all header entries with the same name. #5319GrpcServiceprovides more consistentServerCall.Listenerbehavior under error conditions. #5273
📃 Documentation
- Updated Production Checklist with guidance on
using
ClientFactoryBuilder.maxNumEventLoopsPerEndpoint(). This addition will help you mitigate potential client-side bottlenecks. #5297
🏚️ Deprecations
- N/A
☢️ Breaking changes
- N/A
⛓ Dependencies
- Apache Curator 5.5.0 → 5.6.0
- Brave 5.16.0 → 6.0.0
- Brotli4j 1.12.0 → 1.15.0
- Envoy control plane 1.0.42 (new)
- Dropwizard 2.1.8 → 2.1.10
- Dropwizard Metrics 4.2.21 → 4.2.24
- GraphQL Java 20.4 → 21.3
- Fabric Kubernetes client 6.10.0 (new)
- gRPC Java 1.58.0 → 1.61.0
- gRPC Kotlin 1.4.0 → 1.4.1
- Guava 32.1.3 → 33.0.0
- Jackson 2.15.3 → 2.16.1
- Jetty 9.4.51 → 9.4.52, 10.0.17 → 10.0.19, 11.0.17 → 11.0.19, 12.0.5 (new)
- JUnit 5.10.0 → 5.10.1
- Kafka client 3.6.0 → 3.6.1
- Kotlin 1.9.0 → 1.9.22
- krotoDC 1.0.5 - 1.0.6
- Logback 1.2.11 → 1.2.13, 1.3.11 → 1.3.14, 1.4.11 → 1.4.14
- Micrometer 1.11.5 → 1.12.2
- Micrometer Tracing 1.1.6 → 1.2.2
- Netty 4.1.100 → 4.1.106
- Netty io_uring 0.0.23 → 0.0.24
- Protobuf 3.24.0 → 3.25.1
- Reactor 3.5.11 → 3.6.2
- Resilience4j 2.1.0 → 2.2.0
- ScalaPB 0.11.13 → 0.11.15
- Spring 6.0.11 → 6.1.3
- Spring Boot 2.7.14 → 2.7.18, 3.1.2 → 3.2.2
- Tomcat 8.5.94 → 8.5.98, 9.0.82 → 9.0.85, 10.1.15 → 10.1.18
🙇 Thank you
This release was possible thanks to the following contributors who shared their brilliant ideas and awesome pull requests:





















