Spring Boot webclient 多次 post api 调用:打开文件太多

问题描述 投票:0回答:1

我的 Spring Boot 应用程序处理预定的批处理作业,其中涉及在一个批处理作业中对配置的 api 进行数千次 post api 调用。这些调用在线程池中同时处理。

下面是每个api调用所使用的方法。它与其他 api 调用没有任何共享资源。

private <T> String getResponseV2(String deviceConnection, String uri, T body, Consumer<HttpHeaders> headersConsumer) {
        SslContext sslContext = null;
        try {
            sslContext = SslContextBuilder
                    .forClient()
                    .trustManager(InsecureTrustManagerFactory.INSTANCE)
                    .build();
        } catch (SSLException e) {
            log.error("Error creating ssl context: {}",e.getLocalizedMessage());
            log.error("Error: ",e);
            return null;
        }

        SslContext finalSslContext = sslContext;
        TcpClient tcpClient = TcpClient.create().secure(sslContextSpec -> sslContextSpec.sslContext(finalSslContext));
        HttpClient httpClient = HttpClient.from(tcpClient).wiretap("reactor.netty.http.client.HttpClient",
                LogLevel.DEBUG, AdvancedByteBufFormat.TEXTUAL).responseTimeout(Duration.ofSeconds(20));

        return WebClient.builder()
                .baseUrl(deviceConnection)
                .clientConnector(new ReactorClientHttpConnector(httpClient))
                .build()
                .post().uri(uri)
                .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                .headers(headersConsumer)
                .body(Mono.just(body), body.getClass())
                .retrieve()
                /*.onStatus(HttpStatus::isError, res -> {
                    log.info("Webclient Response {}", res.bodyToMono(String.class));
                    return Mono.error(new IllegalStateException("Failed to Fetch Data"));
                })*/
                .bodyToMono(String.class).block();
    }

在每个单独的作业中,此函数都会被调用两次,一次用于获取身份验证令牌,另一次用于实际的 post api 调用。

我的问题是我不完全熟悉 webclient,不确定这是否是在我的用例中使用 webclient 的正确方法,或者这是否会泄漏资源。

这是因为经过一些测试运行后,我在服务中遇到以下异常:

Caused by: io.netty.channel.ChannelException: io.netty.channel.unix.Errors$NativeIoException: newSocketDgram(..) failed: Too many open files
    at io.netty.channel.unix.Socket.newSocketDgram0(Socket.java:442)
    at io.netty.channel.epoll.LinuxSocket.newSocketDgram(LinuxSocket.java:327)
    at io.netty.channel.epoll.EpollDatagramChannel.<init>(EpollDatagramChannel.java:84)
    at io.netty.channel.epoll.EpollDatagramChannel.<init>(EpollDatagramChannel.java:75)
    at reactor.netty.resources.DefaultLoopEpoll.getChannel(DefaultLoopEpoll.java:55)
    at reactor.netty.resources.LoopResources.onChannel(LoopResources.java:214)
    at reactor.netty.tcp.TcpResources.onChannel(TcpResources.java:208)
    at reactor.netty.transport.NameResolverProvider.lambda$newNameResolverGroup$0(NameResolverProvider.java:415)
    at io.netty.bootstrap.AbstractBootstrap.initAndRegister(AbstractBootstrap.java:310)
    at io.netty.bootstrap.AbstractBootstrap.register(AbstractBootstrap.java:227)
    at io.netty.resolver.dns.DnsNameResolver.<init>(DnsNameResolver.java:456)
    at io.netty.resolver.dns.DnsNameResolverBuilder.build(DnsNameResolverBuilder.java:476)
    at io.netty.resolver.dns.DnsAddressResolverGroup.newNameResolver(DnsAddressResolverGroup.java:114)
    at io.netty.resolver.dns.DnsAddressResolverGroup.newResolver(DnsAddressResolverGroup.java:92)
    at io.netty.resolver.dns.DnsAddressResolverGroup.newResolver(DnsAddressResolverGroup.java:77)
    at io.netty.resolver.AddressResolverGroup.getResolver(AddressResolverGroup.java:70)
    ... 12 common frames omitted

这些都伴随着这个

