Below is a snippet of an existing Rest Interface implementation.
#RestController
#RequestMapping("/login")
public class LoginController {
#Autowired
private LoginProcessor loginProcessor;
#RequestMapping(
consumes = MediaType.TEXT_XML_VALUE,
produces = { MediaType.TEXT_XML_VALUE,
MediaType.APPLICATION_JSON_VALUE },
value = "/v1/login",
method = RequestMethod.POST)
public LoginResponse loginRequest(
#RequestBody String credentials) throws JAXBException {
return loginProcessor.request(credentials);
}
}
If the REST call to loginRequest() is initiated from different clients, and possibly, at the same time :-
1) Will a new thread be created to handle each request. Therefore, all requests are being processed concurrently ?
or
2) Is there one thread to handle all requests, which would mean only loginRequest() is being executed at any one time, and other request are queued up ?
I would ideally like to the interface to be able to handle multiple requests at any one time.
Thank you for your help in both clarifying and furthering my understanding on the subject.
Pete
You can search stack overflow for this type of question as it has been answered before. You can read these answers:
https://stackoverflow.com/a/7457252/10632970
https://stackoverflow.com/a/17236345/10632970
Good luck with your studies.
Every application should run in server either web server (tomcat) or application server (web logic), by default tomcat web container will have 200 threads ( you can adjust as your wish), so 200 threads can process concurrently at a time in tomcat
For every input request will be taken by web container thread and next to dispatcher servlet to corresponding controller class
I suppose you are using spring framework ( as you have used Autowired and other annotations). Thus to ans your ques: Yes spring will create new thread for each new request. Kindly refer to this answer, this should solve your queries
https://stackoverflow.com/a/17236345/7622687
Related
In my Spring Boot 2.1.6 project (based on Tomcat) I have a rest controller. I added a default constructor to it which prints something. I thought in Tomcat-based servers each request is handled in separate thread. So I expected each request to trigger a new controller object and as a result new print from the constructor. However, I made a test of sending 30 requests to the rest controller and I only see that the print was made once. So as far as I understand the rest controller handles all those requests in one thread.
My question is whether indeed multiple requests are handled in a single thread or maybe there's certain request threshold upon which another thread will be opened? I'm using default Spring Boot configuration perhaps this is controlled somewhere in the config?
This is the code for my controller:
#RestController
public class TrackingEventController {
public TrackingEventController() {
System.out.println("from TrackingEventController");
}
#RequestMapping(method=GET, path=trackingEventPath)
public ResponseEntity<Object> handleTrackingEvent(
#RequestParam(name = Routes.event) String event,
#RequestParam(name = Routes.pubId) String pubId,
#RequestParam(name = Routes.advId) String advId) {
return new ResponseEntity<>(null, new HttpHeaders(), HttpStatus.OK);
}
}
You're mixing two orthogonal concepts:
a thread
a controller instance
A single thread could create and/or use one, or several controller instances.
Multiple threads could also create and/or use one, or several controller instances.
The two are unrelated.
And how it actually works is
Spring beans are singletons by default, so Spring creates a single instance of your controller
A servlet container uses a pool of threads.
Every time a request comes in, a thread is chosen from the pool, and this thread handles the request. If the request is mapped to your controller, then the appropriate method of the unique controller instance is executed by this thread.
If you want to know which thread is handling the current request, add this to your controller method:
System.out.println(Thread.currentThread().getName());
Spring boot Tomcat thread pool default size is 200. You can make out that different threads server different requests. Put a debug point on some REST endpoint, and call it multiple times from Postman etc. From debugger, check the thread name. s.b.
I have a sprint boot (v1.5.15) based Restful application that provides user based services, particularly login and get user details.
The login activity is slightly heavy where as the get user details api is pretty light weight.
I have a controller akin to this
#RestController
public class UserController{
#PostMapping("/login")
public LoginResponse userLogin(#RequestBody LoginRequest loginRequest){
...
}
#GetMapping("/users/{id}")
public LoginResponse userIdGet(#PathVariable("id") String id){
...
}
}
Is there any way I could limit the number of concurrent calls to the /login api. Basically I want to limit this to say x as the /users/{id} can handle in the same resources around 10x of that calls.
The application uses the embedded tomcat server and I know of server.tomcat.max-connections, server.tomcat.max-threads and server.tomcat.min-spare-threads however these restrict the calls at the application level rather than at the API.
There are solutions which limit the number of active connections, see e.g. https://dzone.com/articles/how-to-limit-number-of-concurrent-user-session-in .
However, afaik, such solutions are just rejecting further request.
If you do not like to reject request, you might limit the concurrent work done by using using an application wide fixed thread pool ExecutorService ( https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html#newFixedThreadPool(int) ) and submit your request body to that thread pool and imediatly call get on the returned Future.
So you can replace
#PostMapping("/api/xyzMethod")
public Response xyzMethod(#RequestBody Request request) {
return handleXyzMethod(request); });
}
by
#PostMapping("/api/xyzMethod")
public Response xyzMethod(#RequestBody Request request) throws InterruptedException, ExecutionException {
return xyzMethodExecutor.submit(() -> { return handleXyzMethod(request); }).get();
}
with some
private static ExecutorService xyzMethodExecutor = Executors.newFixedThreadPool(10);
A drawback is that the user might have to wait for the reply and / or that multiple request will fill the threads pool queue until the service becomes (too) unresponsive. So maybe you have to endow this solution with some kind of timeout on the FutureTasks or combine the two solution (that is also have a larger limit on the number of concurrent sessions).
I am trying to write rest endpoints for user and his services. Not sure for the below use case it should be in User or Service controller.
The below examples will find the service in which the "userId" is a consumer or producer
http://localhost/user/{userId}/consumer/services
http://localhost/user/{userId}/producer/services
or
http://localhost/service/consumer/user/{userId}
http://localhost/service/producer/user/{userId}
The first example makes more sense to me, any suggestions and a good approach?
If you ask me, I would recommend the 1st approach. But having said that, I would route the requests to the Controllers this way
#RequestMapping(path = "/user")
public class UserController{
// write code for User API
}
#RequestMapping(path = "/user/{userId}/consumer")
public class ConsumerController{
// write code for Services API
}
#RequestMapping(path = "/user/{userId}/producer")
public class ProducerController{
// write code for Services API
}
Neither one. As long as the user is not the subject of action (entity on which action is performed), user info is the metadata which you can (and should) derive from the Authentication principal rather than what's coming on the URL
I am planning to use the following as it seems more appropriate.
http://localhost/service?userId={userId}&userType={userType}
userType= CONSUMER OR PRODUCER
The above will return the services where the userId is a CONSUMER or PRODUCER of the service.
Hi I just Need an application on DeferredResult in Spring MVC which clear it's working.
It is easier when you understand the concept of DeferredResult:
Your controller is eventually a function executed by the servlet container (for that matter, let's assume that the server container is Tomcat) worker thread. Your service flow start with Tomcat and ends with Tomcat. Tomcat gets the request from the client, holds the connection, and eventually returns a response to the client. Your code (controller or servlet) is somewhere in the middle.
Consider this flow:
Tomcat get client request.
Tomcat executes your controller.
Release Tomcat thread but keep the client connection (don't return response) and run heavy processing on different thread.
When your heavy processing complete, update Tomcat with its response and return it to the client (by Tomcat).
Because the servlet (your code) and the servlet container (Tomcat) are different entities, then to allow this flow (releasing tomcat thread but keep the client connection) we need to have this support in their contract, the package javax.servlet, which introduced in Servlet 3.0 . Spring MVC use this new Servlet 3.0 capability when the return value of the controller is DeferredResult (BTW, also Callable). DeferredResult is a class designed by Spring to allow more options (that I will describe) for asynchronous request processing in Spring MVC, and this class just holds the result (as implied by its name) so it means you need some kind of thread that will run you async code. What do you get by using DeferredResult as the return value of the controller? DeferredResult has built-in callbacks like onError, onTimeout, and onCompletion. It makes error handling very easy.
Here you can find a simple working examples I created.
The main part from the github example:
#RestController
public class DeferredResultController {
static ExecutorService threadPool = getThreadPool();
private Request request = new Request();
#RequestMapping(value="/deferredResultHelloWorld/{name}", method = RequestMethod.GET)
public DeferredResult<String> search(#PathVariable("name") String name) {
DeferredResult<String> deferredResult = new DeferredResult<>();
threadPool.submit(() -> deferredResult.setResult(request.runSleepOnOtherService(name)));
return deferredResult;
}
}
https://spring.io/blog/2012/05/14/spring-mvc-3-2-preview-adding-long-polling-to-an-existing-web-application
and the source code is: https://github.com/spring-projects/spring-amqp-samples/tree/spring-mvc-async
for useful articles see blog post series about spring async support:
https://spring.io/blog/2012/05/07/spring-mvc-3-2-preview-introducing-servlet-3-async-support
I'm writing a REST service with Spring Web 4.0.5 and one of called methods is sending e-mail (with javax mail). Sending mail takes some time, but I would like to be able to send HTTP response (no matter what response, e.g. 200) BEFORE this method finishes - so before the mail is sent. Is it even possible? Preferably without multithreading?
#RestController
#RequestMapping(value = "/mails", produces = "application/json")
public class RestMailService{
#Autowired
MailService mailService;
#RequestMapping(value="/test", method = RequestMethod.GET)
public void sendMail(){
mailService.sendMail();
}
}
I believe all possible solutions include multithreading. The thread will be either directly started by you or hidden behind messaging or something similar.
if you were to go with multi-threading after all please use some Executor instead of below suggested new Thread(...).start()
I would also note that returning HTTP 200 before the operation finishes may somewhat confuse the user as the code suggests the operation was successful where in fact the operation maybe didn't even start yet.