RejectedSoftware Forums

Sign up

Virtual hosts and load balancing?

does vibe.d support load balancing and or virtual hosts? tried vibedist but no luck! Vibe.D seems like a pretty good attempt at a web server but seems to have lost support from the dev ;/

Re: Virtual hosts and load balancing?

Am 18.09.2016 um 06:43 schrieb Uiy Uiy:

does vibe.d support load balancing and or virtual hosts? tried vibedist but no luck! Vibe.D seems like a pretty good attempt at a web server but seems to have lost support from the dev ;/

Virtual hosts are supported by setting the HTTPServerSettings.hostName
field accordingly. It is possible to call listenHTTP multiple times
with the same IP/port, but with different host names.

There is also support for a simple form of multi-thread based load
balancing by setting HTTPServerOption.distribute. However, it
circumvents D's shared qualifier, so that the user is fully
responsible for ensuring thread safety. For this reason, I'd generally
not recommend this, but instead use multi-process load balancing on a
single machine (letting multiple processes listen on the same port).

For multi-machine load-balancing, vibedist was planned, but it isn't
there yet. However, any off-the-shelf load-balancing solution should
work with vibe.d just like with other web servers - the main difference
is that manual configuration is required.

BTW, I'm currently still busy with other things, but development will be
back to full speed shortly! Considerable resources also went into
diet-ng and vibe-core (which is a revamped version of the
vibe.core module and will be the basis for all further developments),
which slowed down the pace for the main repository somewhat.

Re: Virtual hosts and load balancing?

On Mon, 19 Sep 2016 11:16:11 +0200, Sönke Ludwig wrote:

Am 18.09.2016 um 06:43 schrieb Uiy Uiy:

does vibe.d support load balancing and or virtual hosts? tried vibedist but no luck! Vibe.D seems like a pretty good attempt at a web server but seems to have lost support from the dev ;/

Virtual hosts are supported by setting the HTTPServerSettings.hostName
field accordingly. It is possible to call listenHTTP multiple times
with the same IP/port, but with different host names.

There is also support for a simple form of multi-thread based load
balancing by setting HTTPServerOption.distribute. However, it
circumvents D's shared qualifier, so that the user is fully
responsible for ensuring thread safety. For this reason, I'd generally
not recommend this, but instead use multi-process load balancing on a
single machine (letting multiple processes listen on the same port).

For multi-machine load-balancing, vibedist was planned, but it isn't
there yet. However, any off-the-shelf load-balancing solution should
work with vibe.d just like with other web servers - the main difference
is that manual configuration is required.

BTW, I'm currently still busy with other things, but development will be
back to full speed shortly! Considerable resources also went into
[diet-ng][1] and [vibe-core][2] (which is a revamped version of the
vibe.core module and will be the basis for all further developments),
which slowed down the pace for the main repository somewhat.

[1]: https://github.com/rejectedsoftware/diet-ng
[2]: https://github.com/vibe-d/vibe-core

Cool. Thanks.

I am having some trouble with the virtual hosts but I think I just have to play around with it.

What I really would like to do is be able to create n independent websites(each one is restricted to it's own "space") and serve them off the same ip but also allow for common functionality to be served between them, such as common templates, etc.

e.g.,
<code>
public
source
views
data
images
css
Site1.com
public
source
views
data
images
css
Site2.com
public
source
views
data
images
css
...
</code>

Then when Site1.com is accessed, all the files are served from it's subdirectory. It would be nice if some common templates, icons, etc can be stored in the root to be used by all the sites but otherwise secure(no way for someone to access site2's files from site1.

I see no way to set a path for each server or really accomplish this effectively with one vibe.d process. Any ideas?

I got this error from your site:

500 - Internal Server Error

Internal Server Error

Internal error information:
object.Exception@../../../root/.dub/packages/vibe-d-0.7.29/vibe-d/source/vibe/utils/dictionarylist.d(167): Accessing non-existent key 'group'.

/usr/include/dmd/phobos/std/exception.d:405 pure @safe void std.exception.bailOut!(Exception).bailOut(immutable(char)[], ulong, const(char[])) [0x92e9df]
/usr/include/dmd/phobos/std/exception.d:363 pure @safe bool std.exception.enforce!(Exception, bool).enforce(bool, lazy const(char)[], immutable(char)[], ulong) [0x93200a]
../../../root/.dub/packages/vibe-d-0.7.29/vibe-d/source/vibe/utils/dictionarylist.d:167 vibe.utils.dictionarylist.DictionaryList!(immutable(char)[], true, 16uL, false).DictionaryList.opIndexinout(pure @safe inout(immutable(char)[]) function(immutable(char)[])) [0xb675b7]
source/vibenews/web.d:195 void vibenews.web.WebInterface.getPostArticle(vibe.http.server.HTTPServerRequest, vibe.http.server.HTTPServerResponse, immutable(char)[]) [0x9f4530]
../../../root/.dub/packages/vibe-d-0.7.29/vibe-d/source/vibe/web/web.d:723 void vibe.web.web.handleRequest!("getPostArticle", void vibenews.web.WebInterface.getPostArticle(vibe.http.server.HTTPServerRequest, vibe.http.server.HTTPServerResponse, immutable(char)[]), vibenews.web.WebInterface).handleRequest(vibe.http.server.HTTPServerRequest, vibe.http.server.HTTPServerResponse, vibenews.web.WebInterface, vibe.web.web.WebInterfaceSettings) [0x9df817]
../../../root/.dub/packages/vibe-d-0.7.29/vibe-d/source/vibe/web/web.d:181 void vibe.web.web.T20registerWebInterfaceHTC8vibenews3web12WebInterfaceVE4vibe3web6common11MethodStylei5Z.registerWebInterface(vibe.http.router.URLRouter, vibenews.web.WebInterface, vibe.web.web.WebInterfaceSettings).lambda12!(vibe.http.server.HTTPServerRequest, vibe.http.server.HTTPServerResponse).lambda12(vibe.http.server.HTTPServerRequest, vibe.http.server.HTTPServerResponse) [0x9d95b4]
../../../root/.dub/packages/vibe-d-0.7.29/vibe-d/source/vibe/http/router.d:268 _D4vibe4http6router9URLRouter13handleRequestMFC4vibe4http6server17HTTPServerRequestC4vibe4http6server18HTTPServerResponseZ21
T9lambda4TmTAAyaZ9lambda4MFmMAAyaZb [0xacf50b]
../../../root/.dub/packages/vibe-d-0.7.29/vibe-d/source/vibe/http/router.d:595 const(bool function(immutable(char)[], scope bool delegate(ulong, scope immutable(char)))) vibe.http.router.MatchTree!(vibe.http.router.Route).MatchTree.doMatch [0xad02c4]
../../../root/.dub/packages/vibe-d-0.7.29/vibe-d/source/vibe/http/router.d:528 bool vibe.http.router.MatchTree!(vibe.http.router.Route).MatchTree.match(immutable(char)[], scope bool delegate(ulong, scope immutable(char))) [0xacfb5f]
../../../root/.dub/packages/vibe-d-0.7.29/vibe-d/source/vibe/http/router.d:261 void vibe.http.router.URLRouter.handleRequest(vibe.http.server.HTTPServerRequest, vibe.http.server.HTTPServerResponse) [0xacf1c5]
../../../root/.dub/packages/vibe-d-0.7.29/vibe-d/source/vibe/http/server.d:1796 bool vibe.http.server.handleRequest(vibe.core.stream.Stream, vibe.core.net.TCPConnection, vibe.http.server.HTTPListenInfo, ref vibe.http.server.HTTPServerSettings, ref bool) [0xaf907e]
../../../root/.dub/packages/vibe-d-0.7.29/vibe-d/source/vibe/http/server.d:1552 void vibe.http.server.handleHTTPConnection(vibe.core.net.TCPConnection, vibe.http.server.HTTPListenInfo) [0xaf76be]
../../../root/.dub/packages/vibe-d-0.7.29/vibe-d/source/vibe/http/server.d:1433 void vibe.http.server.listenHTTPPlain(vibe.http.server.HTTPServerSettings).doListen(vibe.http.server.HTTPListenInfo, bool, bool)._lambda4(vibe.core.net.TCPConnection) [0xaf7084]
../../../root/.dub/packages/vibe-d-0.7.29/vibe-d/source/vibe/core/drivers/libevent2
tcp.d:610 void vibe.core.drivers.libevent2tcp.ClientTask.execute() [0xb9d6c5]
../../../root/.dub/packages/vibe-d-0.7.29/vibe-d/source/vibe/core/core.d:488 void vibe.core.core.makeTaskFuncInfo!(void delegate()).makeTaskFuncInfo(ref void delegate()).callDelegate(vibe.core.core.TaskFuncInfo*) [0x9be0d1]
../../../root/.dub/packages/vibe-d-0.7.29/vibe-d/source/vibe/core/core.d:1119 void vibe.core.core.CoreTask.run() [0xb2ac11]
??:? void core.thread.Fiber.run() [0xc25f99]
??:? fiber
entryPoint [0xc25d1b]
??:? [0xffffffff]

when trying to log in.

Re: Virtual hosts and load balancing?

On Thu, 22 Sep 2016 17:41:26 GMT, Uiy Uiy wrote:

I am having some trouble with the virtual hosts but I think I just have to play around with it.

What I really would like to do is be able to create n independent websites(each one is restricted to it's own "space") and serve them off the same ip but also allow for common functionality to be served between them, such as common templates, etc.

e.g.,

public
source
views
data
images
css
Site1.com
   public
   source
   views
   data
   images
   css
Site2.com
   public
   source
   views
   data
   images
   css
...

Then when Site1.com is accessed, all the files are served from it's subdirectory. It would be nice if some common templates, icons, etc can be stored in the root to be used by all the sites but otherwise secure(no way for someone to access site2's files from site1.

I see no way to set a path for each server or really accomplish this effectively with one vibe.d process. Any ideas?

You can call serveStaticFiles multiple times, as needed:

{ // setup host 1
  auto settings = new HTTPServerSettings;
  settings.hostName = "foo.example.org";

  auto router = new URLRouter;
  router.serveStaticFiles("/public");
  router.serveStaticFiles("/site1/public");

  listenHTTP(settings, router);
}

{ // setup host 2
  auto settings = new HTTPServerSettings;
  settings.hostName = "bar.example.org";

  auto router = new URLRouter;
  router.serveStaticFiles("/public");
  router.serveStaticFiles("/site2/public");

  listenHTTP(settings, router);
}

The two virtual hosts are logically completely distinct, except that both serve the "public" folder of the root directory.

I got this error from your site:

500 - Internal Server Error
(...)

This appears to be issue #25. It has been lying around for quite a wile now, but I'll have to prioritize this some day, as someone regularly hits this.

Re: Virtual hosts and load balancing?

On Sun, 25 Sep 2016 11:39:34 GMT, Sönke Ludwig wrote:

On Thu, 22 Sep 2016 17:41:26 GMT, Uiy Uiy wrote:

I am having some trouble with the virtual hosts but I think I just have to play around with it.

What I really would like to do is be able to create n independent websites(each one is restricted to it's own "space") and serve them off the same ip but also allow for common functionality to be served between them, such as common templates, etc.

e.g.,

public
source
views
data
images
css
Site1.com
   public
   source
   views
   data
   images
   css
Site2.com
   public
   source
   views
   data
   images
   css
...

Then when Site1.com is accessed, all the files are served from it's subdirectory. It would be nice if some common templates, icons, etc can be stored in the root to be used by all the sites but otherwise secure(no way for someone to access site2's files from site1.

I see no way to set a path for each server or really accomplish this effectively with one vibe.d process. Any ideas?

You can call serveStaticFiles multiple times, as needed:

{ // setup host 1
  auto settings = new HTTPServerSettings;
  settings.hostName = "foo.example.org";

  auto router = new URLRouter;
  router.serveStaticFiles("/public");
  router.serveStaticFiles("/site1/public");

  listenHTTP(settings, router);
}

{ // setup host 2
  auto settings = new HTTPServerSettings;
  settings.hostName = "bar.example.org";

  auto router = new URLRouter;
  router.serveStaticFiles("/public");
  router.serveStaticFiles("/site2/public");

  listenHTTP(settings, router);
}

The two virtual hosts are logically completely distinct, except that both serve the "public" folder of the root directory.

But how do we keep the views isolated and such. It doesn't seem to keep the two sites distinct. You are simply adding two different directories to serve from(BTW, what is the precedence order?).

If I have 10 sites, say, and ones view directory, then things can get very hairy quickly. I have to keep everything named properly.

It would be nice to have a

settings.rootDir which sets the root dir for the site.

That is, unless setting hostName sets the rootDir?

Or is there something I'm missing?

My goal is to really have n distinct sites with each it's own distinct root directory. The common folder is not as important... I can just copy files between them if necessary. I was just trying to avoid duplicating a bunch of files between the sites but then I forgot about views and dt files.

Re: Virtual hosts and load balancing?

On Tue, 27 Sep 2016 01:24:03 GMT, Uiy Uiy wrote:

On Sun, 25 Sep 2016 11:39:34 GMT, Sönke Ludwig wrote:

(...)
The two virtual hosts are logically completely distinct, except that both serve the "public" folder of the root directory.

But how do we keep the views isolated and such. It doesn't seem to keep the two sites distinct. You are simply adding two different directories to serve from(BTW, what is the precedence order?).

Precedence is in the order as registered in the router (i.e. the root public folder would be searched first in the example).

If I have 10 sites, say, and ones view directory, then things can get very hairy quickly. I have to keep everything named properly.

Since "views" are a compile-time feature, and due to the way string imports work, they cannot be truly distinct, unless you build each site as a separate executable. In general, I'd always recommend to do that anyway to increase robustness against crashes and hangs.

You just need to have a single front-end web server in that case, which has all the virtual hosts registered and forwards the requests to the appropriate process.

It would be nice to have a

settings.rootDir which sets the root dir for the site.

This can't work unfortunately, because Diet templates are already processed at compile time.

That is, unless setting hostName sets the rootDir?

No, those are distinct.

Or is there something I'm missing?

My goal is to really have n distinct sites with each it's own distinct root directory. The common folder is not as important... I can just copy files between them if necessary. I was just trying to avoid duplicating a bunch of files between the sites but then I forgot about views and dt files.

Then I'd really recommend going with a reverse proxy and separate processes. A rough sketch would be:

proxy (of course you could also instead use something like Nginx here, which is not a bad idea in general):

shared static this()
{
  auto hosts = [
    tuple("foo.example.org", 8081),
    tuple("bar.example.org", 8082)
  ];

  foreach (host; hosts) {
    auto settings = new HTTPServerSettings;
    settings.host = host[0];

    auto psettings = new HTTPReverseProxySettings;
    psettings.destinationHost = "127.0.0.1";
    psettings.destinationPort = host[1];

    listenHTTPReverseProxy(settings, psettings);
  }
}

first site:

shared static this()
{
  auto router = new URLRouter;
  // ...

  auto settings = new HTTPServerSettings;
  settings.bindAddresses = ["127.0.0.1"];
  settings.port = 8081;

  listenHTTP(settings, router);
}

Each of these would be in a separate DUB package. You could still have all sites depend on a separate package that contains common views and public resources. The "copyFiles" directive of the package recipe can be used to copy the runtime resources for each site automatically (example).