tack trace:
        at org.springframework.web.reactive.function.client.ExchangeFunctions$DefaultExchangeFunction.lambda$wrapException$9(ExchangeFunctions.java:137)
        at reactor.core.publisher.MonoErrorSupplied.subscribe(MonoErrorSupplied.java:70)
        at reactor.core.publisher.Mono.subscribe(Mono.java:4046)
        at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:103)
        at reactor.core.publisher.FluxPeek$PeekSubscriber.onError(FluxPeek.java:221)
        at reactor.core.publisher.FluxPeek$PeekSubscriber.onError(FluxPeek.java:221)
        at reactor.core.publisher.FluxPeek$PeekSubscriber.onError(FluxPeek.java:221)
        at reactor.core.publisher.MonoNext$NextSubscriber.onError(MonoNext.java:93)
        at reactor.core.publisher.MonoFlatMapMany$FlatMapManyMain.onError(MonoFlatMapMany.java:204)
        at reactor.core.publisher.SerializedSubscriber.onError(SerializedSubscriber.java:124)
        at reactor.core.publisher.FluxRetryWhen$RetryWhenMainSubscriber.whenError(FluxRetryWhen.java:224)
        at reactor.core.publisher.FluxRetryWhen$RetryWhenOtherSubscriber.onError(FluxRetryWhen.java:273)
        at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.drain(FluxConcatMap.java:413)
        at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.onNext(FluxConcatMap.java:250)
        at reactor.core.publisher.EmitterProcessor.drain(EmitterProcessor.java:491)
        at reactor.core.publisher.EmitterProcessor.tryEmitNext(EmitterProcessor.java:299)
        at reactor.core.publisher.SinkManySerialized.tryEmitNext(SinkManySerialized.java:97)
        at reactor.core.publisher.InternalManySink.emitNext(InternalManySink.java:27)
        at reactor.core.publisher.FluxRetryWhen$RetryWhenMainSubscriber.onError(FluxRetryWhen.java:189)
        at reactor.core.publisher.MonoCreate$DefaultMonoSink.error(MonoCreate.java:189)
        at reactor.netty.http.client.HttpClientConnect$MonoHttpConnect$ClientTransportSubscriber.onError(HttpClientConnect.java:306)
        at reactor.core.publisher.MonoCreate$DefaultMonoSink.error(MonoCreate.java:189)
        at reactor.netty.resources.DefaultPooledConnectionProvider$DisposableAcquire.onError(DefaultPooledConnectionProvider.java:166)
        at reactor.netty.internal.shaded.reactor.pool.AbstractPool$Borrower.fail(AbstractPool.java:427)
        at reactor.netty.internal.shaded.reactor.pool.SimpleDequePool.lambda$drainLoop$5(SimpleDequePool.java:310)
        at reactor.core.publisher.FluxDoOnEach$DoOnEachSubscriber.onError(FluxDoOnEach.java:186)
        at reactor.core.publisher.MonoCreate$DefaultMonoSink.error(MonoCreate.java:189)
        at reactor.netty.resources.DefaultPooledConnectionProvider$PooledConnectionAllocator$PooledConnectionInitializer.onError(DefaultPooledConnectionProvider.java:565)
        at reactor.core.publisher.Operators.error(Operators.java:196)
        at reactor.core.publisher.FluxFlatMap.trySubscribeScalarMap(FluxFlatMap.java:134)
        at reactor.core.publisher.MonoFlatMap.subscribeOrReturn(MonoFlatMap.java:53)
        at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:57)
        at reactor.netty.resources.DefaultPooledConnectionProvider$PooledConnectionAllocator.lambda$connectChannel$0(DefaultPooledConnectionProvider.java:525)
        at reactor.core.publisher.MonoCreate.subscribe(MonoCreate.java:57)
        at reactor.core.publisher.Mono.subscribe(Mono.java:4046)
        at reactor.core.publisher.Mono.subscribeWith(Mono.java:4161)
        at reactor.core.publisher.Mono.subscribe(Mono.java:4017)
        at reactor.core.publisher.Mono.subscribe(Mono.java:3953)
        at reactor.core.publisher.Mono.subscribe(Mono.java:3925)
        at reactor.netty.internal.shaded.reactor.pool.SimpleDequePool.drainLoop(SimpleDequePool.java:318)
        at reactor.netty.internal.shaded.reactor.pool.SimpleDequePool.drain(SimpleDequePool.java:261)
        at reactor.netty.internal.shaded.reactor.pool.SimpleDequePool.doAcquire(SimpleDequePool.java:256)
        at reactor.netty.internal.shaded.reactor.pool.AbstractPool$Borrower.request(AbstractPool.java:382)
        at reactor.netty.resources.DefaultPooledConnectionProvider$DisposableAcquire.onSubscribe(DefaultPooledConnectionProvider.java:206)
        at reactor.netty.internal.shaded.reactor.pool.SimpleDequePool$QueueBorrowerMono.subscribe(SimpleDequePool.java:578)
        at reactor.netty.resources.PooledConnectionProvider.lambda$acquire$1(PooledConnectionProvider.java:120)
        at reactor.core.publisher.MonoCreate.subscribe(MonoCreate.java:57)
        at reactor.netty.http.client.HttpClientConnect$MonoHttpConnect.lambda$subscribe$0(HttpClientConnect.java:266)
        at reactor.core.publisher.MonoCreate.subscribe(MonoCreate.java:57)
        at reactor.core.publisher.FluxRetryWhen.subscribe(FluxRetryWhen.java:76)
        at reactor.core.publisher.MonoRetryWhen.subscribeOrReturn(MonoRetryWhen.java:46)
        at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:57)
        at reactor.netty.http.client.HttpClientConnect$MonoHttpConnect.subscribe(HttpClientConnect.java:269)
        at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64)
        at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
        at reactor.core.publisher.Mono.subscribe(Mono.java:4046)
        at reactor.core.publisher.Mono.block(Mono.java:1702)
        at .service.AirLinkOSDeviceServiceWebClientImpl.getResponseV2(AirLinkOSDeviceServiceWebClientImpl.java:197)
        at .service.AirLinkOSDeviceServiceWebClientImpl.setConfigurationItemV2(AirLinkOSDeviceServiceWebClientImpl.java:119)
        at .service.DeviceScheduledJobAsyncService.processApi(DeviceScheduledJobAsyncService.java:71)
        at .service.DeviceScheduledJobAsyncService.processDeviceJob(DeviceScheduledJobAsyncService.java:44)
        at .service.DeviceScheduledJobAsyncService$$FastClassBySpringCGLIB$$ba9a8368.invoke(<generated>)
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
        at org.springframework.aop.interceptor.AsyncExecutionInterceptor.lambda$invoke$0(AsyncExecutionInterceptor.java:115)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:750)
    Suppressed: java.lang.Exception: #block terminated with an error
        at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:99)
        at reactor.core.publisher.Mono.block(Mono.java:1703)
        at .service.AirLinkOSDeviceServiceWebClientImpl.getResponseV2(AirLinkOSDeviceServiceWebClientImpl.java:197)
        at .service.AirLinkOSDeviceServiceWebClientImpl.setConfigurationItemV2(AirLinkOSDeviceServiceWebClientImpl.java:119)
        at .service.DeviceScheduledJobAsyncService.processApi(DeviceScheduledJobAsyncService.java:71)
        at .service.DeviceScheduledJobAsyncService.processDeviceJob(DeviceScheduledJobAsyncService.java:44)
        at .service.DeviceScheduledJobAsyncService$$FastClassBySpringCGLIB$$ba9a8368.invoke(<generated>)
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
        at org.springframework.aop.interceptor.AsyncExecutionInterceptor.lambda$invoke$0(AsyncExecutionInterceptor.java:115)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:750)
