Mongrel2是一款面向现代Web应用(Web 2.0 以及以后)而设计的Web浏览器。由干净的C语言写成,(目前)在Linux(及类似的Unix)系统上运行。它支持HTTP, Flash sockets, WebSockets, Long Polling,异步等技术,基本上走在当今Web服务端技术的最前沿。
主页
http://mongrel2.org/
手册
http://mongrel2.org/static/mongrel2-manual.html
Mongrel2的理念
按前面的描述,Mongrel2听起来是个很牛X的Web服务器,其实它真正独特的地方还不是前面的描述,而是它的理念:
- Web服务框架。它提供了很多基础设施,封装了大量Web处理方面的细节,并且以消息的方式为服务器更里层的应用提供多种服务;
- 语言中立。Mongrel2本身是用C语言写成的,但是他力求做到提供的服务语言中立(包括内部协议的设计),理论上可以为任何语言使用(只要这种语言能处理字符串)。实际上,目前已经有17种语言为它写了接口模块,所以可以说到现在为止他已经实现这个目标;
- 多样灵活的控制接口,为管理员的精确控制提供了方便(甚至可以精确到控制一个持续性连接);
关于语言中立,我们来八卦一下。Mongrel2的作者Zed Shaw,之前是Ruby社区的一位大牛,为Ruby社区设计了Mongrel服务器(针对Ruby设计的),这是个广受好评的Web Server,效率差不多是Ruby社区最高的了。后来,不知道咋回事儿(可能是关于一些Ruby技术的发展观点的分歧),Zed Shaw与Ruby界的其它某些人闹翻了。于是他一怒之下退出了Ruby圈子,发誓再也不搞Ruby了。退出之后,兴趣转向了python,写了一本书 Learn Python: The Hard Way。2010年开始,带着对Ruby界的愤怒(也许是很受伤),他开始了Mongrel2的设计。Mongrel2与Mongrel理念完全不一样,Mongrel2的目标就是要语言中立,并且宣称未来的软件开发一定是语言无关的(这种观念我蛮赞同)。就这么一年多的时间,到现在为止(2011年8月10日),发展到了1.7.5版,影响力逐渐大了起来。
Mongrel2与ZeroMQ社区也很有渊源——Mongrel2是ZeroMQ的第一个比较正式的有影响力的项目。ZeroMQ宣称是最牛逼的消息队列,是个新东西,可一直没有什么有影响力的应用。这次与Mongrel2的联姻,简直就是天作之合,我看行!
我关注Mongrel2,还是在其Tir示意框架出来之后,那时Mongrel2的版本为1.4。当时我正在估摸着设计一款Lua的Web框架,用于我们以后的产品中。发现Tir后,立即对这一套系统进行了消化,觉得Mongrel2, ZeroMQ, Redis, Lua的配合绝对有戏,重要的是在Mongrel2的基础上开发Web框架,能省很多事情(Mongrel2把许多以许需要框架来完成的事情包装好了)。于是立马开始了Bamboo项目。
配置文件写法
对象
- Server
- Host
- Dir
- Proxy
内置变量
- settings
- servers
配置选项
先贴上,后面再翻译。
The list of available settings are:
control_port=ipc://run/control
This is where Mongrel2 will listen with 0MQ for control messages. You should use ipc:// for the spec, so that only a local user with file access can get at it.
limits.buffer_size=2 * 1024
Internal IO buffers, used for things like proxying and handling requests. This is a very conservative setting, so if you get HTTP headers greater than this, you’ll want to increase this setting. You’ll also want to shoot whoever is sending you those requests, because the average is 400-600 bytes.
limits.client_read_retries=5
How many times it will attempt to read a complete HTTP header from a client. This prevents attacks where a client trickles an incomplete request at you until you run out of resources.
limits.connection_stack_size=32 * 1024
Size of the stack used for connection coroutines. If you’re trying to cram a ton of connections into very little RAM, see how low this can go.
limits.content_length=20 * 1024
Maximum allowed content length on submitted requests. This is, right now, a hard limit so requests that go over it are rejected. Later versions of Mongrel2 will use an upload mechanism that will allow any size upload.
limits.dir_max_path=256
Max path length you can set for Dir handlers.
limits.dir_send_buffer=16 * 1024
Maximum buffer used for file sending when we need to use one.
limits.fdtask_stack=100 * 1024
Stack frame size for the main IO reactor task. There’s only one, so set it high if you can, but it could possibly go lower.
limits.handler_stack=100 * 1024
The stack frame size for any Handler tasks. You probably want this high, since there’s not many of these, but adjust and see what your system can handle.
limits.handler_targets=128
The maximum number of connection IDs a message from a Handler may target. It’s not smart to set this really high.
limits.header_count=128 * 10
Maximum number of allowed headers from a client connection.
limits.host_name=256
Maximum hostname for Host specifiers and other DNS related settings.
limits.mime_ext_len=128
Maximum length of MIME type extensions.
limits.proxy_read_retries=100
The number of read attempts Mongrel2 should make when reading from a backend proxy. Many backend servers don’t buffer their I/O properly and Mongrel2 will ditch their HTTP response if it doesn’t get a header after this many attempts.
limits.proxy_read_retry_warn=10
This is the threshold where you get a warning that a particular backend is having performance problems, useful for spotting potential errors before they become a problem.
limits.url_path=256
Max URL paths. Does not include query string, just path.
superpoll.hot_dividend=4
Ratio of the total (like 1/4th, 1/8th) that should be in the hot selection. Set this higher if you have lots of idle connections; set it lower if you have more active connections.
superpoll.max_fd=10 * 1024
Maximum possible open files. Do not set this above 64 * 1024, and expect it to take a bit while Mongrel2 sets up constant structures.
upload.temp_store=None
This is not set by default. If you want large requests to reach your handlers, then set this to a directory they can access, and make sure they can handle it. Read about it in the Hacking section under Uploads. The file has to end in XXXXXX chars to work (read man mkstemp).
upload.temp_store_mode=0666
The mode to chmod any files uploaded to upload.temp_store.
zeromq.threads=1
Number of 0MQ IO threads to run. Careful, we’ve experienced thread bugs in 0MQ sometimes with high numbers of these.
limits.tick_timer=10
Mongrel2 keeps an internal clock for efficiency and to run the timeouts. This is how often that clock updates, and defaults to 10 seconds.
limits.min_ping=120
Minimum time since last activity before considering closing a socket. Set to 0 to disable it.
limits.min_write_rate=300
Minimum bytes/second written before considering closing a socket. Set to 0 to disable it.
limits.min_read_rate=300
Minimum bytes/second read before considering closing a socket. Set to 0 to disable it.
limits.kill_limit=2
How many of min_ping, min_write_rate, and min_read_rate have to trigger before a socket is killed.
m2sh管理工具
Mongrel2的源码包里面自带一个工具m2sh,可以用来方便地从命令行管理Mongrel2。
在命令行中敲入 m2sh,回车。会进入下面的提示符:
==============================================
mongrel2> help
Mongrel2 m2sh has these commands available:
load Load a config.
config Alias for load.
shell Starts an interactive shell.
access Prints the access log.
servers Lists the servers in a config database.
hosts Lists the hosts in a server.
routes Lists the routes in a host.
commit Adds a message to the log.
log Prints the commit log.
start Starts a server.
stop Stops a server.
reload Reloads a server.
running Tells you what's running.
control Connects to the control port.
version Prints the Mongrel2 and m2sh version.
help Get help, lists commands.
uuid Prints out a randomly generated UUID.
==============================================
m2sh servers --db conf/config.sqlite
SERVERS:
------
main ipaste 505417b8-1de4-454f-98b6-07eb9225cca1
server2 tfzhw 505417b8-1de4-454f-98b6-07eb9225cca2
==============================================
mongrel2> hosts --db conf/config.sqlite -server name
HOSTS in name:
-----
[ERROR] (errno: No such file or directory) Invalid query, it has no columns, which is a bug.
mongrel2> hosts --db conf/config.sqlite -server main
HOSTS in main:
-----
1 ipaste
==============================================
mongrel2> routes --db conf/config.sqlite -server main -host ipaste
ROUTES in host ipaste, server main
-----
/
/media/
/favicon.ico
==============================================
mongrel2> log --db conf/config.sqlite
LOG MESSAGES:
------
2011-01-12 05:41:34 root legerobot-office conf/mongrel2.conf load command
2011-01-18 06:26:54 root legerobot-office conf/mongrel2.conf load command
2011-01-18 06:29:54 root legerobot-office conf/mongrel2.conf load command
2011-01-18 06:46:34 root legerobot-office conf/mongrel2.conf load command
2011-01-18 06:47:15 root legerobot-office conf/mongrel2.conf load command
2011-01-18 06:51:39 root legerobot-office conf/mongrel2.conf load command
2011-01-27 07:47:56 root legerobot-office conf/mongrel2.conf load command
==============================================
mongrel2> access --db conf/config.sqlite
[WARN] (errno: No such file or directory) No option --log given, using "logs/access.log" as the default.
[1312945845] 192.168.0.101:2633 ipaste "GET /get/ HTTP/1.1" 200 0
[1312945874] 192.168.0.101:2634 ipaste "GET / HTTP/1.1" 200 0
[1312945874] 192.168.0.101:2634 ipaste "GET /media/js/jquery.min.js HTTP/1.1" 304 0
[1312945874] 192.168.0.101:2635 ipaste "GET /media/css/fileuploader.css HTTP/1.1" 304 0
[1312945874] 192.168.0.101:2636 ipaste "GET /media/js/fileuploader.js HTTP/1.1" 304 0
[1312945874] 192.168.0.101:2637 ipaste "GET /get/ HTTP/1.1" 200 0
[1312945875] 192.168.0.101:2639 ipaste "GET / HTTP/1.1" 200 0
[1312945875] 192.168.0.101:2639 ipaste "GET /media/js/jquery.min.js HTTP/1.1" 304 0
[1312945875] 192.168.0.101:2640 ipaste "GET /media/css/fileuploader.css HTTP/1.1" 304 0
[1312945875] 192.168.0.101:2641 ipaste "GET /media/js/fileuploader.js HTTP/1.1" 304 0
[1312945875] 192.168.0.101:2642 ipaste "GET /get/ HTTP/1.1" 200 0
[1312945879] 192.168.0.101:2644 ipaste "GET /get/ HTTP/1.1" 200 0
==============================================
mongrel2> stop --db conf/config.sqlite -name main
mongrel2> servers --db conf/config.sqlite
SERVERS:
------
main ipaste 505417b8-1de4-454f-98b6-07eb9225cca1
server2 tfzhw 505417b8-1de4-454f-98b6-07eb9225cca2
mongrel2> running --db conf/config.sqlite -name main
mongrel2 at PID 2854 running.
mongrel2> running --db conf/config.sqlite -name main
mongrel2 at PID 3132 running.
mongrel2> running --db conf/config.sqlite -name server2
mongrel2 at PID 3191 running.
mongrel2> running --db conf/config.sqlite -name main
[ERROR] (errno: No such file or directory) Couldn't read the PID from .//run/mongrel2.pid
mongrel2 is not running because pid_file isn't there.
==============================================
mongrel2> start --db conf/config.sqlite -name main
[INFO] (src/mime.c:49) MAX limits.mime_ext_len=128
[INFO] (src/host.c:62) MAX limits.url_path=256, limits.host_name=256
[INFO] (src/handler.c:338) MAX limits.handler_stack=102400
[INFO] (src/config/config.c:84) Loaded handler 1:tcp://127.0.0.1:9999:e884a439-31be-4f74-8050-a93565795b25:tcp://127.0.0.1:9998:
[INFO] (src/config/config.c:226) Loaded route 1:/:handler for host 1:ipaste
[INFO] (src/dir.c:175) MAX limits.dir_send_buffer=16384, limits.dir_max_path=256
[INFO] (src/config/config.c:135) Loaded directory 1:sites/ipaste/:index.html
[INFO] (src/config/config.c:226) Loaded route 2:/media/:dir for host 1:ipaste
[INFO] (src/config/config.c:135) Loaded directory 1:sites/ipaste/:index.html
[INFO] (src/config/config.c:226) Loaded route 3:/favicon.ico:dir for host 1:ipaste
[INFO] (src/config/config.c:274) Loaded 1 hosts for server 1:505417b8-1de4-454f-98b6-07eb9225cca1
[INFO] (src/server.c:416) LOADING Handler tcp://127.0.0.1:9999
[INFO] (src/superpoll.c:285) MAX open file descriptors is 10240 now.
[ERROR] (src/unixy.c:99: errno: No such file or directory) Failed to open PID file .//run/mongrel2.pid for reading.
[INFO] (src/unixy.c:138) No previous Mongrel2 running, continuing on.
[INFO] (src/mongrel2.c:200) All loaded up, time to turn into a server.
mongrel2> start --db conf/config.sqlite -name server2
[INFO] (src/mime.c:49) MAX limits.mime_ext_len=128
[INFO] (src/host.c:62) MAX limits.url_path=256, limits.host_name=256
[INFO] (src/handler.c:338) MAX limits.handler_stack=102400
[INFO] (src/config/config.c:84) Loaded handler 2:tcp://127.0.0.1:9997:e884a439-31be-4f74-8050-a93565795b24:tcp://127.0.0.1:9996:
[INFO] (src/config/config.c:226) Loaded route 4:/:handler for host 2:tfzhw
[INFO] (src/dir.c:175) MAX limits.dir_send_buffer=16384, limits.dir_max_path=256
[INFO] (src/config/config.c:135) Loaded directory 2:sites/tfzhw/:index.html
[INFO] (src/config/config.c:226) Loaded route 5:/media/:dir for host 2:tfzhw
[INFO] (src/config/config.c:135) Loaded directory 2:sites/tfzhw/:index.html
[INFO] (src/config/config.c:226) Loaded route 6:/favicon.ico:dir for host 2:tfzhw
[INFO] (src/config/config.c:274) Loaded 1 hosts for server 2:505417b8-1de4-454f-98b6-07eb9225cca2
[INFO] (src/server.c:416) LOADING Handler tcp://127.0.0.1:9997
[INFO] (src/superpoll.c:285) MAX open file descriptors is 10240 now.
[ERROR] (src/unixy.c:99: errno: No such file or directory) Failed to open PID file .//run/mongrel2_server2.pid for reading.
[INFO] (src/unixy.c:138) No previous Mongrel2 running, continuing on.
[INFO] (src/mongrel2.c:200) All loaded up, time to turn into a server.
==============================================
运行期控制
在m2sh提示符下,执行下面语句,会进行远程控制提示符
mongrel2> control --db conf/config.sqlite -name server2
[INFO] Connecting to control port ipc://.//run/control
==============================================
m2 [server2]> help
name help
stop stop the server (SIGINT)
reload reload the server
help this command
control_stop stop control port
kill kill a connection
status status, what=['net'|'tasks']
terminate terminate the server (SIGTERM)
time the server's time
uuid the server's uuid
info information about this server
==============================================
m2 [server2]> status what=net
id fd type last_ping last_read last_write bytes_read bytes_written
m2 [server2]> status what=tasks
id system name state status
1 false SERVER read fd idle
2 false Handler_task read handler idle
3 false control read handler running
4 false ticker idle
5 true fdtask yield ready
==============================================
m2 [server2]> time
time: 1312946823
==============================================
m2 [server2]> uuid
uuid: 505417b8-1de4-454f-98b6-07eb9225cca2
==============================================
m2 [server2]> info
port: 6768
bind_addr: 0.0.0.0
uuid: 505417b8-1de4-454f-98b6-07eb9225cca2
chroot: ./
access_log: /logs/access_server2.log
error_log: /logs/error_server2.log
pid_file: /run/mongrel2_server2.pid
default_hostname: tfzhw
==============================================
m2 [main]> status what=net
id fd type last_ping last_read last_write bytes_read bytes_written
16 36 1 71 71 71 896 176
9 37 1 71 71 71 2052 5019
17 39 1 60 71 71 1358 117
14 41 1 71 71 71 2111 5019
m2 [main]> kill id=16
status: OK
m2 [main]> kill id=9
status: OK
m2 [main]> kill id=17
status: OK
m2 [main]> kill id=14
status: OK
m2 [main]> status what=net
id fd type last_ping last_read last_write bytes_read bytes_written
18 30 1 31 31 0 448 0
19 31 1 11 11 0 479 0
20 36 1 11 11 0 679 0
21 37 1 11 11 0 487 0
==============================================
注:使用类似 m2sh start --db conf/config.sqlite -name main 之类的命令也是可以的。