I was researching some JDBC Oracle Connection Pooling items and came across a new(er) Oracle Pool implementation called Universal Connection Pool (UCP). Now this uses a new class, PoolDataSource, for connection pooling rather then the OracleDataSource [with the cache option enabled]. I am debating whether to switch to this new implementation but can't find any good documentation of what (if any) fixes/upgrades this would buy me. Anyone have an experience with both? Pluses/Minuses? Thanks.
Latest Oracle jdbc driver (11.2.0.1.0) explicit states that Oracle Implicit Connection cache (which is that one that use OracleDataSource) it's deprecated :
Oracle JDBC Drivers release 11.2.0.1.0 production Readme.txt
What Is New In This Release ?
Universal Connection Pool
In this release the Oracle Implicit Connection Cache feature is
deprecated. Users are strongly encouraged to use the new Universal
Connection Pool instead. The UCP has all of the features of the
ICC, plus much more. The UCP is available in a separate jar file,
ucp.jar.
So I think it's better to start using UCP, but the documentation it's not that good.
For example I didn't find a way to use UCP with spring...
UPDATE: I've found the correct spring configuration:
OK I think I've found the right configuration:
<bean id="dataSource" class="oracle.ucp.jdbc.PoolDataSourceFactory" factory-method="getPoolDataSource">
<property name="URL" value="jdbc:oracle:thin:#myserver:1521:mysid" />
<property name="user" value="myuser" />
<property name="password" value="mypassword" />
<property name="connectionFactoryClassName" value="oracle.jdbc.pool.OracleDataSource" />
<property name="connectionPoolName" value="ANAG_POOL" />
<property name="minPoolSize" value="5" />
<property name="maxPoolSize" value="10" />
<property name="initialPoolSize" value="5" />
<property name="inactiveConnectionTimeout" value="120" />
<property name="validateConnectionOnBorrow" value="true" />
<property name="maxStatements" value="10" />
</bean>
The key is to specify the right factory class and the right factory method
PDS is 'universal' as it provides the same level of pooling functionality you get in ODS for non-Oracle databases, e.g. MySQL.
See UCP Dev Guide, an article on Oracle website and UCP Transition Guide
I don't see any immediate benefit of moving to UCP (PDS) from ODS, but perhaps in the future Oracle will deprecate some of the functionality in ODS. I used ODS for a while and I'm quite happy with it for the time being, but if I started fresh I'd go with PDS.
I did an extensive evaluation of UCP and decided to NOT use UCP - please have a look at this post for details.
I tested the UCP and deployed it to production in a Spring 3.0.5 Hibernate app using Spring JMS listener containers and Spring-managed sessions and transactions using the #Transactional annotation. The data sometimes causes SQL constraint errors, due to separate listener threads trying to update the same record. When that happens, the exception is thrown by one method annotated by #Transactional and the error is logged into the database using another method annotated by #Transactional. For whatever reason, this process seems to result in a cursor leak, that eventually adds up and triggers the ORA-01000 open cursor limit exceeded error, causing the thread to cease processing anything.
OracleDataSource running in the same code doesn't seem to leak cursors, so it doesn't cause this problem.
This is a pretty weird scenario, but it indicates to me that it's a little too early to be using the UCP in an application with this kind of structure.
I too am testing UCP and am finding myself that I am having performance issues in a Thread Pool based application. Initially, I tried OracleDataSource, but am having trouble configuring it for batch processing. I keep getting NullPointerExceptions in the connections, leading me to believe I have some sort connection leak, but only with some application, there are other applications we manage that are not batch process oriented that OracleDataSource works well.
Based on this post and a few others I found researching this subject, I tried UCP. I found that with enough tweaking, I could get rid of closed connections/NullPointerExceptions on connections style errors, but Garbage Collection was taking a beating. Long-Term GC fills up fast and does not ever seem to free up until the application finishes running. This can sometimes take as long as a day or more if the load is really heavy. I also notice that it takes progressive longer to process data as well. I compare that to the now depreciated OracleCacheImpl class (that we currently use in production because it still "just works"), where it used a third of the GC memory that UCP does and processes files much faster. In all other applications UCP seems to work just fine and handles just about everything I throw at it, but the Thread Pool Application is a major app and I could not risk GC Exceptions in production.
The implicit connection caching performs quite a bit better than UCP if you use the connection validation. This corresponds to bug 16723836, which is scheduled to be fixed in 12.1.0.2.
UCP pooling becomes increasingly more expensive to get/return
connections as the concurrent load increases. The test compares the oracle
implicit connection caching, tomcat's pooling, and UCP. All 3 are
configured to allow a max of 200 connections, a minimum of 20 connections and
an initial size of 2. All 3 are configured to validate the connections as
they are removed from the pool. The tomcat pool uses the statement "select
sysdate from dual" for validation.
These results on a 64bit RedHat node with 64 logical cores (32 physical) and 128 GB of ram.
At 5 concurrent threads, UCP is the slowest, but total connection management
time (get and close) is under 1 ms on average.
As the concurrency is increased, UCP falls further and further behind the
other solutions:
25 Threads:
Implicit: 0.58ms
Tomcat: 0.92ms
UCP: 1.50ms
50 Threads:
Implicit: 0.92ms
Tomcat: 1.60ms
UCP: 6.80ms
100 Threads:
Implicit: 2.60ms
Tomcat: 3.20ms
UCP: 21.40ms
180 Threads:
Implicit: 13.86ms
Tomcat: 15.34ms
UCP: 40.70ms
There are two possible ways to use UCP in Spring Bean.xml.
For db.properties set by some file then load this then Use one of them:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:resources/db.properties</value>
</property>
</bean>
First one wiht oracle.ucp.jdbc.PoolDataSourceImpl :-
<bean id="dataSource" class="oracle.ucp.jdbc.PoolDataSourceImpl">
<property name="URL" value="${jdbc.url}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="validateConnectionOnBorrow" value="true"/>
<property name="connectionFactoryClassName" value="oracle.jdbc.pool.OracleDataSource" />
<property name="connectionPoolName" value="TEST_POOL" />
<property name="minPoolSize" value="10" />
<property name="maxPoolSize" value="20" />
<property name="initialPoolSize" value="12" />
</bean>
Second one with oracle.ucp.jdbc.PoolDataSourceFactory :-
<bean id="dataSource" class="oracle.ucp.jdbc.PoolDataSourceFactory"
factory-method="getPoolDataSource">
<property name="URL" value="${jdbc.url}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="validateConnectionOnBorrow" value="true"/>
<property name="connectionFactoryClassName" value="oracle.jdbc.pool.OracleDataSource" />
<property name="connectionPoolName" value="TEST_POOL" />
<property name="minPoolSize" value="10" />
<property name="maxPoolSize" value="20" />
<property name="initialPoolSize" value="12" />
</bean>
That's It :)
Here is the link for Detail Documentation :
https://docs.oracle.com/cd/E11882_01/java.112/e12265/connect.htm#CHDDCICA
I tried ucp and the performance is better... May be the key is using this
oracle.ucp.jdbc.PoolDataSource ds = (oracle.ucp.jdbc.PoolDataSource)envContext.lookup(url_r);
MyConnectionLabelingCallback callback = new MyConnectionLabelingCallback();
ds.registerConnectionLabelingCallback( callback );
Properties label = new Properties();
label.setProperty(pname, KEY);
conn = ds.getConnection(label);
This helps to borrow the connection and never closing it.. so the performance is great
The code for the callback class is
public class MyConnectionLabelingCallback
implements ConnectionLabelingCallback {
public MyConnectionLabelingCallback()
{
}
public int cost(Properties reqLabels, Properties currentLabels)
{
// Case 1: exact match
if (reqLabels.equals(currentLabels))
{
System.out.println("## Exact match found!! ##");
return 0;
}
// Case 2: some labels match with no unmatched labels
String iso1 = (String) reqLabels.get("TRANSACTION_ISOLATION");
String iso2 = (String) currentLabels.get("TRANSACTION_ISOLATION");
boolean match =
(iso1 != null && iso2 != null && iso1.equalsIgnoreCase(iso2));
Set rKeys = reqLabels.keySet();
Set cKeys = currentLabels.keySet();
if (match && rKeys.containsAll(cKeys))
{
System.out.println("## Partial match found!! ##");
return 10;
}
// No label matches to application's preference.
// Do not choose this connection.
System.out.println("## No match found!! ##");
return Integer.MAX_VALUE;
}
public boolean configure(Properties reqLabels, Object conn)
{
System.out.println("Configure################");
try
{
String isoStr = (String) reqLabels.get("TRANSACTION_ISOLATION");
((Connection)conn).setTransactionIsolation(Integer.valueOf(isoStr));
LabelableConnection lconn = (LabelableConnection) conn;
// Find the unmatched labels on this connection
Properties unmatchedLabels =
lconn.getUnmatchedConnectionLabels(reqLabels);
// Apply each label <key,value> in unmatchedLabels to conn
for (Map.Entry<Object, Object> label : unmatchedLabels.entrySet())
{
String key = (String) label.getKey();
String value = (String) label.getValue();
lconn.applyConnectionLabel(key, value);
}
}
catch (Exception exc)
{
return false;
}
return true;
}
}
Related
We have a 8 node Ignite cluster on production. Below is the cache configuration for one of the caches.
<bean id="cache-template-bean" abstract="true"
class="org.apache.ignite.configuration.CacheConfiguration">
<property name="name" value="inputDataCacheTemplate*"/>
<property name="cacheMode" value="PARTITIONED"/>
<property name="backups" value="1"/>
<property name="atomicityMode" value="ATOMIC"/>
<property name="dataRegionName" value="dr.prod.input"/>
<property name="partitionLossPolicy" value="READ_WRITE_SAFE"/>
<property name="writeSynchronizationMode" value="PRIMARY_SYNC"/>
<property name="statisticsEnabled" value="true"/>
<property name="affinity">
<bean class="org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction">
<property name="partitions" value="256"/>
</bean>
</property>
<property name="expiryPolicyFactory">
<bean class="javax.cache.expiry.CreatedExpiryPolicy" factory-method="factoryOf">
<constructor-arg>
<bean class="javax.cache.expiry.Duration">
<constructor-arg value="DAYS"/>
<constructor-arg value="7"/>
</bean>
</constructor-arg>
</bean>
</property>
</bean>
We are seeing a strange behaviour. It is as follows
Application A writes a record to cache
Application B tries to read that record
Application B is unable to find record in cache, so it inserts new one thereby wiping the data entered by Application A
3 happens very rarely. There are 1000 such cache miss for about 50M events we receive daily.
Gap between 1 and 2 is more than 20ms at least.
We tried putting a code in Application B where on first cache miss we wait for about 20ms. Now we could reduce those misses by a great margin. But still there were some misses. The fact that app B could read same record it could not find after a delay means that app A is not failing in record insertion, nor there is some other network factor which is impacting inserts nor it is because eviction or expiry. It is also ensured that for 1 and 2 key used for put and get operations is same.
What could be going on here? Please help.
I think it's more likely that you have a race condition.
Application B tries to read that record
Application A writes a record to cache
Application B is unable to find record in cache, so it inserts new one thereby wiping the data entered by Application A
Clients generally go to the primary partition to retrieve data, so it's incredibly unlikely that applications A and B are seeing different data.
The traditional way of dealing with this is with transactions, which would also work in Ignite.
Better might be using different APIs. For example, there's IgniteCache#getAndPutIfAbsent() and IgniteCache#putIfAbsent(), both of which do the check and write atomically without needing transactions.
We are facing a weird problem in which the activemq consumers for some random queues are decreasing till they become 0 after which they are not able to recover.
Once this happens we have to redeploy the consumer application again to start processing.
We have been struggling with this issue for some time but could not figure out the root cause.
activemq broker version 5.14.5
following is the connection configuration.
<bean id="activeMQIconnectConnectionFactory" class="test.ActiveMQIconnectConnectionFactory">
<property name="brokerURL" value="failover:(tcp://localhost:61616)"/>
<property name="prefetchPolicy" ref="prefetchPolicy"/>
<property name="redeliveryPolicy" ref="redeliveryPolicy"/>
<property name="trustAllPackages" value="true"/>
<!-- http://activemq.apache.org/consumer-dispatch-async.html
The default setting is dispatchAsync=true
If you want better thoughput and the chances of having a slow consumer are low, you may want to change this to false.
-->
<property name="dispatchAsync" value="true"/>
<!--
whether or not timestamps on messages should be disabled or not. If you disable them it adds a small performance boost.
Default is false
-->
<property name="disableTimeStampsByDefault" value="true"/>
<!-- http://activemq.apache.org/optimized-acknowledgement.html
This option is disabled by default but can be used to improve throughput in some circumstances as it decreases load on the broker.
-->
<property name="optimizeAcknowledge" value="true"/>
<!-- Default 300ms
For us, 5 sec.
-->
<property name="optimizeAcknowledgeTimeOut" value="5000"/>
<property name="useAsyncSend" value="true"/>
<property name="exceptionListener" ref="jmsExceptionListener"/>
</bean>
<bean id="testQueue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg index="0" value="test.queue"/>
</bean>
<bean id="jmsProducerFactoryPool" class="org.apache.activemq.pool.PooledConnectionFactory" destroy-method="stop"
init-method="start">
<property name="connectionFactory" ref="activeMQIconnectConnectionFactory"/>
<property name="maxConnections" value="10"/>
<property name="maximumActiveSessionPerConnection"
value="1000"/>
<property name="createConnectionOnStartup" value="true"/>
</bean>
<bean id="jmsConsumerFactoryPool" class="org.apache.activemq.pool.PooledConnectionFactory" destroy-method="stop"
init-method="start">
<property name="connectionFactory" ref="activeMQIconnectConnectionFactory"/>
<property name="maxConnections" value="10"/>
<property name="maximumActiveSessionPerConnection" value="1000"/>
<property name="createConnectionOnStartup" value="true"/>
<property name="reconnectOnException" value="true"/>
<property name="idleTimeout" value="86400000"/>
</bean>
<bean id="redeliveryPolicy" class="org.apache.activemq.RedeliveryPolicy">
<property name="maximumRedeliveries" value="1"/>
<property name="queue" value="*"/>
</bean>
<bean id="prefetchPolicy" class="org.apache.activemq.ActiveMQPrefetchPolicy">
<property name="queuePrefetch" value="500"/>
</bean>
<bean id="jmsTemplate" class="com.minda.iconnect.jms.impl.TimedJmsTemplate">
<property name="connectionFactory" ref="jmsProducerFactoryPool"/>
<property name="defaultDestinationName" value="iconnect.queue"/>
<property name="deliveryPersistent" value="true"/>
<!-- I think this is ingored if explicitQosEnabled is not set -->
</bean>
<bean id="simpleMessageConverter" class="org.springframework.jms.support.converter.SimpleMessageConverter"/>
<bean id="testProducer"
class="com.test.TestProducer">
<property name="consumerDestination" ref="testQueu"/>
<property name="jmsTemplate" ref="jmsTemplate"/>
<property name="messageConverter" ref="simpleMessageConverter"/>
</bean>
<bean id="testContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="jmsConsumerFactoryPool"/>
<property name="destination" ref="testS"/>
<property name="messageListener">
<bean class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
<property name="delegate" ref="testConsumer"/>
<property name="defaultListenerMethod" value="process"/>
<property name="messageConverter" ref="simpleMessageConverter"/>
</bean>
</property>
<property name="concurrentConsumers" value="50"/>
<property name="maxConcurrentConsumers" value="100"/>
<property name="sessionTransacted" value="false"/>
<property name="autoStartup" value="true"/>
</bean>
</beans>
class for connectionFactory
public class ActiveMQIconnectConnectionFactory extends org.apache.activemq.ActiveMQConnectionFactory
{
private static final Logger LOG = LoggerFactory.getLogger(ActiveMQIconnectConnectionFactory.class);
#Override
public void setBrokerURL(String brokerURL)
{
// LOG when connecting to activemq
// using this setter to be sure it's only logged once
// See DJ-5780
LOG.info("ActiveMQ configured is: " + (DEFAULT_BROKER_URL.equals(brokerURL) ? "(default init setting) " : "") + brokerURL);
LOG.info("Connecting to ActiveMQ");
super.setBrokerURL(brokerURL);
}
}
Till now we have been playing around the parameters for timeouts etc but not luck.
We suspect that the issue is occurring due to some connection issue or handling of connections via DMLC, but could not identify the problem. Help is highly appreciated!
I think that your problem is a mix of Spring DMLC and AMQ behaviors based on your configurations affecting each other.
try by changing :
<property name="optimizeAcknowledgeTimeOut" value="500"/>
AND
org.springframework.jms.listener.DefaultMessageListenerContainer.setReceiveTimeout(0);
Or
org.springframework.jms.listener.DefaultMessageListenerContainer.setReceiveTimeout(10000);
org.springframework.jms.listener.DefaultMessageListenerContainer.setIdleTaskExecutionLimit(100);
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jms/listener/AbstractPollingMessageListenerContainer.html#setReceiveTimeout-long-
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jms/listener/DefaultMessageListenerContainer.html#setIdleTaskExecutionLimit-int-
public void setIdleTaskExecutionLimit(int
idleTaskExecutionLimit) Specify the limit for idle executions of a
consumer task, not having received any message within its execution.
If this limit is reached, the task will shut down and leave receiving
to other executing tasks. The default is 1, closing idle resources
early once a task didn't receive a message. This applies to dynamic
scheduling only; see the "maxConcurrentConsumers" setting. The minimum
number of consumers (see "concurrentConsumers") will be kept around
until shutdown in any case.
Within each task execution, a number of message reception attempts
(according to the "maxMessagesPerTask" setting) will each wait for an
incoming message (according to the "receiveTimeout" setting). If all
of those receive attempts in a given task return without a message,
the task is considered idle with respect to received messages. Such a
task may still be rescheduled; however, once it reached the specified
"idleTaskExecutionLimit", it will shut down (in case of dynamic
scaling).
Raise this limit if you encounter too frequent scaling up and down.
With this limit being higher, an idle consumer will be kept around
longer, avoiding the restart of a consumer once a new load of messages
comes in. Alternatively, specify a higher "maxMessagesPerTask" and/or
"receiveTimeout" value, which will also lead to idle consumers being
kept around for a longer time (while also increasing the average
execution time of each scheduled task).
http://activemq.apache.org/performance-tuning.html
Optimized Acknowledge When consuming messages in auto acknowledge mode
(set when creating the consumers' session), ActiveMQ can acknowledge
receipt of messages back to the broker in batches (to improve
performance). The batch size is 65% of the prefetch limit for the
Consumer. Also if message consumption is slow the batch will be sent
every 300ms. You switch batch acknowledgment on by setting
optimizeAcknowledge=true on the ActiveMQ ConnectionFactory.
http://activemq.apache.org/what-is-the-prefetch-limit-for.html
Once the broker has dispatched a prefetch limit number of messages to
a consumer it will not dispatch any more messages to that consumer
until the consumer has acknowledged at least 50% of the prefetched
messages, e.g., prefetch/2, that it received. When the broker has
received said acknowledgements it will dispatch a further prefetch/2
number of messages to the consumer to 'top-up', as it were, its
prefetch buffer. Note that it's possible to specify a prefetch limit
on a per consumer basis (see below).
I have to poll a directory and write entries to rdbms.
I wired up a redis metadatstore for duplicates check. I see that the framework updates the redis store with entries for all files in the folder [~ 140 files], much before the rdbms entries gets written. At the time of application termination, rdbms has logged only 90 files. On application restart no more files are picked from folder.
Properties: msgs.per.poll=10, polling.interval=2000
How can I ensure entries to redis are made after writing to db, so that both are in sync and I don't miss any files.
<code>
<task:executor id="executor" pool-size="5" />
<int-file:inbound-channel-adapter channel="filesIn" directory="${input.Dir}" scanner="dirScanner" filter="compositeFileFilter" prevent-duplicates="true">
<int:poller fixed-delay="${polling.interval}" max-messages-per-poll="${msgs.per.poll}" task-executor="executor">
</int:poller>
</int-file:inbound-channel-adapter>
<int:channel id="filesIn" />
<bean id="dirScanner" class="org.springframework.integration.file.RecursiveLeafOnlyDirectoryScanner" />
<bean id="compositeFileFilter" class="org.springframework.integration.file.filters.CompositeFileListFilter">
<constructor-arg ref="persistentFilter" />
</bean>
<bean id="persistentFilter" class="org.springframework.integration.file.filters.FileSystemPersistentAcceptOnceFileListFilter">
<constructor-arg ref="metadataStore" />
</bean>
<bean name="metadataStore" class="org.springframework.integration.redis.metadata.RedisMetadataStore">
<constructor-arg name="connectionFactory" ref="redisConnectionFactory"/>
</bean>
<bean id="redisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:hostName="localhost" p:port="6379" />
<int-jdbc:outbound-channel-adapter channel="filesIn" data-source="dataSource" query="insert into files values (:path,:name,:size,:crDT,:mdDT,:id)"
sql-parameter-source-factory="spelSource">
</int-jdbc:outbound-channel-adapter>
....
</code>
Artem is correct, you might as well extend the RedisMetadataStore and flush the entries that are not in your database on initialization time, this way you could use Redis and be in sync with the DB. But this kind of couples things a little.
How can I ensure entries to redis are made after writing to db
It's isn't possible, because FileSystemPersistentAcceptOnceFileListFilter works before any message sending and only once, when FileReadingMessageSource.toBeReceived is empty. Of course, it tries to refetch files on the next application restart, but it can't do that because your RedisMetadataStore already contains entries for those files.
I think we don't have in your case any choice unless use some custom JdbcFileListFilter based on your files table. Fortunately you logic ends up with file entry anyway.
The Spring's DefaultMessageListenerContainer (DMLC) has concurrentConsumer and taskExecutor property. The taskExecutor bean can be given corePoolSize property. What is then the difference between specifying concurrentConsumer and corePoolSize ? When concurrentConsumer property is defined it means that Spring will create specified number of consumer/messageListeners to process the message. When does corePoolSize comes into picture ?
Code snippet
<bean id="myMessageListener"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
<property name="destination" ref="myQueue" />
<property name="messageListener" ref="myListener" />
<property name="cacheLevelName" value="CACHE_CONSUMER"/>
<property name="maxConcurrentConsumers" value="10"/>
<property name="concurrentConsumers" value="3"/>
<property name="taskExecutor" ref="myTaskExecutor"/>
</bean>
<bean id="myTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor" >
<property name="corePoolSize" value="100"/>
<property name="maxPoolSize" value="100"/>
<property name="keepAliveSeconds" value="30"/>
<property name="threadNamePrefix" value="myTaskExecutor"/>
</bean>
According to 4.3.6 version, the taskExecutor contains instances of AsyncMessageListenerInvoker which responsible for message processing. corePoolSize is a number of physical threads in the defined pool, while concurrentConsumer is a number of tasks in this pool. I guess this abstraction was designed for more flexible control.
The Purpose of TaskExecutor Property
Set the Spring TaskExecutor to use for running the listener threads.
Default is a SimpleAsyncTaskExecutor, starting up a number of new threads, according to the specified number of concurrent consumers.
Specify an alternative TaskExecutor for integration with an existing thread pool.
Above is from [Spring Official Documentation][1]
When you specify the alternative task executor, then instead of using the asyncTaskExcutor the listener threads will use the defined task executor.
This can be easily illustrated when we define two jmsListeners with the same containerFactory. when you specify the concurrency, the concurrency should support the taskExecutor corePoolSize and maxPoolSize.
If you set the concurrency as 5-20 and you have two listeners then you should set the core poolSize more than 10 and the maxPoolSize more than 40. then listeners can get the threads accordingly their concurrency limit.
In this case, If you set the maxPoolsize to less than 10 then the listener containers will not be upon 10. From the spring you will get below warning as well
The number of scheduled consumers has dropped below concurrent consumers limit, probably due to tasks having been rejected. Check your thread pool configuration! Automatic recovery to be triggered by remaining consumers.
basically, the listener threads will act based on the taskExecutor property.
I am testsing eclipselink to make bulk data insert into derby.
Compared by the same set of data, eclipse link take double time of jdbc batch update.
I have enabled the batchupdate feature of eclipse link, and the other properties:
<property name="eclipselink.jdbc.batch-writing" value="JDBC"/>
<property name="eclipselink.jdbc.batch-writing.size" value="1000"/>
<property name="eclipselink.jdbc.cache-statements" value="true"/>
<property name="eclipselink.jdbc.cache-statements.size" value="30"/>
<property name="eclipselink.cache.shared.default" value="false"/>
<property name="eclipselink.jdbc.read-connections.max" value="20"/>
<property name="eclipselink.jdbc.read-connections.min" value="1"/>
<property name="eclipselink.jdbc.write-connections.min" value="1"/>
<property name="eclipselink.jdbc.write-connections.max" value="30"/>
The question is how to make eclipse link be faster?
Please include the code, and the SQL log. Also include your JDBC code, and make sure it is kosher (closing statements, etc.).
Are you using sequence preallocation? If not then you will not be getting any batching (check your SQL log to see if the batch is occurring).
I would not change the connection pooling defaults, your are less efficient than the default (initial 1, min 32, max 32, no separate read/write pool). Having a different min/max will cause connection throttling, which is bad.
See,
http://java-persistence-performance.blogspot.com/2011/06/how-to-improve-jpa-performance-by-1825.html
Since JPA operates on top of JDBC, is will always take more time than fully optimized JDBC code. But does have the advantage of letting you use Java objects and not write JDBC code, and make major optimization such as batch writing just by changing a flag, instead of rewriting the code.