Caused by: io.netty.channel.ChannelException: io.netty.channel.unix.Errors$NativeIoException: newSocketStream(..) failed: Too many open files
    at io.netty.channel.unix.Socket.newSocketStream0(Socket.java:430)
    at io.netty.channel.epoll.LinuxSocket.newSocketStream(LinuxSocket.java:319)
    at io.netty.channel.epoll.LinuxSocket.newSocketStream(LinuxSocket.java:323)
    at io.netty.channel.epoll.EpollSocketChannel.<init>(EpollSocketChannel.java:45)
    at reactor.netty.resources.DefaultLoopEpoll.getChannel(DefaultLoopEpoll.java:49)
    at reactor.netty.resources.LoopResources.onChannel(LoopResources.java:214)
    at reactor.netty.tcp.TcpResources.onChannel(TcpResources.java:208)
    at reactor.netty.transport.TransportConfig.lambda$connectionFactory$0(TransportConfig.java:265)
    at reactor.netty.transport.TransportConnector.doInitAndRegister(TransportConnector.java:171)
    at reactor.netty.transport.TransportConnector.connect(TransportConnector.java:102)
    at reactor.netty.resources.DefaultPooledConnectionProvider$PooledConnectionAllocator.lambda$connectChannel$0(DefaultPooledConnectionProvider.java:524)
    at reactor.core.publisher.MonoCreate.subscribe(MonoCreate.java:57)
    at reactor.core.publisher.Mono.subscribe(Mono.java:4046)
    at reactor.core.publisher.Mono.subscribeWith(Mono.java:4161)
    at reactor.core.publisher.Mono.subscribe(Mono.java:4017)
    at reactor.core.publisher.Mono.subscribe(Mono.java:3953)
    at reactor.core.publisher.Mono.subscribe(Mono.java:3925)
    at reactor.netty.internal.shaded.reactor.pool.SimpleDequePool.drainLoop(SimpleDequePool.java:318)
    at reactor.netty.internal.shaded.reactor.pool.SimpleDequePool.drain(SimpleDequePool.java:261)
    at reactor.netty.internal.shaded.reactor.pool.SimpleDequePool.doAcquire(SimpleDequePool.java:256)
    at reactor.netty.internal.shaded.reactor.pool.AbstractPool$Borrower.request(AbstractPool.java:382)
    at reactor.netty.resources.DefaultPooledConnectionProvider$DisposableAcquire.onSubscribe(DefaultPooledConnectionProvider.java:206)
    at reactor.netty.internal.shaded.reactor.pool.SimpleDequePool$QueueBorrowerMono.subscribe(SimpleDequePool.java:578)
    at reactor.netty.resources.PooledConnectionProvider.lambda$acquire$1(PooledConnectionProvider.java:120)
    at reactor.core.publisher.MonoCreate.subscribe(MonoCreate.java:57)
    at reactor.netty.http.client.HttpClientConnect$MonoHttpConnect.lambda$subscribe$0(HttpClientConnect.java:266)
    at reactor.core.publisher.MonoCreate.subscribe(MonoCreate.java:57)
    at reactor.core.publisher.FluxRetryWhen.subscribe(FluxRetryWhen.java:76)
    at reactor.core.publisher.MonoRetryWhen.subscribeOrReturn(MonoRetryWhen.java:46)
    at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:57)
    at reactor.netty.http.client.HttpClientConnect$MonoHttpConnect.subscribe(HttpClientConnect.java:269)
    at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64)
    at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
    at reactor.core.publisher.Mono.subscribe(Mono.java:4046)
    at reactor.core.publisher.Mono.block(Mono.java:1702)
    at .service.AirLinkOSDeviceServiceWebClientImpl.getResponseV2(AirLinkOSDeviceServiceWebClientImpl.java:197)
    at .service.AirLinkOSDeviceServiceWebClientImpl.setConfigurationItemV2(AirLinkOSDeviceServiceWebClientImpl.java:119)
    at .service.DeviceScheduledJobAsyncService.processApi(DeviceScheduledJobAsyncService.java:71)
    at .service.DeviceScheduledJobAsyncService.processDeviceJob(DeviceScheduledJobAsyncService.java:44)
    at .service.DeviceScheduledJobAsyncService$$FastClassBySpringCGLIB$$ba9a8368.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
    at org.springframework.aop.interceptor.AsyncExecutionInterceptor.lambda$invoke$0(AsyncExecutionInterceptor.java:115)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:750)
Caused by: io.netty.channel.unix.Errors$NativeIoException: newSocketStream(..) failed: Too many open files

或者这个

org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection
    at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:467)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.startTransaction(AbstractPlatformTransactionManager.java:400)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373)
    at sun.reflect.GeneratedMethodAccessor78.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:128)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215)
    at com.sun.proxy.$Proxy152.getTransaction(Unknown Source)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:595)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:382)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:174)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215)
    at com.sun.proxy.$Proxy149.save(Unknown Source)
    at .service.DeviceScheduledJobAsyncService.processApi(DeviceScheduledJobAsyncService.java:99)
    at .service.DeviceScheduledJobAsyncService.processDeviceJob(DeviceScheduledJobAsyncService.java:44)
    at .service.DeviceScheduledJobAsyncService$$FastClassBySpringCGLIB$$ba9a8368.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
    at org.springframework.aop.interceptor.AsyncExecutionInterceptor.lambda$invoke$0(AsyncExecutionInterceptor.java:115)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:750)
Caused by: org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection
    at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:112)
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:99)
    at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.acquireConnectionIfNeeded(LogicalConnectionManagedImpl.java:111)
    at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.getPhysicalConnection(LogicalConnectionManagedImpl.java:138)
    at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.getConnectionForTransactionManagement(LogicalConnectionManagedImpl.java:273)
    at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.begin(LogicalConnectionManagedImpl.java:281)
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.begin(JdbcResourceLocalTransactionCoordinatorImpl.java:246)
    at org.hibernate.engine.transaction.internal.TransactionImpl.begin(TransactionImpl.java:83)
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.beginTransaction(HibernateJpaDialect.java:164)
    at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:421)
    ... 36 common frames omitted
