I honestly don't understand why this is called a "web server", and not a "reverse proxy", which is what it appears to be.
I also don't understand what "self-hosting" means for a reverse proxy written in C. It appears to mean "it compiles and runs", which would be a curious use of the word "self-hosting".
The section "Let this sink in for a moment" appears to extoll the following revolutionary notion: when you contact backends through TCP or a messaging library with bindings for many languages, these backends can be written in many languages, and the proxy won't care. To that amazing achievement I would add the following little-known astounding fact: when you visit a web site with your browser, the web server answering the request could be written in any programming language with decent networking libraries, and the browser won't care. The browser "loves all languages equally!". I believe this to be an early forerunner of this amazing language-agnostic technique that mongrel2 will now fully popularize to the programming masses.
Well, this is only the beginning. Right now it proxies, and that was one week or so of work. Next it will really pick up web server features: routing, configuration, serving files, etc.
That's why "Self-Hosting" was in quotes. It's self-hosting in that I can serve the chat demo up and that proves out the design. That was my goal for this week.
Now, yes, your web server can take one HTTP request and hand it to one backend. Applause all around, it is "language agnostic". Oh, well after you write an HTTP server in every language. Oh, and for only one request. Oh, and to only one backend. Oh, and the response can go to only one frontend server. Oh, and except that every web server thinks everything is a "file". Oh, and then there's that nasty config you dare not change. Oh, and when you want to add another 100 backends you gotta change every frontend to be aware of them.
And so on. The revolutionary part is with Mongrel2 I'm trying to break the 1:1 mapping of REQUEST:RESPONSE so that you can have N:N mapping easily, and that backends can be simple 0mq handlers of JSON and in any language. You can have N requests map to arbitrarily any N backends and they can respond to any N frontends asynchronously.
That's how the chat demo works right now. I get a request, and then the backend replies to the front end to deliver messages to all connected browsers. I could even start up 10 backends without changing one thing in the front end. Try that with current web servers without tons of hacks.
Another way to put this, and much more simply, is that right now web servers need to know every little thing about your backend architecture, and they force you to cram it into the concept of "files at URLs". Mongrel2 will not care what your backend is as long as it responds, and it won't constrain to everything being a cohesive file or even HTTP.
Seriously. Zed produces a shocking amount of content and software. On top of all the software he writes, he's got multiple blogs that get updated frequently.
Clearly Zed Shaw has discovered self-replication and is using it to his advantage.
I do "Time Opportunism" rather than "Time Management". It's a subtle difference, but works incredibly well when you're in a creative+technical discipline like coding, writing, or music.
Pretty simple really. Instead of trying to control how I spend your time, I try to take advantage of whatever time I have to do what I'm feeling like doing. A key part of this is reducing the amount of bullshit and setup time necessary to do the things I want, and combining activities.
For example, I try to practice guitar 4 hours a day. I also like watching TV. So, I have a little practice amp in my living room that's always plugged in and has a cable so I can just grab a guitar, and noodle while I watch TV. That alone gives me about 2 hours of practicing mindless stuff.
I'm sure I'm missing something, because Zed is smarter than me. Why is this much better than just running each of those services on different ports? How does having everything behind a single port increase flexibility? It seems like he's serving multiple services over a single port, but I thought the point of ports as a software construct were to advertise different services?
Helps with firewalls. Helps with poorly-documented services. Helps when you don't know what you're going to be running (i.e. your language/platform supports multiple sorts with a config file, and you don't want your web server to have to read that config file).
Also helps when you may be changing what you're doing. You know all that annoyance you currently do with NGinX and Apache and whatever else where you write a very cryptic config file telling it what runs on what ports and in what directories and how to serve it? I would love to do less of that. I would love to not have to change it every time I put up a new little Ruby-on-Rails toy web-app. I would love to be able to just shove a new Rails or PHP or Sinatra or Node.js project into my github repository, have a simple cron job on my server check it out into my "checkouts" directory, and then not have to configure the web server for it.
These things are doable with current servers, of course. They're just a pain and involve writing a fair bit of code to make it happen. If you could subtract the "update your NGinX/Apache/whatever config" step, you'd eliminate a fair bit of the current friction.
This is more important for hobbyists than big sites. A really flexible server will never be quite as fast as a fully dedicated server (cf Mongrel_cluster versus, say, Passenger). But for hobbyists, it could be a godsend.
Newer hobbyists won't even have to learn how to deploy a Comet/FlashSocket/Websocket server from behind a reverse-proxy. I envy that.
In general yes, but as more and more technology gets added to the stack, it becomes increasingly difficult to keep everything running on port 80, which is the only port your users should have to hit on a web request. Take web sockets for instance, I have to run that on an off port because I can't run it through nginx yet.
That's very true. There's only so far a parser can go at keeping the protocols straight. Thankfully most protocols are designed to be really different so it's easy to do this right now. If I ran into a protocol that didn't work in this way then I'd have that on a separate port.
I've dealt with this by getting another IP and pointing a subdomain at it, then I can start all over again with port 80. Your point still stands for this discussion, though.
Port 80. This means you can make web apps that use all available protocols but only need to know about port 80. Gets through firewalls, cuts down on configuration, and it's not too hard to do in the server.
Honest question: I'm not too familiar with firewalls, but do they not check for the validity of the traffic on port 80 to make sure it's actually HTTP?
Yes there are firewalls/proxies which check for validity of HTTP over port 80, though others don’t bother, or just look at the first bit of traffic for each connection.
HTTPS goes over port 443, and I imagine there are some firewalls somewhere or another which block it altogether. Probably not enough of them to worry too much about though.
Some firewalls at least make sure that traffic over port 443 does a proper SSL handshake.... after that the data is encrypted, so they have no way to tell just what’s going through.
So would FlashSocket traffic get blocked by these firewalls if it was trying to sneak in through port 80, then? That would kinda beat the purpose of this effort.
You don't need to be able to decrypt anything to identify an HTTPS flow. An unencrypted SSL/TLS handshake takes place first, before any encrypted data is sent across the wire.
has a very good chance of changing how we architect and deploy web applications
I'd be curious to see a quick HN brainstorm of some cool apps that one might be more likely to think of after thinking along the lines of a mongrel2 deployment.
Node.js should have the potential to eat the same lunch as Mongrel2.
Now that pre-forking is possible, node can do 6-10k http requests / sec per CPU core. That leaves plenty of room for dispatching requests to any backends. And you get full flexibility of scripting everything in JS.
I like the idea of a language agnostic application server, but I'm not sold on this design yet.
Your language still must efficiently implement some protocol to talk to Mongrel2, whether that's HTTP, 0mq, or some custom binary protocol, right?
I'd like a simple, efficient, scalable HTTP server written in C (or C++ I suppose) that I can write multiple language bindings for. Is this feasible? Is there anything like that out there?
Hasn't Apache proved itself to be able to scale to large workloads when configured well? Doesn't it have modules to support many different languages? It's it nice and fast and written in C or C++?
I guess the problem is that Apache does everything, and the price for that is that it isn't very streamlined.
I may be totally off base because I really don't know that much about non-Apache web servers. Please explain how these new generalized web servers like Mongrel2 would provide a significant advantage over existing web servers like Apache.
Yeah, Apache is too heavyweight. I want the server embedded in a language-specific module, not the other way around (an Apache module for the specific language). Something like Mongrel or Unicorn, but written entirely in C, except for language-specific bindings.
I should be able to just execute "server.run(application, port)" or whatever, not have to dive into Apache configuration files. Even with Mongrel2 you need to start multiple processes to get anything working.
Well, it doesn't get much simpler than JSON over 0mq. I think Mongrel2 will actually have to include some turing complete language since there's no way I could anticipate what people will want to modify with it. If there's one thing I know, it's that companies do the craziest stupid crap with their architectures.
As a side note, the current design is definitely POC level, so keep tracking it and if it goes off in a stupid direction let me know.
You could do worse than Lua if you're going that route - it's small, clean, and fast, designed for embedding and you can move smoothly from simple config files to complex scripted behaviour.
I'd like a simple, efficient, scalable HTTP server written in C ...
Check out libebb - http://tinyclouds.org/libebb/. It was created by Ryah Dahl (node.js fame) and is a solid piece of software. We used it in our WebROaR server for ruby web applications.
Sidenote: libebb's Ragel based parser is derived from Mongrel.
How is this different than using Layer 4 routing/load-balancing? If you are already scaling to multiple backends then you're probably likely to have access to more than 1 or 2 public facing IPs if you have to ensure everything inbound is on port 80. Just use sub-domains with different DNS A records. You listen on port 80 and then route to your backend application farm. The load balancers already have various means to monitor health on the backend and you can scale to 100Gbs speed already if you have the budget.
Check out LVS if you want open-source. HAProxy can handle this in a limited fashion. Then if you have gone big already then you can probably afford a Brocade ServerIron, Citrix Netscaler or F5 Big-IP.
That stuff is 1:1. I'm shooting for N:N. For example, that chat demo is taking an individual request from a browser, passing it to a backend, and then that backend can reply to N number of other browsers on the Mongrel2 server. All async, and would even work with HTTP.
That's damn near impossible with all of the tech you listed.
Not quite. I wasn't talking about how the backend communicates. I'm a big fan of zeromq too but there are many types of messaging and it is a must once you start adding more than a few servers. As I see others have mentioned, you're going to have problems with parsing speed at some point. What happens when you need to scale out to handle all the requests on the front end?
How is HA going to be handled? WIll it be easy enough to have an Active/Active of the mongrel server? How do you get away from a single point of failure?
First off, speed is not scalability. I think we need to start talking about "scalability" in terms of the "speed" / "cost". I can get billions of req/sec if I have billions of dollars. What scalability should be is getting as much as you can performance/stability wise with the least amount of money.
With that being said, the plan is that since all backends and frontends can talk using arbitrary types of 0MQ sockets, and 0MQ provides for any kind of network layout, you can make it as "no single point of failure" as you have money to burn on. In my tests so far it's incredibly trivial to have 10 mongrel2 servers submitting requests using a subscribed UUID, and then have 20 backends servicing those requests and replying as needed. Since both the frontends and backends are just using basic messaging with subscribed queues it's fairly easy to get them to talk without any one of them being the point of failure.
Of course, with this comes a configuration penalty which I have to figure out. Either the backends then have to know where all the frontends are (probably easiest) or the frontends have to know about backends. I still haven't got that worked out, but again, it's fairly trivial to create a "registration" service where newly minted backends/frontends announce themselves.
Finally, all of these things have been solved no problem. The easiest answer is I'll just figure out how other people have done it and copy them. It's not like this is new territory or anything. The question itself is kind of stupid because you're saying, for some reason, 0mq precludes my ability to use any existing best practice architecture, when really they're orthogonal and I'm not just using 0mq.
haproxy can kind-of do this as well: "support for inspecting HTTP contents in TCP frontends and switching to HTTP backends (allowing HTTP+SSL to coexist on the same port)."
It should be possible (and not too difficult) to support non-HTTP protocols switching on the same front end port.
I also don't understand what "self-hosting" means for a reverse proxy written in C. It appears to mean "it compiles and runs", which would be a curious use of the word "self-hosting".
The section "Let this sink in for a moment" appears to extoll the following revolutionary notion: when you contact backends through TCP or a messaging library with bindings for many languages, these backends can be written in many languages, and the proxy won't care. To that amazing achievement I would add the following little-known astounding fact: when you visit a web site with your browser, the web server answering the request could be written in any programming language with decent networking libraries, and the browser won't care. The browser "loves all languages equally!". I believe this to be an early forerunner of this amazing language-agnostic technique that mongrel2 will now fully popularize to the programming masses.