1
votes

If I have 4 Dart Server Running and I want to forward requests, how would I do that in Dart? On one hand I want to efficiently react on the requests but also be able to have certain requests handled in a distinct way or have an IP from a city handled somewhere. So I evaluate a session ID and say this session should be served by server2:1234 meaning the response ideally would be printed by that server, not routed everything through the server1:80 because that massively drains the availability of the server1:80

In "hello world" numbers:
server1:80 can serve aprox: 8000 req/sec
4 servers can serve aprox: 15-20000 req/sec (with nginx as a frontend)

Isolates can not handle httprequests afaik I would need to parse/downgrade the request for the isolate which is even worse.

2 questions:

How can I forward a request without blocking the main instance?
(like with nginx loadbalancing)
How can I ideally route requests to isolates?
(any example I found was either outdated or used a pattern that I would not prefere: spawning an isolate for every request... not a good Idea. I'd rather dynamically create server instances in Isolates and forward requests there)

The main issue I see is, that you don't share memory, so the question is, if it is even possible to route any data without having a duplicate copy. If servers run on different machines you would create serious traffic overhead. A method to dynamically header redirect/rewrite would be best I guess. But even for that I'd need lets say 4-16 "threads" on port 80 to be efficient. Afaik not possible with dart. Whats the best thing to do?

I'd really appreciate help here.

UPDATE

with this patch: https://codereview.chromium.org/250513002/
you can actually achieve parallel server processes which works similar as an older patch: https://codereview.chromium.org/25511002/

in both cases you listen on a same port but in case two you can just run another process and reuse the port while in case one you can run processes in isolates and share a ServerSocketReference.

The older patch needed some adjustments but finally with the new SDK I can at least get rid of nginx. Saving the nginx proxy pass delivers arround 10-20 % more hello world requests. With 2 parallel processes I achieved around 140% performance while with 3 and 4 it was just 145%. But in total arround 10k req/sec on my laptop which is fine(also states we just want to die in beauty here ;) )

This is highly experimental and nobody knows how it will work in the future. I recommend the first patch since it seems to be the cleaner approach.

Here is the basic example I wished to find earlier :)

import 'dart:io';
import 'dart:isolate';
isoserve(List d){
    d[0].create().then((server){
    HttpServer httpserver = new HttpServer.listenOn(server);
             httpserver.listen((HttpRequest hr){
             hr.response.write(d[1]);
         hr.response.close();
     });
    });
}

main() { 
    ServerSocket.bind(InternetAddress.ANY_IP_V6, 5555).then( (serverSocket) {
        Isolate.spawn(isoserve,[serverSocket.reference,"aloha world"]);
        Isolate.spawn(isoserve,[serverSocket.reference,"aloha world 2"]);
        });
}

UPDATE == works with SDK 1.4 now

1
That nginx feature is not sufficient for your requirements? library.linode.com/web-servers/nginx/configuration/… nginx load-balancing seems to support routing based on headers too spin.atomicobject.com/2013/07/08/… - Günter Zöchbauer
No. I know how to deal with distribution in nginx. I want to do the same thing in Dart to have full control in every step of the evaluation process of every request. In nginx I'd need to lua script. nginx is fine to serve files. I want to manage applications. As stated, in case I have a sessionID I want to be handled on some server I want to evaluate on the fly. and route it from>to a server. The port 80 is just one case. - Dr. Dama
I thought there was an open bug to support copying a connection to another isolate but I can't find it now. I think this is what you would need. - Günter Zöchbauer
If you're running on a recent linux kernel you can actually bind multiple listen sockets on the same port. To use this you need to patch the DartVM. See here. It's bit-rotted but is pretty easy to re-apply it manually. This will allow you to create a separate socket in each isolate and have them all listen on port 80. You can also just use separate processes instead of isolates. Note this doesn't address your port forwarding request. I don't think that is possible in general, not just with Dart. - Greg Lowe
Me too. It looks like there is another experimental change which has merged now, that lets you share sockets between isolates. codereview.chromium.org/250513002/diff/70001/sdk/lib/io/… - Greg Lowe

1 Answers

0
votes

Dart 1.13 adds the shared flag when creating server sockets and HttpServer instances. This allows more than one isolate to bind to the same port. The incoming connection requests are distributed equally to the listening isolates.


Seems there is no open bug for this. I found this information: https://groups.google.com/a/dartlang.org/forum/#!topic/misc/yYNRbBm0zmM

The Dart team is considering 'transferables' to allow copying other than List/Map/String/num/bool between isolates which should allow connections to be transferred to another isolate. The discussion also contains several other thoughts and attempts to this problem.