19:23:12.811 [nioEventLoopGroup-1-2] ERROR i.m.h.s.netty.RoutingInBoundHandler - Micronaut Server Error - No request state present. Cause: Connection reset by peer
--
聽 | java.io.IOException: Connection reset by peer
聽 | at sun.nio.ch.FileDispatcherImpl.read0(Native Method)
聽 | at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:39)
聽 | at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)
聽 | at sun.nio.ch.IOUtil.read(IOUtil.java:192)
聽 | at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:380)
聽 | at io.netty.buffer.PooledByteBuf.setBytes(PooledByteBuf.java:253)
聽 | at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:1133)
聽 | at io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:350)
聽 | at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:148)
聽 | at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:714)
聽 | at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:650)
聽 | at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:576)
聽 | at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
聽 | at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
聽 | at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
聽 | at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
聽 | at java.lang.Thread.run(Thread.java:748)
This exception should not be thrown.
This exception is thrown. There is not enough information in the stacktrace to determine source. Perhaps a health check or info source?
1.3.41.8.2222.0.0pom.xml dependencies:
<dependencies>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-discovery-client</artifactId>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-security</artifactId>
</dependency>
<dependency>
<groupId>io.micronaut.configuration</groupId>
<artifactId>micronaut-security-ldap</artifactId>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-management</artifactId>
</dependency>
<dependency>
<groupId>io.micronaut.configuration</groupId>
<artifactId>micronaut-micrometer-registry-statsd</artifactId>
</dependency>
<dependency>
<groupId>com.github.jknack</groupId>
<artifactId>handlebars</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.micronaut.configuration</groupId>
<artifactId>micronaut-openapi</artifactId>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-views</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>27.0.1-jre</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.vavr</groupId>
<artifactId>vavr</artifactId>
<version>0.10.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-inject</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-validation</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-runtime</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-client</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-server-netty</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-inject-java</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-inject-groovy</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.micronaut.test</groupId>
<artifactId>micronaut-test-spock</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.objenesis</groupId>
<artifactId>objenesis</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
All the dependencies of the classpath:
io.micronaut:micronaut-discovery-client:jar:1.3.4:compile
org.slf4j:slf4j-api:jar:1.7.29:compile
io.micronaut:micronaut-security:jar:1.4.0:compile
io.micronaut:micronaut-http:jar:1.3.4:compile
io.micronaut:micronaut-http-server:jar:1.3.4:compile
io.micronaut:micronaut-security-annotations:jar:1.4.0:compile
com.optum.cirrus.micronaut:micronaut-security-jwt:jar:5.0.0:compile
io.micronaut.configuration:micronaut-security-ldap:jar:1.4.0:compile
io.micronaut:micronaut-management:jar:1.3.4:compile
io.micronaut:micronaut-router:jar:1.3.4:compile
io.micronaut.configuration:micronaut-micrometer-registry-statsd:jar:1.3.0:compile
io.micrometer:micrometer-core:jar:1.3.6:compile
org.hdrhistogram:HdrHistogram:jar:2.1.11:compile
org.latencyutils:LatencyUtils:jar:2.0.3:compile
io.micronaut.configuration:micronaut-micrometer-core:jar:1.3.0:compile
javax.validation:validation-api:jar:2.0.1.Final:compile
io.micrometer:micrometer-registry-statsd:jar:1.3.6:compile
com.github.jknack:handlebars:jar:4.1.2:runtime
io.micronaut.configuration:micronaut-openapi:jar:1.4.1:compile
io.swagger.core.v3:swagger-core:jar:2.1.1:compile
javax.xml.bind:jaxb-api:jar:2.3.1:provided
javax.activation:javax.activation-api:jar:1.2.0:provided
io.swagger.core.v3:swagger-models:jar:2.1.1:compile
io.swagger.core.v3:swagger-annotations:jar:2.1.1:compile
io.micronaut:micronaut-views:jar:1.3.1:compile
io.micronaut:micronaut-views-core:jar:1.3.1:compile
io.micronaut:micronaut-views-freemarker:jar:1.3.1:compile
io.micronaut:micronaut-views-handlebars:jar:1.3.1:compile
io.micronaut:micronaut-views-soy:jar:1.3.1:compile
io.micronaut:micronaut-views-thymeleaf:jar:1.3.1:compile
io.micronaut:micronaut-views-velocity:jar:1.3.1:compile
org.projectlombok:lombok:jar:1.18.10:provided
com.google.guava:guava:jar:27.0.1-jre:compile
com.google.guava:failureaccess:jar:1.0.1:compile
com.google.guava:listenablefuture:jar:9999.0-empty-to-avoid-conflict-with-guava:compile
com.google.code.findbugs:jsr305:jar:3.0.2:compile
org.checkerframework:checker-qual:jar:2.5.2:compile
com.google.errorprone:error_prone_annotations:jar:2.3.3:compile
com.google.j2objc:j2objc-annotations:jar:1.1:compile
org.codehaus.mojo:animal-sniffer-annotations:jar:1.17:compile
commons-io:commons-io:jar:2.6:compile
commons-cli:commons-cli:jar:1.4:compile
org.apache.commons:commons-lang3:jar:3.9:compile
com.fasterxml.jackson.dataformat:jackson-dataformat-xml:jar:2.10.3:compile
com.fasterxml.jackson.core:jackson-core:jar:2.10.3:compile
com.fasterxml.jackson.core:jackson-annotations:jar:2.10.3:compile
com.fasterxml.jackson.core:jackson-databind:jar:2.10.3:compile
com.fasterxml.jackson.module:jackson-module-jaxb-annotations:jar:2.10.3:compile
jakarta.xml.bind:jakarta.xml.bind-api:jar:2.3.2:compile
jakarta.activation:jakarta.activation-api:jar:1.2.1:compile
org.codehaus.woodstox:stax2-api:jar:4.2:compile
com.fasterxml.woodstox:woodstox-core:jar:6.1.1:compile
com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:jar:2.10.3:compile
org.yaml:snakeyaml:jar:1.24:compile
io.vavr:vavr:jar:0.10.0:compile
io.vavr:vavr-match:jar:0.10.0:compile
io.jsonwebtoken:jjwt:jar:0.9.1:compile
io.micronaut:micronaut-inject:jar:1.3.4:compile
javax.annotation:javax.annotation-api:jar:1.3.2:compile
javax.inject:javax.inject:jar:1:compile
io.micronaut:micronaut-core:jar:1.3.4:compile
io.micronaut:micronaut-validation:jar:1.3.4:compile
io.micronaut:micronaut-runtime:jar:1.3.4:compile
io.micronaut:micronaut-aop:jar:1.3.4:compile
io.reactivex.rxjava2:rxjava:jar:2.2.12:compile
com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.10.3:compile
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:2.10.3:compile
io.micronaut:micronaut-http-client:jar:1.3.4:compile
io.micronaut:micronaut-websocket:jar:1.3.4:compile
io.micronaut:micronaut-http-netty:jar:1.3.4:compile
io.micronaut:micronaut-buffer-netty:jar:1.3.4:compile
io.netty:netty-handler:jar:4.1.48.Final:compile
io.netty:netty-resolver:jar:4.1.48.Final:compile
io.netty:netty-handler-proxy:jar:4.1.48.Final:compile
io.netty:netty-common:jar:4.1.48.Final:compile
io.netty:netty-buffer:jar:4.1.48.Final:compile
io.netty:netty-transport:jar:4.1.48.Final:compile
io.netty:netty-codec:jar:4.1.48.Final:compile
io.netty:netty-codec-socks:jar:4.1.48.Final:compile
io.micronaut:micronaut-http-server-netty:jar:1.3.4:compile
io.netty:netty-codec-http:jar:4.1.48.Final:compile
io.micronaut:micronaut-inject-java:jar:1.3.4:provided
ch.qos.logback:logback-classic:jar:1.2.3:runtime
ch.qos.logback:logback-core:jar:1.2.3:runtime
cglib:cglib-nodep:jar:3.2.12:test
io.micronaut:micronaut-inject-groovy:jar:1.3.4:test
org.codehaus.groovy:groovy:jar:2.5.8:test
io.micronaut.test:micronaut-test-spock:jar:1.1.5:test
io.micronaut.test:micronaut-test-core:jar:1.1.5:test
org.spockframework:spock-core:jar:1.2-groovy-2.5:test
org.codehaus.groovy:groovy-json:jar:2.5.8:test
org.codehaus.groovy:groovy-nio:jar:2.5.2:test
org.codehaus.groovy:groovy-macro:jar:2.5.2:test
org.codehaus.groovy:groovy-templates:jar:2.5.4:test
org.codehaus.groovy:groovy-test:jar:2.5.8:test
org.codehaus.groovy:groovy-sql:jar:2.5.2:test
org.codehaus.groovy:groovy-xml:jar:2.5.4:test
junit:junit:jar:4.12:test
org.hamcrest:hamcrest-core:jar:1.3:test
org.objenesis:objenesis:jar:2.6:test
io.projectreactor:reactor-core:jar:3.3.0.RELEASE:test
org.reactivestreams:reactive-streams:jar:1.0.3:compile
application.yml relevant configurations:
---
# Application and Server Configurations
micronaut:
application:
name: service
application:
environment: ${APPLICATION_ENVIRONMENT:local}
---
# Server Configurations
micronaut:
server:
port: 8080
cors:
enabled: true
configurations:
web:
maxAge: 3600 # 1 hour
config-client:
enabled: false
---
# Endpoints Configuration
endpoints:
info:
enabled: true
sensitive: false
routes:
enabled: true
sensitive: false
health:
enabled: true
sensitive: false
details-visible: ANONYMOUS
---
# Metrics Configuration
micronaut:
metrics:
enabled: true
export:
statsd:
enabled: true
flavor: datadog
step: PT1M
host: localhost
port: 8125
---
# Security Configuration
micronaut:
security:
enabled: true
---
# Swagger Configurations
swagger:
path: /swagger/api-docs
version: 3.22.1
layout: StandaloneLayout
deepLinking: true
urls:
- name: service
url: ${swagger.path}/service-1.0.X.yml
---
# Static Resource and View Definitions
micronaut:
router:
static-resources:
swagger:
enabled: true
paths: classpath:META-INF/swagger
mapping: ${swagger.path}/**
views:
enabled: true
folder: /views
handlebars:
enabled: true
---
# Http Client Configurations
micronaut:
http:
client:
connect-timeout: 10s
If you could provide an example that reproduces the issue that would help a great deal.
I'll try to do that over the weekend. Confirmed this issue in a non kafka application as well. Seems that its limited to netty. This happened when we upgraded from MN 1.3.3 to 1.3.4. Will try to get an example app uploaded or diagnose the issue.
I see that netty was upgraded from 4.1.47.Final to 4.1.48.Final in that release so I will see if the issue still persists with previous versions.
Any solutions to this issue?
Just an update on this. I'm still getting this with Micronaut 2.0.0 stack.
I left netty and used the tomcat server dependecy instead and worked like a charm!
I see that netty was upgraded from
4.1.47.Finalto4.1.48.Finalin that release so I will see if the issue still persists with previous versions.
I tried this and it didn't worked out, seems to be a problem with the last release of netty
In my case, this was caused by haproxy's L4 health checks, which only connect and don't actually perform an HTTP request. Turning it off got rid of the log message, and while I didn't test it, I expect real HTTP endpoint health check would get rid of it as well.
@mmanes, this makes sense, considering its happening on an interval / periodic basis. @graemerocher, @jameskleeh is there any way to suppress this type of error or handle it more gracefully?
@brianwyka Probably, however an example app that reproduces the issue would be needed to determine this best fix
@mmanes, does a simple hello world app produce the issue with a CONNECT only health check? Is it TCP?
@brianwyka I tried on two different basic micronaut applications, so it seems so. It should be easily reproducible by adding haproxy in front of the application while having check inter 10s on the backend server configuration. haproxy simply establishes a TCP connection then immediately sends an RST.
Modifying haproxy to use HTTP health checks with something like: option httpchk GET /health HTTP/1.0 prevents the errors from being logged, and is a better health check anyway.
http://cbonte.github.io/haproxy-dconv/2.3/configuration.html#check
I have this problem too, with Micronaut 2.2.0
For us, this only happens if we have 2 pods running at the same time.
Our config is very similar to the OP. I have a feeling the metrics endpoint is the culprit.
I added a full trace log (had to remove minimal stuff like jdbc urls and env variables)
micronaut:
application:
name: auth
metrics:
enabled: false
export:
prometheus:
enabled: true
step: PT1M
descriptions: true
server:
netty:
worker:
threads: 10
childOptions:
autoRead: false
autoClose: true
security:
authentication: bearer
token:
jwt:
signatures:
secret:
generator:
secret: ${jwt.secret}
jws-algorithm: ${jwt.algorithm}
caches:
users:
expire-after-write: 2m
---
endpoints:
health:
sensitive: false
prometheus:
sensitive: false
---
datasources:
default:
url: jdbc:${user-service.postgres.uri}
driver-class-name: org.postgresql.Driver
dialect: POSTGRES
maximum-pool-size: 4
---
flyway:
datasources:
default:
locations: classpath:databasemigrations
url: jdbc:${user-service.postgres.uri}
schemas:
- app
---
carhub:
proxy:
config:
- path: /api/v./vehicles/.*
host: export-service:8080
methods:
- GET
- path: /api/v./export/.*
host: export-service:8080
- path: /api/v./reservation/.*
host: reservation-broker:8080
- path: /api/v2/salescontract/.*
host: sc-broker:8080
- path: .*
host: carhub:8080
Verfied the health checks again. It's not them.
The last thing that's shared by the two pods in openshift is the DB connection. We use jdbc with hikari.
This only starts happening if we scale up to 2 pods. the moment we scale down, exceptions are gone.
Any pointers where this could come from?
Seems like client connections being dropped unexpectedly. The error should be handled more gracefully by Micronaut though and simply logged to debug level
I'm not sure if this isn't a timeout issue of some sort. I see multiple exceptions in rapid succession and then silence again.
@jameskleeh, just opened https://github.com/micronaut-projects/micronaut-core/pull/4807 to change logging to DEBUG. Is this sufficient?
This still happens multiple times per second for us, I don't think changing this to a debug log will actually fix anything (micronaut 2.2.3). I wonder why this occurs in the first place. We are not dropping that many connections at all. Even just running the pods idle in oc with only health and prometheus requests as traffic gives us these errors.
@meredrica if you have a way to reproduce we can try get to the bottom of it
this code is supposed to suppress logging of these connection reset exceptions: https://github.com/micronaut-projects/micronaut-core/blob/8e79eac72cf1ce70fac62a74882db2a618d154a2/http-server-netty/src/main/java/io/micronaut/http/server/netty/RoutingInBoundHandler.java#L154
Since upgrading to Micronaut 2.x these connection resets have become more problematic. We used to hide them to keep our request logging from recording them. Now that's not sufficient because they are being counted as 500's in our prometheus metrics (in addition to the 200 for the real response). All the connection resets I've seen have come after the real response has been sent back to the client. It would be nice if connection resets that happen after the response is out the door are explicitly ignored, rather than relying on exception handling magic (and now metrics magic).
In our case the connection resets don't happen when calling the endpoints from inside the same k8s cluster. Something in our k8s network plumbing seems to be terminating connections in a way that netty doesn't like.
If these resets can't be avoided entirely, it would be nice if ExceptionHandlers could return null to indicate there is no response to send. Currently custom exception handlers are required to return a response object, or have RoutingInBoundHandler create a default 500 response.
@americ that sounds almost exactly like our problem. my team is not managing the cluster so we can't change the behaviour. it also explains why this only happens when we have more than one pod.
@brianwyka I think it might be better to just reuse the logException method in #4807 instead of just dropping it to debug.
I had issues previously with the built-in web metrics. Wierd things happened when the meter reporting logic threw RuntimeException-s, because they were not handled in the subscriber. Plus, I think most web filters don't work correctly in cases when there are multiple execution chains, which is the case if you let an exception fall through the controller method and handle it via an error handler method. I made this mistake myself as well with the tracing filters, see: #4314
I ended up writing a local replacement for the web metrics filters - they cannot really be extended - which solved those issues for me. @americ, @meredrica I am happy to share it with you so that you can check if it resolves the issues in your apps, I just need some time to extract it from my project.
@lgathy I'm interested in seeing your solution. Our current workaround maps these errors to status code 100, which avoids it being counted as a success or failure in our alert system.
@americ I've created this PR which ignores client connection related exceptions. You can try the snapshot after its merged or build it yourself and try https://github.com/micronaut-projects/micronaut-core/pull/4867
@jameskleeh we have a global exception handler that's a workaround for this issue. It looks like your change only affects apps with no exception handler defined. If I understand our code and yours, I think we can get rid of our exception handler now. I believe we added it so we could tag these fake 500 responses so our request logging filter could discard them. We'll try out the snapshot build.
@jameskleeh I just tried 2.3.1-SNAPSHOT and the connection reset handling works great. They aren't affecting our prometheus metrics any more and we don't need an exception handler. I was worried the exception handler removal would affect our response logging, but it doesn't.
Two big thumbs up!
@americ Glad to hear
Most helpful comment
Just an update on this. I'm still getting this with Micronaut
2.0.0stack.