Most ‘middle’ physical endpoints in NetKernel should be written to be threadsafe. The kernel can schedule threadsafe endpoint execution on any available worker thread in the kernel worker thread pool, in parallel with other endpoints (or other requests to the same endpoint). This allows the kernel to automatically maximise the use of all available CPU processing cores on the computer running NetKernel.
Non-threadsafe endpoints can only be executed one at a time in series, which creates a big processing bottleneck if a series of requests to the same non-threadsafe endpoint are made at the same time.
By default endpoints are not considered to be threadsafe by NetKernel. By default, execution of endpoints is serialised such that any particular endpoint can only process one request at a time. This is a safe default when developing endpoints, however if your endpoints do not contain any state between request handling - i.e. they only have local variables and not member variables, or if any shared state is thread safely accessed, then it is a good idea to call declareThreadSafe() in your endpoints constructor to declare its use to be thread safe. This reduces any contention and liveness issues. This is particularly important for overlays and other infrastructural endpoints that will often need to process large numbers of requests. –From the NetKernel documentation
By default, an endpoint that extends the StandardAccessorImpl
base class is assumed to be NON-THREADSAFE by the kernel. NetKernel has to be told that an endpoint is threadsafe; it’s not clever enough to parse your source code to determine that for itself. This is done by invoking the declareThreadSafe
superclass method in your endpoint’s constructor:
public class MyAccessor extends StandardAccessorImpl {
public MyAccessor() {
declareThreadSafe();
}
}
It is a common ‘gotcha’ of newbie (and not so newbie) NetKernel developers to forget to do this. The execution bottleneck may only show up later in load testing (e.g. comparing count
vs. expected in the Endpoint Profiler tool).
One technique I have used is to create a simple ThreadSafeStandardAccessorImpl
utility class somewhere in my NetKernel classpath, that just calls declareThreadSafe
in its constructor. All my threadsafe endpoints (which are almost all of them) extend this class. For some reason, I just find it much easier to remember to declare each endpoint class by extending ThreadSafeStandardAccessorImpl
than remembering to add the declareThreadSafe()
method call. Your mileage may vary.
Then my endpoint code becomes:
public class MyAccessor extends ThreadSafeStandardAccessorImpl {
@Override
public void onSource(INKFRequestContext aContext) throws Exception {
...
}
}
Note that I no longer even need a constructor method, unless there are other declarations to be made.
Other advantages to this technique is that I can use my IDE of choice to quickly scan my source code for any endpoint classes that do not extend ThreadSafeStandardAccessorImpl
, and so therefore may be erroneously assumed to be non-threadsafe by NetKernel. You can also use the Non-Threadsafe Endpoints page in the NetKernel Backend Fulcrum.
Of course, it is still up to the developer to ensure that a ThreadSafeStandardAccessorImpl
- extended endpoint class is ACTUALLY threadsafe in practise. Follow established best practise for writing any Java threadsafe code, as well as NetKernel - specific rules for ensuring thread safety such as:
For more information on NetKernel endpoint thread safety, check out these links: