Using Qi4j as a skeleton framework in a high throughput, highly concurrent servlet deployment (and problems with race conditions)

19 views
Skip to first unread message

Tasos Parisinos

unread,
Apr 1, 2015, 2:07:55 PM4/1/15
to qi4j...@googlegroups.com
Hi all

Let me describe my problem. We have implemented a servlet (deployed in tomcat) that takes a REST request and based on its query parameters, it builds and executes a single query (using Hibernate ORM) within a JTA transaction (using Atomikos). The application specifics are not important, what is important is that we need high throughput (15.000 trx / sec is our objective).

We have implemented all infrastructure code using Qi4j for COP and DI as well as Property<T> data validation (constraint annotations). In deployment time (in a separate thread) we assemble and activate two Qi4j runtimes, each with a Qi4j application. The first is used only during deployment, while the second is used in ALL  threads that serve requests. Using Qi4j this second application, starts various ServiceComposite while the servlet deployes, for eager initialization (logger service, mapping service, repository service, rest service, application services, domain services, transaction service, token service to name only some). We implement our Use Cases with a DCI design.

These services and DCI code uses various ValueBuilder<T> and TransientBuilder<T> to do composition. 

The problem is:

Because ALL request threads, use the same Qi4j application, we have various race conditions that are mainly associated with the various builders. These race conditions appear when the servlet serves more that 2000 trx / sec. Sacrificing some throughput we can synchronize shared variables, but to minimize performance impact we need to know:

1. What is the best practice for such cases
2. Which part of ValueBuilderFactory, ValueBuilder<T>, TransientBuilderFactory, TransientBuilder<T> is best to synchronize?

Thanx in advance

Kent Sølvsten

unread,
Apr 1, 2015, 3:26:16 PM4/1/15
to qi4j...@googlegroups.com
I am not an expert so it might be the blind leading the deaf ......

but i sense a potential problem with concurrent access to various variants of ValueBuilderFactory#newValueBuilder and TransientBuilderFactory#newTransientBuilder.
(the internal usage of ConcurrentHashMap inside TypeLookup - shouldn't we use putIfAbsent?).

So that would be good candidates for synchronization. If that solves your problem i believe you might have found a bug - and a work-around.
ValueBuilder and TransientBuilder instances should probably be created, used and discarded inside a single web request and not reused.

/Kent
--
You received this message because you are subscribed to the Google Groups "qi4j-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to qi4j-dev+u...@googlegroups.com.
To post to this group, send email to qi4j...@googlegroups.com.
Visit this group at http://groups.google.com/group/qi4j-dev.
For more options, visit https://groups.google.com/d/optout.

Tasos Parisinos

unread,
Apr 1, 2015, 3:50:03 PM4/1/15
to qi4j...@googlegroups.com
Thanx for you reply Kent

I agree with you that builder instances should be created used and discarded inside a single request (a single thread from the servlet container pool). The builder factories though, as the application itself should be used commonly across all request threads (in a synchronized manner) in order to avoid instantiating such an application PER thread, as this will greatly compromise performance. The use of putIfAbsent in that context seems to be corrent. I'll give it a try and update you with results
Reply all
Reply to author
Forward
0 new messages