1

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

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
Dr. Dama
  • 167
  • 2
  • 5
  • That nginx feature is not sufficient for your requirements? https://library.linode.com/web-servers/nginx/configuration/front-end-proxy-and-software-load-balancing#sph_software-load-balancing nginx load-balancing seems to support routing based on headers too http://spin.atomicobject.com/2013/07/08/nignx-load-balancing-reverse-proxy-updated/ – Günter Zöchbauer May 06 '14 at 11:10
  • 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 May 06 '14 at 11:21
  • 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 May 06 '14 at 11:37
  • Sharing data between isolates / Copying a connection is one thing. Somehow I doubt port-forwarding and rewriting it is derived from this pattern. I also remember a discussion regarding remote isolates but long time before I started to get serious with dart, which happens to be now :) – Dr. Dama May 06 '14 at 11:52
  • 1
    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](https://codereview.chromium.org/25511002/). 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 May 08 '14 at 10:55
  • Thanks a lot! With this I should be able to solve my problem. I actually use distinct processes. Since isolates are pretty much a server/client pattern, I think they should get transformable streams. To be honest I haven't yet explored the complete API regarding HttpClient as recieveport alternative. The Port forwarding problem is probably solved if I get it working, since you can route with a distinct process to a destination without having the master process on port 80 blocked. Later on of course you send a signal/message and/or assign the receiver to a favoured/direct connection/port :) – Dr. Dama May 09 '14 at 14:05
  • I would prefere to be able to do that without patch, to always be able to have several processes behind a port etc. – Dr. Dama May 09 '14 at 14:06
  • 1
    Me too. It looks like there is another experimental change which has merged now, that lets you share sockets between isolates. https://codereview.chromium.org/250513002/diff/70001/sdk/lib/io/socket.dart – Greg Lowe May 11 '14 at 22:40
  • you just have the better keywords :) I guess I wouldn't have found that before dart 2.0 .... thanks a lot! – Dr. Dama May 14 '14 at 03:46

2 Answers2

1

Actually Dart HttpServer is very poorly designed. Socket, RawSokcet, SecureSocket etc. In NodeJs you have Tcp Socket which you can forward on any server Http,Https or Websocket server. If you use share ports between http and https server it doesn't pass all https queries to https server. So isolate can run a separate process but no work guarantee

Sartaj
  • 139
  • 5
0

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.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • Thx, I already read all that stuff. I'm not lazy ;) It doesn't solve anything. I thought at least one of the problems I have can be solved. I know complex objects can not be transferred. I am looking for a method to have a request/stream pushed to a server on a server :) // similar like isolate to isolate – Dr. Dama May 06 '14 at 12:11
  • I had the impression that very recently the focus shifted more to Dart on the server as until recently the focus was almost entirely Dart on the client. This may improve things but will still take some time I guess. I didn't assume you are lazy of course, but I think this discussion contains the best information about this topic so far. Hopefully it may at least help others that stumble over your question ;-) – Günter Zöchbauer May 06 '14 at 12:14
  • well, the shared memory problem has been issued from the start. For my taste Dart is pretty good designed. I never really liked the overloaded Java API and debugging style and build process ant/maven etc. Since Dart did a really good job performance wise compared to the Java server(in my test scenario), I thought I should just give it a try. I don't need those spring/hibernate/Jboss stuff anyway. So this is where the journey ended :'-) hope I'll get some ideas though. btw. best resource for examples I found here: https://github.com/dart-lang/bleeding_edge/ – Dr. Dama May 06 '14 at 15:25
  • Do you have a more specific location what you referring to? Is transferrable already implemented in Dart-VM? Performance optimization in Dart-VM wasn't even really started ;-) – Günter Zöchbauer May 06 '14 at 15:28
  • my dear, if I had a satisfying answer, I wasn't here :) I usually really dig deep and do things myself before I ask. But for your curiosity https://github.com/dart-lang/bleeding_edge/tree/968b1529bd26834ba4531fd2d052ffca18867cf0/dart/tests/standalone/io there are a lot of test cases that give insight how to do stuff :) – Dr. Dama May 06 '14 at 16:43
  • I interpreted your comment as if you found something. If not I don't understand why you posted the link. I couldn't find anything that seems related in the unit test. – Günter Zöchbauer May 06 '14 at 16:47
  • not for sure this e.g. has some concept: https://github.com/dart-lang/bleeding_edge/blob/968b1529bd26834ba4531fd2d052ffca18867cf0/dart/tests/standalone/io/http_proxy_test.dart but not distributed or in isolate, so I'm still on hot coals :) – Dr. Dama May 06 '14 at 17:07
  • Seems for outgoing connections. Why don't you just add a question to the thread linked in my answer and ask if something has changed since the discussion. – Günter Zöchbauer May 06 '14 at 17:12
  • the dart guys are also here. stackoverflow is a bit more mature. So I wouldn't bother so much in a duplicate content matter :) just give it some time.... – Dr. Dama May 06 '14 at 17:19
  • 1
    The feature to pass ServerSocket to other isolates just landed (as experimental) https://groups.google.com/a/dartlang.org/forum/#!topic/misc/G9wYnvSG0UQ – Günter Zöchbauer May 21 '14 at 20:06
  • 1
    I know ;) always on track – Dr. Dama May 21 '14 at 23:43
  • Would be great if you could drop a note when you got it working. – Günter Zöchbauer May 22 '14 at 03:53
  • updated my post long time ago :) new SDK also works fine – Dr. Dama May 23 '14 at 02:16