On Thursday, 10 January 2013 at 16:59, tumbler wrote:
If I use server in single-threaded mode it works fine.WebServers.createWebServer(8080);But if I try it with multi-threaded executors, like that:WebServers.createWebServer(Executors.newFixedThreadPool(2), 8080);Then I have exceptions both on client and server sides.
Thanks for explanation, Joe. Then I think assumption about only single-
threaded executor should be added to the constructor javadoc or
somewhere else.
After that I have one question. How important send the responses to
WebSocketConnection in the same event thread?
I mean not just call connection.send(message) from others threads,
but do:
connection.execute(new Runnable() {
@Override
public void run() {
connection.send(message);
}
});
I'm asking because until didn't meet any issue with that.
Webbit is designed to be a single threaded non-blocking server. All the assumptions inside this code are for this model. In short, you should only pass in a single threaded executor to Webbit.However, your handlers are free to communicate with other threads, for example if you are doing computationally expensive tasks or need to interact with an IO library that does not have a non-blocking interface. So long as you follow these rules:* Only ever pass a single threaded executor into the Webbit constructor.* Perform all your interactions with Webbit (including reading requests and writing responses) on this main executor.
--
You received this message because you are subscribed to the Google Groups "Webbit" group.
To unsubscribe from this group and stop receiving emails from it, send an email to webbit+un...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
Thanks for explaining how to have the worker thread call HttpControl.execute(Runnable) to get back onto the main thread followed by writing to the HttpResponse from there. It seems to work fine.This does complicate the design though, because now I need a wrapper object to pass back all the HttpResponse fields to the main thread (content type, cookies, status code, content, other response headers). This duplicates the methods of HttpResponse. Is it safe to call all the HttpResponse methods except for end() or error() from worker threads, assuming that only one worker thread will ever be handling one request? It would be much simpler to only have to run end() or error() back on the main thread once the response is fully composed. (Chunked responses would still need to call HttpControl.execute(Runnable) for each new chunk, once chunked encoding is supported.)
--
You received this message because you are subscribed to a topic in the Google Groups "Webbit" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/webbit/Vr_MN9CwNsA/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to webbit+un...@googlegroups.com.
I don't know how a nontrivial data-backed website or web service could be built that doesn't block on most HTTP requests, because most HTTP requests will need to hit a database. If all your database collections can fit in HashMaps in memory, then maybe you can do all data accesses on the main thread (and you can manually persist changes to the HashMaps to disk), but otherwise you need to hit a database, and it's a bit of a pain to have to create a Runnable that is sent off to a worker thread and then create another Runnable to go back to the main thread. I know that the callback-that-calls-a-callback model is what Node.js and similar follow today, but it makes your code unnecessarily complicated, especially in Java.In my code, I created a helper class that spawns the worker thread, collects all the HttpResponse-style parameters of the result and then calls back to the main thread. But I do think that something like this should provided in Webbit itself, because the need to query a database or access a file in an HTTP handler is pretty much universal, especially in the "stateless HTTP server" model, which punts all state to the database (and to session-in-client browser cookies) for scalability.You already have the async worker logic in place for IOWorkers; it would be nice to genericize this and create some sort of BlockingHttpHandler or something that is automatically wrapped in the async worker logic for you.
The trouble I see with this is that it would be very cumbersome to implement a generic user facing API without closure+lightweight SAM creation support that would allow you to carry the context while managing the thread switching (or at least, the end result would not look much better than it is today). Java 8 will fix both of these problems, until then one can use one of the alternative JVM languages with Webbit or create use case specific control-flows.
@Get("/login/{name}/{password}")public class LoginHandler extends RestHandler {public Response handleRequest(HttpRequest req, @Param("name") String name, @Param("password") String pw) {User user = User.authenticate(name, pw);if (user != null) {String pageHtml = Page.render("Login", Page.text("Successfully logged in));Session cookie = new Session(user);return html(pageHtml) //.cookie(cookie, user.getAuthTokenExpires());} else {return html(Page.render("Login failed", Page.text("Username/password incorrect"))) //.status(Response.UNAUTHORIZED).deleteCookie(Session.COOKIE_NAME);}}}
@Get("/profile/{profileid}")public class ProfileHandler extends RestHandler {public Response handleRequest(HttpRequest req, @Param("profileid") String profileid, User user) {return html(Page.render("Login", Page.text("Looking at profile for " + profileid+ "; user is logged in and verified as " + user.getEmail())));}}
// [...in method handleHttpRequest:...]
final RestHandler handler = this;Gribbit.threadPoolExecutor.submit(new Runnable() {@Overridepublic void run() {// Invoke subclass method handleRequest() with extra params extracted from URL. Method can block.Response response;try {response = (Response) handleRequestMethod.invoke(handler, args);
} catch (Exception e) {response = new Response().status(Response.INTERNAL_SERVER_ERROR).contentText("Error processing this request");
}// Once request is complete, schedule writing of result back to response on the main Webbit server thread.final Response responseCopy = response;ctl.execute(new Runnable() {@Overridepublic void run() {// Send response back on 'res'responseCopy.sendResponse(res, ctl);}});}});
On Wed, Apr 10, 2013 at 7:37 AM, peter hausel <peter....@gmail.com> wrote:The trouble I see with this is that it would be very cumbersome to implement a generic user facing API without closure+lightweight SAM creation support that would allow you to carry the context while managing the thread switching (or at least, the end result would not look much better than it is today). Java 8 will fix both of these problems, until then one can use one of the alternative JVM languages with Webbit or create use case specific control-flows.I don't really understand what you mean here: what problems are you describing, and how will features in Java 8 fix these problems?