At a high level, I have a MemcachedPoolService class that has two methods: getClientInstance() and returnClientInstance(client). As expected, getClientInstance() returns an instance of a MemcachedClient (spymemcachced) to the caller, and returnClientInstance(client) returns a MemcachedClient back to the pool. MemcachedPoolService needs to be available to other @Stateless services (injected) that all need access to Memcached.
Currently I have MemcachedPoolService marked as a @Singleton, but I'm getting the following error when more than one client tries accessing the app:
[0m[31m16:54:22,968 ERROR [org.jboss.as.ejb3.invocation] (http-/0.0.0.0:8080-10)
JBAS014134: EJB Invocation failed on component MemcachedPoolService for method public
net.spy.memcached.MemcachedClient com.apexlab.cache.MemcachedPoolService.getClientInstance():
javax.ejb.EJBTransactionRolledbackException: JBAS014373: EJB 3.1 PFD2 4.8.5.5.1 concurrent
access timeout on org.jboss.invocation.InterceptorContext$Invocation@24bf375e - could not
obtain lock within 5000MILLISECONDS
What would be the best way to set up my MemcachedPoolService (and my web app in general) for a production environment to avoid getting the concurrent timeout exceptions?
First and foremost, MemcachedPoolService is a stateless service, and hence if you are not doing any db updates that require consistency (Thats why it is @Singleton anyway, otherwise you would use @Stateless), then simply mark the class as
@Singleton
@Lock(LockType.READ)
public class MemcachedPoolService{}
or
@Singleton
public class MemcachedPoolService{
@Lock(LockType.READ)
public void myPossibleMultiAccessMethod(){}
}
if thats not an option, then:
@Singleton
public class MemcachedPoolService{
@AccessTimeout(Integer.MORE_THAN_5000_MILLIS)
public void myPossibleMultiAccessMethod(){}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With