11 Replies Latest reply on Aug 1, 2008 10:32 AM by brian.stansberry

    Service threads


      This is in response to a few related JIRAs:


      There are other internal service threads as well, such as async cache loader writer threads, repl queue threads, etc.

      WRT. the JIRAs above, it makes sense to refactor these to use an ExecutorService and then allow users to pass in their own ExecutorService, either via an ExecutorServiceProvider interface, or by using a setter on the Configuration (for IOC frameworks). This would default to a fixed pool service using a single thread, except for the case of JBCACHE-1262 and JBCACHE-1108 where it may make sense to allow users to configure a pool size.

      Now my question is this - how much flexibility would people want? Does it make sense to use a single ExecutorService for all such service tasks? Or does it make sense for this to be more fine-grained?

      Brian, this would be related to your use case of not using the internal eviction thread for SFSB state.

      Perhaps what we need is a decoupling between the executors themselves and the tasks they are used for - e.g.,

       <executor name="evictionExecutor">
       <pool size="1" />
       <async />
       <executor name="genericExecutor">
       <executor name="evictionExecutor" />
       <executor name="genericExecutor" />
       <executor name="genericExecutor" />


        • 1. Re: Service threads

          So an "eviction" element with no "executor" child element means JBC doesn't run eviction, but lets me do it with my own thread? That's what I'd like.

          Besides that, +1 on allowing injection of the ExecutorService(s). Wherever possible, services that run in the AS should allow injection of centralized thread pools for this kind of stuff.

          • 2. Re: Service threads

            I was thinking more like no executor child element means we create and use a default one.

            If you want to provide your own thread with which to perform evictions you'd pass in a custom executor that provides this.

            Or does this not help your use case?

            • 3. Re: Service threads

              The issue is I don't provide the thread. JBossWeb or the EJB3 runtime provide the thread, and it periodically invokes my integration code telling it to "backgroundProcess". JBC eviction is then part of that background process work.

              Perhaps a clearer way to conceptualize the problem is to think of cache eviction as one step in an overall larger task. Say, for example, step 2 of 3. I want to control the order of execution of the whole task. JBC passing one step to an executor on its own schedule doesn't let me do that.

              If allowing configuration for this is too ugly, I could just drop in a custom executor that just drops tasks on the floor. The main thing for me is to make sure the API still exists for an external thread to run eviction (get region, get the eviction policy, trigger the policy to run.)

              • 4. Re: Service threads

                Perhaps a custom Executor that would block until your integration code is ready to run a background process, and then it takes the Runnable passed in to the Executor and deals with it?

                • 5. Re: Service threads

                  Maybe, but the Runnable you pass is probably going to be to clean all regions? Whereas the background process is only dealing with one (whatever region relates to the war/ejb undergoing background processing.)

                  • 6. Re: Service threads

                    Ah good point. You're talking about your own eviction algorithm then. :-)

                    • 7. Re: Service threads

                      Somewhat. I'm happy to access the existing EvictionPolicy associated with the region (which is part of the public API of Region, get the EvictionAlgorithm from that (which is part of the public EvictionPolicy API) and invoke process() on that (which is part of the public EvictionAlgorithm API).

                      Looking at the eviction system in JBC, it seems nicely set up to work a la carte:

                      1) An interceptor that generates events and passes them to the region, which queues them. (This is somewhat coupled to #2 via the EvictionPolicy.canIgnoreEvent() call the interceptor makes.)

                      2) The EvictionPolicy/Algorithm which can take a process the region's queue of events and determine what to evict, and then evict it.

                      3) The evict() API on the cache, which is used by EvictionPolicy/Algorithm but also allows self-managed eviction.

                      4) A thread-management system that kicks off #2.

                      So, main thing is I think JBC should support these combos from the a la carte menu:

                      #1 + #2 + #3 + #4 (of course)


                      #1 + #2 + #3.

                      If configuring this last one requires doing something a bit hacky that's OK by me, although it's better to just be able to say in a config "no #4 please". Again, to me the main thing is to keep those API calls I described above available. [1]

                      I don't see any point in JBC trying to support #1 + #3 (i.e. add a way to bypass the EvictionInterceptor call to EvictionPolicy.canIgnoreEvent()). If someone wants that they can just implement a CacheListener to get events.

                      [1] Probably a good separate discussion is the API of EvictionPolicy/EvictionAlgorithm. Currently those are a bit of a mix of API and SPI, with an implementation detail (delegate to EvictionAlgorithm) mixed in.

                      • 8. Re: Service threads

                        I agree that this should be a separate discussion. :-) Why don't you start one based on your comments above - which are very valid?

                        For the purposes of this discussion though, how much flexibility are we looking for in terms of configuring/sharing/providing an executor service?

                        • 9. Re: Service threads

                          Okay, then for 3.0 here is what I propose:

                          1. Eviction and ReplQueue scheduled tasks will now use a ScheduledExecutor instead, just to be more "current" and to make things easier for future changes around here.
                          2. AsyncCacheLoader to take in a maxThreads param and to use its own pooled exec service (with a default)
                          3. Same for async notifications (with a default)
                          4. TcpCacheServer will have its own threading cfgs anyway

                          And in future if people deem it useful I'll introduce the ability to inject a custom Executor for each of the above.

                          Now regarding eviction, Brian, could you start another thread/JIRA on redesigning eviction into the logical, distinct tasks you mentioned? I agree with most of your comments there and think eviction is a little too monolithic at the moment.


                          • 10. Re: Service threads

                            Regarding disabling the eviction thread by setting WakeupIntervalSeconds to 0, this is done.

                            • 11. Re: Service threads

                              Thanks for the WakeupIntervalSeconds = 0; perfect. :-)

                              Thread for eviction redesign: