I'm reading "RESTful Java with JAX-RS 2.0" book. I'm completely confused with asynchronous JAX-RS, so I ask all questions in one. The book writes asynchronous server like this:
#Path("/customers")
public class CustomerResource {
#GET
#Path("{id}")
#Produces(MediaType.APPLICATION_XML)
public void getCustomer(#Suspended final AsyncResponse asyncResponse,
#Context final Request request,
#PathParam(value = "id") final int id) {
new Thread() {
#Override
public void run() {
asyncResponse.resume(Response.ok(new Customer(id)).build());
}
}.start();
}
}
Netbeans creates asynchronous server like this:
#Path("/customers")
public class CustomerResource {
private final ExecutorService executorService = java.util.concurrent.Executors.newCachedThreadPool();
#GET
#Path("{id}")
#Produces(MediaType.APPLICATION_XML)
public void getCustomer(#Suspended final AsyncResponse asyncResponse,
#Context final Request request,
#PathParam(value = "id") final int id) {
executorService.submit(new Runnable() {
#Override
public void run() {
doGetCustomer(id);
asyncResponse.resume(javax.ws.rs.core.Response.ok().build());
}
});
}
private void doGetCustomer(#PathParam(value = "id") final int id) {
}
}
Those that do not create background threads use some locking methods to store response objects for further processing. This example is for sending stock quotes to clients:
#Path("qoute/RHT")
public class RHTQuoteResource {
protected List<AsyncResponse> responses;
#GET
#Produces("text/plain")
public void getQuote(#Suspended AsyncResponse response) {
synchronized (responses) {
responses.add(response);
}
}
}
responses object will be shared with some background jobs and it will send quote to all clients when it is ready.
My questions:
In example 1 and 2 web server thread(the one that handle request) dies
and we create another background thread. The whole idea behind
asynchronous server is to reduce idle threads. These examples are
not reducing idle threads. One threads dies and another one born.
I thought creating unmanaged threads inside container is a bad idea.
We should only use managed threads using concurrency utilities in
Java EE 7.
Again one of ideas behind async servers is to scale. Example 3 does not scale, does it?
Executive Summary: You're over-thinking this.
In example 1 and 2 web server thread(the one that handle request) dies and we create another background thread. The whole idea behind asynchronous server is to reduce idle threads. These examples are not reducing idle threads. One threads dies and another one born.
Neither is particularly great, to be honest. In a production service, you wouldn't hold the executor in a private field like that but instead would have it as a separately configured object (e.g., its own Spring bean). On the other hand, such a sophisticated example would be rather harder for you to understand without a lot more context; applications that consist of systems of beans/managed resources have to be built to be that way from the ground up. It's also not very important for small-scale work to be very careful about this, and that's a lot of web applications.
The gripping hand is that the recovery from server restart is actually not something to worry about too much in the first place. If the server restarts you'll probably lose all the connections anyway, and if those AsyncResponse objects aren't Serializable in some way (no guarantee that they are or aren't), you can't store them in a database to enable recovery. Best to not worry about it too much as there's not much you can do! (Clients are also going to time out after a while if they don't get any response back; you can't hold them indefinitely.)
I thought creating unmanaged threads inside container is a bad idea. We should only use managed threads using concurrency utilities in Java EE 7.
It's an example! Supply the executor from outside however you want for your fancy production system.
Again one of ideas behind async servers is to scale. Example 3 does not scale, does it?
It's just enqueueing an object on a list, which isn't a very slow operation at all, especially when compared with the cost of all the networking and deserializing/serializing going on. What it doesn't show is the other parts of the application which take things off that list, perform the processing, and yield the result back; they could be poorly implemented and cause problems, or they could be done carefully and the system work well.
If you can do it better in your code, by all means do so. (Just be aware that you can't store the work items in the database, or at least you can't know for sure that you can do that, even if it happens to be actually possible. I doubt it though; there's likely information about the TCP network connection in there, and that's never easy to store and restore fully.)
I share your view expressed in question 1. Let me just add a little detail that the webserver thread doesn't die, it typically comes from a pool and frees itself for another web request. But that doesn't really change much in terms of efficiency of async processing. In those examples, async processing is merely used to pass the processing from one thread pool to another. I don't see any point at all in that.
But there is one use-case where I think async makes sense, eg. when you want to register multiple clients to wait for an event and send a response to all of them once the event occurs. It is described in this article: http://java.dzone.com/articles/whats-new-jax-rs-20
The throughput of the service improves if different thread pools manage request I/O and request processing. Freeing up the request-I/O thread managed by the container allows it to receive the next request, prepare it for processing and feed into the request-processing-thread-pool when a request-processing-thread has been released.
Related
I am working a java library, which has a singleton class with a methods - createTask() and addPointsToTask()
The library is meant to be used in any java service which executes multiple requests.
The service should be able to call createTask only once during it's processing of a single request. Any further calls to createTask in the same thread execution should fail. addPointsToTask can be called any number of times.
As a library owner how can I restrict this method to be called only once per thread?
I have explored ThreadLocal, but don't think it fits my purpose.
One solution is to ask the service that is using the library to set a unique id in threadLocal, but as this 'set-to-thread-local' solution is outside the boundary of the library, this is not a full-proof solution.
Any hints?
Short answer: you won't get a "fool-proof" solution; i.e. a solution that someone can't subvert.
Unless you are running your library on a JVM platfrom that you control, users of your library will be able to find a way to subvert your "only once per thread" restriction if they try hard enough. For example:
They could use reflection to access the private state of the objects or classes that implement the restriction.
They could use bytecode injection to subvert your code.
They could decompile and replacing your code.
They could modify their JVM to do something funky with your code. (The OpenJDK source code is available to anyone.)
Ask yourself the following:
Is this restriction reasonable from the perspective of the programmer you are trying to restrict?
Would a sensible programmer have good reason to try to break it?
Have you considered possible use-cases for your library where it would be reasonable to call createTask() multiple times? For example, use-cases that involve using thread pools?
If you are doing this because you think allowing multiple createTask() calls will break your library, my advice would be:
Tell the programmer via the javadocs and other documentation what is likely to break if they do the thing that you are trying to prevent.
Implement a "soft" check, and provide an easy way for a programmer to disable the check. (But do the check by default, if you think that is appropriate.)
The point is that a sensible programmer won't knowingly subvert restrictions unless they have good reason to. If they do, and they hurt themselves, that is not your problem.
On the other hand, you are implementing this restriction for "business reasons" or to stop "cheating" or something like that, my advice would be to recognize that a determined user will be able to subvert any restrictions you attempt to embed in your code when they run it on their platform. If this fundamentally breaks your model, look for a different model.
You will not be able to prohibit multiple calls from the same request, simply because your library has no concept of what a "request" actually is. This very much depends on the service using the library. Some services may use a single thread per request, but others may not. Using thread-locals is error-prone especially when you are working in multi-threaded or reactive applications where code processing a request can execute on multiple parallel threads.
If your requirement is that addPointsToTask is only called for a task that was actually started by some code that is processing the current request, you could set up your API like that. E.g. createTask could return a context object that is required to call addPointsToTask later.
public TaskContext createTask() {
}
public void addPointsToTask(TaskContext context, ....) {
}
This way you can track task context even over multiple different threads executing code for the same request and points will not get added to a task created by another request.
You could add a method to your singleton which runs some piece of Service-Code in the context of a request.
Dummy implementation:
package stackoverflow;
import java.util.concurrent.Callable;
public enum YourLibrarySingleton {
INSTANCE;
private final ThreadLocal<Task> threadLocalTask;
YourLibrarySingleton() {
this.threadLocalTask = new ThreadLocal<>();
}
public void createTask() {
this.threadLocalTask.set(new Task() {});
}
public void addPointsToTask() {
Task task = this.threadLocalTask.get();
// add points to that task
}
public <T> T handleRequest(Callable<T> callable) throws Exception {
try {
return callable.call();
} finally {
this.threadLocalTask.remove();
}
}
}
Which could be used like this:
package stackoverflow;
public class ServiceCode {
public void handleRequest() throws Exception {
YourLibrarySingleton.INSTANCE.handleRequest(() -> {
YourLibrarySingleton.INSTANCE.createTask();
YourLibrarySingleton.INSTANCE.addPointsToTask();
YourLibrarySingleton.INSTANCE.addPointsToTask();
return "result";
});
}
}
I am facing the following situation, which to my surprise, I couldn't find much documentation:
There is a service which only provides a rest call for item details, by obtaining it 1 by 1.
There are 1k+ items in total.
For responsiveness reasons, I would like to persist this data on my end, and not fetch it lazily.
In order for my API key to not be locked, I would like to limit my calls to X calls / second.
I could not find any support for this in the Feign documentation.
Does anybody know if there is one? Or do you have any suggestions on how to go about this implementation?
There is no built in throttling capability in Feign, that is delegated to the underlying Client implementation. With that said, you can define your own client extending from one of the provided ones, Apache Http, OkHttp, and Ribbon.
One solution is to extend the Client to use a ScheduledThreadPoolExecutor as outlined in this answer.
Apache HttpClient: Limit total calls per second
To use this with the provided ApacheHttpClient in Feign, you could extend it, providing your own implementation of the execute method to use the executor.
public class ThrottledHttpClient extends ApacheHttpClient {
// create a pool with one thread, you'll control the flow later.
private final ExecutorService throttledQueue = Executors.newScheduledThreadPool(1);
#Override
public Response execute(Request request, Request.Options options) throws IOException {
// use the executor
ScheduledFuture<Response> future = throttledQueue.scheduleAtFixedRate(super.execute(), ....);
return future.get()
}
Set the appropriate thread pool size, delay and fixed wait to achieve the throughput you desire.
Play! touts its asynchronous HTTP handling feature, though it is not very clear to me what else are truly async (non-blocking and without thread switching.) In the asynchronous examples I read, like the one below taken from the Play! Framework Cookbook:
public static void generateInvoice(Long orderId) {
Order order = Order.findById(orderId); // #a
InputStream is = await(new OrderAsPdfJob(order).now()); // #b
renderBinary(is);
}
They focuses on the long/expensive "business logic" step at #b, but my concern is at the DB calls at #a. In fact, majority of the controller methods in many apps will just try to do multiple CRUD to DB, like:
public static void generateInvoice(Long orderId) {
Order order = Order.findById(orderId); // #a
render(order);
}
I'm particularly concerned about the claim of using "small number of threads" when serving this DB access pattern.
So the questions are
Will Play! will block on the JDBC calls?
If we wrap such calls in future/promise/await, it will cause thread switching (besides the inconvenience due the pervasiveness of DB calls,) right?
In light of this, how does its asynchronism comparing to a servlet server with NIO connector (e.g. Tomcat + NIO connector but without using the new event handler) in serving this DB access pattern?
Is there any plan to support asynchronous DB driver, like http://code.google.com/p/adbcj/ ?
Play will block on JDBC calls--there's no magic to prevent that.
To wrap a j.u.c.Future in an F.Promise for Play, a loop is needed. This can result in a lot of context switches.
Servlet containers can use NIO e.g. to keep connections open between requests without tying up threads for inactive connections. But a JDBC call in request handling code will block and tie up a thread just the same.
ADBCJ implements j.u.c.Future, but also supports callbacks, which can be tied to an F.Promise, see https://groups.google.com/d/topic/play-framework/c4DOOtGF50c/discussion.
I'm not convinced Play's async feature is worthwhile, given how much it complicates the code and testing. Maybe if you need to handle thousands of requests per second on a single machine while calling slow services.
I have a question bother me a while.
For example,I have a multithreaded server, when it receives a request, it pass this request to a handler, this handler will process this request. One reason we make server multithreaded is:
if it is not multithreaded, when the server processing this request, during the meaning time,
another request coming, then this request will be drop, because the server is not available now.
So I wonder if there is an alternative of multithreaded server, for example, we can create a queue for non-multithreading server? when it can fetch another request from the queue once it finish one.
Yes, you can have an event-based server. This capability is offered by the java.nio package, though you could use a framework like netty rather than do it from scratch.
However, note that while this used to be considered a way to get better performance, it seems like a regular multithreaded server actually offers better performances with today's hardware and operating systems.
Yes you can. Have you considered SEDA-like techniques (i.e. event-driven techniques)? You may want to investigate the Netty library too. It does most of the job for you when it comes to using NIO.
You can still have a single threaded engine with a multi-threaded server.
consider the following skeleton - if you have an Engine that runs, it can be completely single threaded, just handing requests in the order they're received. This allows you to use non-thread-safe components in the business logic, and you've managed to separate your networking layer from your business logic layer! It's a win-win scenario.
class Engine implements Runnable {
private final Object requestLock = new Object();
private List<Request> requests = new LinkedList<Request>();
private boolean running = true;
private Request nextRequest() {
synchronized(requestLock) { return requests.poll(); }
}
/**
* The engine is single threaded. It doesn't care about server connections
*/
public void run() {
while(running) {
Request request = nextRequest();
// handle your request as normal
// also consider making a mechanism to send Responses
}
}
}
The EJB 3.0 specification does not allow a business method of a stateless session bean to create new threads. Why is that? What is wrong with creating additional worker threads that only do raw computations and never call into the app server?
Say, my session bean implements a service that lets users to upload images, and the business method does cpu-intensive image processing on these images. Then it can only use one cpu core to do this job, even if the machine has 8 or more cores? If i utilize a third party image processing library, that internally creates worker threads, i would also violate the EJB specs, even though that library and these threads have nothing to do with the EJB container at all. This does not seem right.
What can happen if i ignore the EJB rules and still create some worker threads to do cpu intensive processing? Of course these threads will never touch any app server objects and the bean thread will join them before returning. Can still something bad happen?
The EJB 3.0 specification does not allow a business method of a stateless session bean to create new threads. Why is that?
Short version: managing threads from EJBs is disallowed because it would harm resource management, transaction management, security (technical reasons) and also because this is something the EJB model doesn't want to promote (philosophical reason).
The EJB specification puts it like this:
21.1.2 Programming Restrictions
...
The enterprise bean must not attempt to manage threads. The enterprise bean must not attempt to start, stop, suspend, or resume a thread, or to change a thread’s priority or name. The enterprise bean must not attempt to manage thread groups.
These functions are reserved for the EJB container. Allowing the enterprise bean to manage threads would decrease the container’s ability to properly manage the runtime environment.
See also
Why is thread creation and management disallowed? in the EJB Restrictions FAQ
Why are beans not allowed to create their own threads?
Concurrency Utilities for Java EE
Section 2.1 "Container-Managed vs. Unmanaged Threads"
(...) If i utilize a third party image processing library, that internally creates worker threads, i would also violate the EJB specs, even though that library and these threads have nothing to do with the EJB container at all. This does not seem right.
What can I say, don't use EJBs if you don't like this.
What can happen if i ignore the EJB rules and still create some worker threads to do cpu intensive processing? Of course these threads will never touch any app server objects and the bean thread will join them before returning. Can still something bad happen?
Whether these threads are touching the app server objects or not doesn't matter. Rules are rules, you don't want to follow them, you're on your own and the behavior is undefined. Some container might be more permissive and allow it, some other won't, your application won't be portable, etc. But it's still explicitly forbidden.
If you want to "spawn" threads in a standard way, use the WorkManager API, or use JMS.
Related Questions
How can an EJB parallelize a long, CPU intensive process?
In my simplified understanding, it's like running a company. You're the boss (the container), and there's an employee which suddenly just hire 100 people out of the blue without any notice (the bean).
But you can still easily do multithreading with the #Asynchronous annotation (there are other ways too).
#Stateless
public class Employee {
#Asynchronous
public Future<Void> work(Project projectThatTakeTooLong) {
// work work work
return new AsyncResult<Void>(null);
}
}
#Stateless
public class Boss {
#Inject
private Employee randomStatelessEmployee;
public void giveWork() {
Future<Void> result1 = randomStatelessEmployee.work(new Project());
Future<Void> result2 = randomStatelessEmployee.work(new Project());
Future<Void> result3 = randomStatelessEmployee.work(new Project());
result1.get();
result2.get();
result3.get();
}
}
There's also a better example here:
Jboss Java EE container and an ExecutorService
One type of workaround:
import java.util.concurrent.Executor;
import javax.ejb.Asynchronous;
import javax.ejb.Stateless;
#Stateless
public class TransactionalExecutor implements Executor {
#Override #Asynchronous
public void execute(Runnable command) {
command.run();
}
}
Now you can use TransactionalExecutor as an executor:
#Stateless
public class SlowService {
#Inject
Executor command;
public void invoke(){
Runnable command = new Runnable() {
#Override
public void run() {
// heavy task
}
};
command.execute(command);
}
}
This is known restriction not to use threads in J2EE applications.
Application server should take care of parallel execution of the program
Yes, you can ignore the EJB rules but can face with extremely unpredictable behaviour.