Caused by: org.postgresql.util.PSQLException: The connection attempt failed.
    at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:315)
    at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:51)
    at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:225)
    at org.postgresql.Driver.makeConnection(Driver.java:465)
    at org.postgresql.Driver.connect(Driver.java:264)
    at java.sql.DriverManager.getConnection(DriverManager.java:664)
    at java.sql.DriverManager.getConnection(DriverManager.java:208)
    at org.springframework.jdbc.datasource.DriverManagerDataSource.getConnectionFromDriverManager(DriverManagerDataSource.java:155)
    at org.springframework.jdbc.datasource.DriverManagerDataSource.getConnectionFromDriver(DriverManagerDataSource.java:146)
    at org.springframework.jdbc.datasource.AbstractDriverBasedDataSource.getConnectionFromDriver(AbstractDriverBasedDataSource.java:205)
    at org.springframework.jdbc.datasource.AbstractDriverBasedDataSource.getConnection(AbstractDriverBasedDataSource.java:169)
    at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122)
    at org.hibernate.internal.NonContextualJdbcConnectionAccess.obtainConnection(NonContextualJdbcConnectionAccess.java:38)
    at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.acquireConnectionIfNeeded(LogicalConnectionManagedImpl.java:108)
    ... 43 common frames omitted
Caused by: java.net.SocketException: Too many open files
    at java.net.Socket.createImpl(Socket.java:478)
    at java.net.Socket.connect(Socket.java:605)
    at org.postgresql.core.PGStream.createSocket(PGStream.java:231)
    at org.postgresql.core.PGStream.<init>(PGStream.java:95)
    at org.postgresql.core.v3.ConnectionFactoryImpl.tryConnect(ConnectionFactoryImpl.java:98)
    at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:213)
    ... 56 common frames omitted
2023-12-13 08:13:51,459  WARN [b7403dc2-fc7c-4249-9b61-dbb98cb96e8d] org.hibernate.engine.jdbc.spi.SqlExceptionHelper [FunctionThread-9] SQL Error: 0, SQLState: 08001
2023-12-13 08:13:51,459  ERROR [b7403dc2-fc7c-4249-9b61-dbb98cb96e8d] org.hibernate.engine.jdbc.spi.SqlExceptionHelper [FunctionThread-9] The connection attempt failed.

无论哪种方式,罪魁祸首似乎都是打开的文件太多。

我有点迷失,因为我无法准确指出问题是什么以及我可以采取什么措施来解决它。

我正在 Docker 容器中运行我的应用程序。

增加文件描述符限制是唯一的解决办法吗?

java spring spring-boot spring-webflux
1个回答
0
投票

您的应用程序在每次 HTTP 调用时都会创建大量基本资源。例如,SSL 上下文之类的内容将在整个应用程序中基本固定。如果其中一些资源包含连接池之类的内容,那么您将在每个请求上创建一个新的连接池;这将导致您所看到的资源耗尽。

从一般意义上来说,您只想在应用程序中创建一次类似

SslContext
HttpClient
的对象,然后在需要时将它们传递给对象。 Spring 的核心功能之一是“依赖注入”系统,它提供了一种标准方法来创建这些对象一次并在需要时将它们注入到对象中。 但更具体地说,Spring Boot 已经包含了自行创建大部分内容的逻辑。您根本不必创建任何这些对象。要求 Spring Boot 将

WebClient.Builder

传递给对象的构造函数,它会强制执行。

@Component
public class MyService {
  private final WebClient.Builder webClientBuilder;

  public MyService(WebClient.Builder webClientBuilder) {
    this.webClientBuilder = webClientBuilder;
  }

 private <T> String getResponseV2(
    String deviceConnection,
    String uri,
    T body,
    Consumer<HttpHeaders> headersConsumer
  ) {
    // without creating any of the other objects
    return WebClient.builder()
      .clone()
      .baseUrl(deviceConnection)
      .build()
      .post().uri(uri)
      ...;
  }
}

Spring Boot 文档提供了有关
注入和配置 WebClient

的更多信息。例如,如果您确实需要自定义 TLS 配置,则可以使用特定于 Spring 的路径,您可以在其中提供 WebClientSsl 对象

,而无需从头开始构建整个对象堆栈。

© www.soinside.com 2019 - 2024. All rights reserved.