我在 Web 客户端收到 java.lang.OutOfMemoryError: Direct buffer memory 错误。
批处理作业每天运行。两次失败,第三次就通过了。
at org.springframework.retry.support.RetryTemplate.rethrow(RetryTemplate.java:532) ~[spring-retry-1.2.5.RELEASE.jar:na]
Caused by: java.lang.OutOfMemoryError: Direct buffer memory
at reactor.netty.http.client.HttpClientDoOnError$OnErrorTcpClient.connect(HttpClientDoOnError.java:242) ~[reactor-netty-0.9.11.RELEASE.jar:0.9.11.RELEASE]
我在日志中找到了 JVM 内存配置。它正在云铸造厂中运行。
JVM Memory Configuration: -Xmx342549K -Xss1M -XX:ReservedCodeCacheSize=240M -XX:MaxDirectMemorySize=10M -XX:MaxMetaspaceSize=194026K
失败的代码:
@Retryable(maxAttemptsExpression = "#{${remote.retry.maxAttempts}}", backoff = @Backoff(delayExpression = "#{${remote.retry.delay}}"))
public Optional<JobStatusResponseDTO> getStatus(String jobNumber, String accountNumber) {
return broadridgeClient.getStatus(accountNumber, jobNumber);
}
@CircuitBreaker(maxAttemptsExpression = "#{${remote.circuitBreaker.maxAttempts}}",
openTimeoutExpression = "#{${remote.circuitBreaker.openTimeout}}", resetTimeoutExpression = "#{${remote.circuitBreaker.resetTimeout}}")
public Optional<JobStatusResponseDTO> getStatus(String account, String jobNumber) {
JobStatusRequestDTO request = new JobStatusRequestDTO();
request.setAccount(account);
request.setJobNumber(jobNumber);
JobStatusResponseDTO jobStatus;
jobStatus = client.post()
.uri(PATH)
.body(BodyInserters.fromValue(request))
.exchange()
.elapsed()
.flatMap(response -> {
if (response.getT2().statusCode() == HttpStatus.NO_CONTENT) {
return Mono.empty();
} else if (isClientOrServerError(response.getT2())) {
return Mono.error(new RemoteClientException(String.format("Job status is not received: %s", response.getT2().statusCode())));
}
return response.getT2().bodyToMono(JobStatusResponseDTO.class);
})
.block();
return Optional.ofNullable(jobStatus);
}
Edit 1:
我还发现 Cloud Foundry 正在为堆设置低内存
我正在使用 CF 任务来运行它。
cf run-task ipbol-proxy-batch "JAVA_OPTS=\"-agentpath:\$PWD/.java-buildpack/oracle_jre/bin/jvmkill-1.16.0_RELEASE=printHeapHistogram=1 -Djava.io.tmpdir=\$TMPDIR -Djava.security.egd=file:///dev/urandom -XX:ActiveProcessorCount=\$(nproc) -Dspring.batch.job.names=${job_name} -Dbatch.run.historic=${run_historic_files} -Dorg.cloudfoundry.security.keymanager.enabled=false -Dorg.cloudfoundry.security.trustmanager.enabled=true -Djava.ext.dirs= -Djava.security.properties=\$PWD/.java-buildpack/java_security/java.security \$JAVA_OPTS\" && CALCULATED_MEMORY=\$(\$PWD/.java-buildpack/oracle_jre/bin/java-buildpack-memory-calculator-3.13.0_RELEASE -totMemory=\$MEMORY_LIMIT -loadedClasses=31842 -poolType=metaspace -stackThreads=250 -vmOptions=\"\$JAVA_OPTS\") && echo JVM Memory Configuration: \$CALCULATED_MEMORY && JAVA_OPTS=\"\$JAVA_OPTS \$CALCULATED_MEMORY\" && KEYSTORE_PARAMS=\$(\$PWD/.java-buildpack/oracle_jre/bin/java -jar \$PWD/.java-buildpack/oracle_jre/keystore-manager-0.1.1.jar) && JAVA_OPTS=\"\$JAVA_OPTS \$KEYSTORE_PARAMS\" && MALLOC_ARENA_MAX=2 VCAP_SERVICES=\$(for i in {1..10}; do \${PWD}/.java-buildpack/mv_decryptor/jpmc-mvdecryptor && exit 0; sleep 3; done; kill \$\$) SERVER_PORT=\$PORT eval exec \$PWD/.java-buildpack/oracle_jre/bin/java \$JAVA_OPTS -cp \$PWD/.::\$PWD/.java-buildpack/container_security_provider/container_security_provider-1.16.0_RELEASE.jar org.springframework.boot.loader.JarLauncher" ipbol-proxy-batch
Edit 2:
我已经更新了代码以在每种情况下使用响应。尽管如此,我还是得到了相同的“java.lang.OutOfMemoryError:直接缓冲内存”
public Optional<JobStatusResponseDTO> getStatus(String account, String jobNumber) {
JobStatusRequestDTO request = new JobStatusRequestDTO();
request.setAccount(account);
request.setJobNumber(jobNumber);
Optional<JobStatusResponseDTO> responseDTO = Optional.empty();
final Object block = client.post()
.uri(PATH)
.body(BodyInserters.fromValue(request))
.exchange()
.elapsed()
.flatMap(response -> {
if (response.getT2().statusCode() == HttpStatus.NO_CONTENT) {
return response.getT2().bodyToMono(Void.class).thenEmpty(Mono.empty());
} else if (isClientOrServerError(response.getT2())) {
return response.getT2().bodyToMono(Void.class).thenEmpty(Mono.error(new RemoteClientException(String.format("Job status is not received: %s", response.getT2().statusCode()))));
}
return response.getT2().bodyToMono(JobStatusResponseDTO.class);
})
.block();
if(block!= null && block instanceof JobStatusResponseDTO)
{
responseDTO = Optional.of((JobStatusResponseDTO)block);
}
return responseDTO;
}
我的组织仓库中没有 spring webflux 5.3。所以不能用那个。
这是默认内存配置
-Xmx1387828K -Xss1M -XX:ReservedCodeCacheSize=240M -XX:MaxDirectMemorySize=10M -XX:MaxMetaspaceSize=197323K