I have to develop a REST API that should be connected to other webservices and java application that can handle database insertion. I do have a lot of insertions each seconds. FOr this one solution proposed was to centralize all insertions and queries in a single web api. In order to fake the final application that handles insertions, I created a client that uses several threads and which calls the backend that handles the insertions. My "fake application" has 5 threads that are used to query my backend. here is a thread implementation I used:
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
List<ResponseBody> addedValues = new ArrayList<>();
StopWatch watch = new StopWatch();
watch.start();
for(int i = 0; i < 10000; i ) {
if(i % 1000 == 0 && i != 0) {
System.out.println("T1 " i);
}
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.connectTimeout(3600, TimeUnit.SECONDS);
builder.readTimeout(3600, TimeUnit.SECONDS);
builder.writeTimeout(3600, TimeUnit.SECONDS);
OkHttpClient client = builder.build();
String json = "{ "
"\"id\": \"db-t1-" i "\", "
"\"user\": \"test\", "
"\"password\": \"test\", "
"\"driver\": \"test\", "
"\"connectionString\": \"test\", "
"\"type\": \"test\""
"}";
RequestBody body = RequestBody.create(json, MediaType.get("application/json; charset=utf-8"));
Request request = new Request.Builder()
.url("http://localhost:8080/db")
.post(body)
.addHeader("Content-Type", "application/json")
.build();
Call call = client.newCall(request);
try {
Response response = call.execute();
addedValues.add(response.body());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
System.out.println(addedValues.size());
watch.stop();
System.out.println("----- t1 - Time Elapsed: " watch.getTime());
}
});
All the other threads are identical to this one. On the other side i have a Springboot application using the latest framework version. All the threads are calling a controller:
@PostMapping(
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE
)
public ResponseEntity<DatabaseCreationResponse> save(@RequestBody DatabaseRequest request) {
ModelMapper modelMapper = new ModelMapper();
modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
DatabaseDto requestDto = modelMapper.map(request, DatabaseDto.class);
DatabaseDto databaseDto = databaseService.save(requestDto);
return new ResponseEntity<>(
modelMapper.map(databaseDto, DatabaseCreationResponse.class),
HttpStatus.CREATED);
}
This controller is calling a service method - the service method is not yet fully implemented...
public DatabaseDto save(DatabaseDto requestDto) {
ModelMapper modelMapper = new ModelMapper();
modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
DatabaseDto returnValue;
try {
DatabaseEntity databaseEntity = modelMapper.map(requestDto, DatabaseEntity.class);
DatabaseEntity storedEntity = databaseRepository.save(databaseEntity);
returnValue = DatabaseDto.builder()
.operationId("generateUID")
.status("OK (use enum)")
.createdAt(new Date())
.build();
} catch (RuntimeException exception) {
returnValue = DatabaseDto.builder()
.operationId("generateUID")
.status("Error (use enum)")
.message(exception.getMessage())
.createdAt(new Date())
.build();
exception.printStackTrace();
}
return returnValue;
}
I tried to implement JNDI and using Hikari to handle know issues with SQLite and concurrent access to database.
First I defined my repository method as @Transactional:
@Transactional
@Override
DatabaseEntity save(DatabaseEntity entity);
Now to complete the configuration i added configurations to application.properties. I fist configured my datasource:
spring.datasource.driverClassName=org.sqlite.JDBC
spring.datasource.url=jdbc:sqlite:C:/data/db.db
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.jndiName=jdbc/myDataSource
#disable schema generation from Hibernate
spring.jpa.hibernate.ddl-auto=create
I also tried to configure Hikari:
#maximum number of milliseconds that a client will wait for a connection
spring.datasource.hikari.connection-timeout = 1800000
spring.datasource.hikari.connectionTimeout=1800000
#minimum number of idle connections maintained by HikariCP in a connection pool
spring.datasource.hikari.minimum-idle= 1
#maximum pool size
spring.datasource.hikari.maximum-pool-size= 1
spring.datasource.hikari.data-source-j-n-d-i=jdbc/myDataSource
#maximum idle time for connection
spring.datasource.hikari.idle-timeout=600000
spring.datasource.hikari.idleTimeout=600000
# maximum lifetime in milliseconds of a connection in the pool after it is closed.
spring.datasource.hikari.max-lifetime= 1800000
spring.datasource.hikari.maxLifetime=1800000
#default auto-commit behavior.
spring.datasource.hikari.auto-commit =true
Finally, I tried to set embedded tomcat server:
# Maximum queue length for incoming connection requests when all possible request processing threads are in use.
server.tomcat.accept-count=10000
# Delay between the invocation of backgroundProcess methods. If a duration suffix is not specified, seconds will be used.
server.tomcat.background-processor-delay=10s
# Maximum number of connections that the server accepts and processes at any given time.
server.tomcat.max-connections=1000000
# Maximum amount of worker threads.
server.tomcat.max-threads=20000
# Minimum amount of worker threads.
server.tomcat.min-spare-threads=1000
# Character encoding to use to decode the URI.
server.tomcat.uri-encoding=UTF-8
# server.tomcat.use-relative-redirects= # Whether HTTP 1.1 and later location headers generated by a call to sendRedirect will use relative or absolute redirects.
Now my issue is the following. I try to insert: 50 000 entries using 5 threads and after a while i do have the following error message in the back end application:
Caused by: org.hibernate.exception.GenericJDBCException: could not execute statement
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:61)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:109)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:95)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:200)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3392)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3991)
at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:103)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:612)
at org.hibernate.engine.spi.ActionQueue.lambda$executeActions$1(ActionQueue.java:483)
at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:480)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:329)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1422)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:476)
at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2233)
at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:1929)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:439)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:183)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:281)
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101)
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:562)
... 65 more
Caused by: org.sqlite.SQLiteException: [SQLITE_BUSY] The database file is locked (database is locked)
at org.sqlite.core.DB.newSQLException(DB.java:1135)
at org.sqlite.core.DB.newSQLException(DB.java:1146)
at org.sqlite.core.DB.execute(DB.java:941)
at org.sqlite.core.DB.executeUpdate(DB.java:1010)
at org.sqlite.jdbc3.JDBC3PreparedStatement.lambda$executeLargeUpdate$2(JDBC3PreparedStatement.java:118)
at org.sqlite.jdbc3.JDBC3Statement.withConnectionTimeout(JDBC3Statement.java:454)
at org.sqlite.jdbc3.JDBC3PreparedStatement.executeLargeUpdate(JDBC3PreparedStatement.java:117)
at org.sqlite.jdbc3.JDBC3PreparedStatement.executeUpdate(JDBC3PreparedStatement.java:99)
at jdk.internal.reflect.GeneratedMethodAccessor67.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.apache.tomcat.jdbc.pool.StatementFacade$StatementProxy.invoke(StatementFacade.java:118)
at jdk.proxy2/jdk.proxy2.$Proxy110.executeUpdate(Unknown Source)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:197)
... 84 more
In my front end application i do have another error message:
Exception in thread "Thread-0" Exception in thread "Thread-3" java.lang.RuntimeException: java.net.SocketException: No buffer space available (maximum connections reached?): connect
at fr.dsidiff.client.Main$1.run(Main.java:55)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.net.SocketException: No buffer space available (maximum connections reached?): connect
at java.base/java.net.PlainSocketImpl.connect0(Native Method)
at java.base/java.net.PlainSocketImpl.socketConnect(PlainSocketImpl.java:105)
at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:412)
at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:255)
at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:237)
at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.base/java.net.Socket.connect(Socket.java:608)
at okhttp3.internal.platform.Platform.connectSocket(Platform.kt:128)
at okhttp3.internal.connection.RealConnection.connectSocket(RealConnection.kt:295)
at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:207)
at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:226)
at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:106)
at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:74)
at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.kt:255)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201)
at okhttp3.internal.connection.RealCall.execute(RealCall.kt:154)
at fr.dsidiff.client.Main$1.run(Main.java:52)
... 1 more
Suppressed: java.net.SocketException: No buffer space available (maximum connections reached?): connect
... 26 more
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:566)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:743)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:711)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:654)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:407)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:163)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:218)
at jdk.proxy2/jdk.proxy2.$Proxy102.save(Unknown Source)
at fr.dsidiff.app.proxy.service.DatabaseService.save(DatabaseService.java:42)
at fr.dsidiff.app.proxy.ui.controller.DatabaseController.save(DatabaseController.java:51)
at jdk.internal.reflect.GeneratedMethodAccessor25.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:207)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:152)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:884)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1080)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:973)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1003)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:906)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:731)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:880)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:814)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:223)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:119)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:400)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1739)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: org.hibernate.exception.GenericJDBCException: could not execute statement
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:61)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:109)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:95)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:200)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3392)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3991)
at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:103)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:612)
at org.hibernate.engine.spi.ActionQueue.lambda$executeActions$1(ActionQueue.java:483)
at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:480)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:329)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1422)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:476)
at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2233)
at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:1929)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:439)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:183)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:281)
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101)
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:562)
... 65 more
Caused by: org.sqlite.SQLiteException: [SQLITE_BUSY] The database file is locked (database is locked)
at org.sqlite.core.DB.newSQLException(DB.java:1135)
at org.sqlite.core.DB.newSQLException(DB.java:1146)
at org.sqlite.core.DB.execute(DB.java:941)
at org.sqlite.core.DB.executeUpdate(DB.java:1010)
at org.sqlite.jdbc3.JDBC3PreparedStatement.lambda$executeLargeUpdate$2(JDBC3PreparedStatement.java:118)
at org.sqlite.jdbc3.JDBC3Statement.withConnectionTimeout(JDBC3Statement.java:454)
at org.sqlite.jdbc3.JDBC3PreparedStatement.executeLargeUpdate(JDBC3PreparedStatement.java:117)
at org.sqlite.jdbc3.JDBC3PreparedStatement.executeUpdate(JDBC3PreparedStatement.java:99)
at jdk.internal.reflect.GeneratedMethodAccessor67.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.apache.tomcat.jdbc.pool.StatementFacade$StatementProxy.invoke(StatementFacade.java:118)
at jdk.proxy2/jdk.proxy2.$Proxy110.executeUpdate(Unknown Source)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:197)
... 84 more
My questions are the following:
- is there a way to increase maximum number of connections ?
- is there a way to queue the queries or to make sure the connection is released between each HTTP queries ?
Actually, the application is running also as a jar, I will also have to deploy it into a Tomcat webserver as a War.
Thanks !
CodePudding user response:
I solved partially my file locked issue: i defined my service method as async
@Async
public synchronized DatabaseDto save(DatabaseDto requestDto) {
ModelMapper modelMapper = new ModelMapper();
modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
DatabaseDto returnValue;
try {
DatabaseEntity databaseEntity = modelMapper.map(requestDto, DatabaseEntity.class);
DatabaseEntity storedEntity = databaseRepository.save(databaseEntity);
returnValue = DatabaseDto.builder()
.operationId("generateUID")
.status("OK (use enum)")
.createdAt(new Date())
.build();
} catch (RuntimeException exception) {
returnValue = DatabaseDto.builder()
.operationId("generateUID")
.status("Error (use enum)")
.message(exception.getMessage())
.createdAt(new Date())
.build();
exception.printStackTrace();
}
return returnValue;
}
CodePudding user response:
I solved this issue by modifying my thread: the call.execute() method was not closing. I replaced my classic try catch with a try with resource in order to automatically close my execute call:
try(Response response = call.execute()) {
// Response response = call.execute();
addedValues.add(response.body());
I also tried to use Dispatcher and connexion pool for each client i instanciated. Here is my implementation:
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
List<ResponseBody> addedValues = new ArrayList<>();
StopWatch watch = new StopWatch();
watch.start();
Dispatcher dispatcher = new Dispatcher();
dispatcher.setMaxRequests(160);
dispatcher.setMaxRequestsPerHost(32);
OkHttpClient client = new OkHttpClient.Builder()
.dispatcher(dispatcher)
.connectTimeout(3600, TimeUnit.SECONDS)
.readTimeout(3600, TimeUnit.SECONDS)
.writeTimeout(3600, TimeUnit.SECONDS)
.retryOnConnectionFailure(true)
.connectionPool(new ConnectionPool(1500,600,TimeUnit.SECONDS))
.build();
for(int i = 0; i < 10000; i ) {
if(i % 1000 == 0 && i != 0) {
System.out.println("T1 " i);
}
String json = "{ "
"\"name\": \"db-t1-" i "\", "
"\"user\": \"test\", "
"\"password\": \"test\", "
"\"driver\": \"test\", "
"\"connectionString\": \"test\", "
"\"type\": \"test\""
"}";
RequestBody body = RequestBody.create(json, MediaType.get("application/json; charset=utf-8"));
Request request = new Request.Builder()
.url("http://localhost:8080/db")
.post(body)
.addHeader("Content-Type", "application/json")
.build();
Call call = client.newCall(request);
try(Response response = call.execute()) {
// Response response = call.execute();
addedValues.add(response.body());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
System.out.println(addedValues.size());
watch.stop();
System.out.println("----- t1 - Time Elapsed: " watch.getTime()); // Prints: Time
}
});