代理接口¶
注意:此模块仅在(现已停止开发的)1.5.x 分支中可用。
模块:mod_proxy_core (已废弃)
描述¶
FastCGI、SCGI、HTTP 等做着同样简单的工作:它们将 HTTP 请求转发到后端并向服务器发送响应。它们只是使用不同的协议来编码数据。
- FastCGI,由 Open Market 开发并记录在 http://www.fastcgi.com/ 上,是一个围绕 HTTP 请求的二进制容器,可减少解析开销。除了正常的响应生成外,它还支持授权查询
- SCGI 类似于 HTTP,只是为 HTTP 头部添加了一个长度头部。http://www.mems-exchange.org/software/scgi/ 中写道:“SCGI 协议是通用网关接口 (CGI) 协议的替代品。它是一个应用程序与 HTTP 服务器接口的标准。它类似于 FastCGI,但设计起来更易于实现。”
- 对于 HTTP,我们支持后端侧的 HTTP/1.0 和 HTTP/1.1
- AJP13 是 Apache JServ 协议版本 1.3(参见 https://tomcat.net.cn/tomcat-3.3-doc/AJPv13.html),由 Apache 世界中的 mod_jk 和 mod_proxy_ajp (Apache 2.2+) 实现。
本小指南将帮助您选择适合您需求的协议。
| 协议 | 偏好 | 二进制协议 | 长连接 |
|---|---|---|---|
| HTTP | mongrel | 否 | 是 |
| SCGI | WSGI (Python) | 不完全是 | 否 |
| FastCGI | PHP, Rails | 是 | 是 |
| AJP13 | Tomcat | 是 | 是 |
安装¶
mod-proxy-core 需要 lighttpd 1.5,旨在取代 mod_fastcgi。
如果您想使用 mod-proxy-core,则必须先加载它。每个协议也是一个模块,也必须在加载
核心模块之后加载。
server.modules = (
...,
"mod_proxy_core",
"mod_proxy_backend_http",
"mod_proxy_backend_fastcgi",
... )
负载均衡¶
mod-proxy-core 支持 4 种不同的负载均衡器
- 静态负载均衡器 (static) 不进行负载均衡,仅在第一个列出的后端不可用时进行故障转移。有关示例(基本上是本地和远程后端),请参见 http://permalink.gmane.org/gmane.comp.web.lighttpd/4686。
- 在轮询 (round-robin) 中,请求平均分配给所有后端。在我们的实现中,我们不强制执行真正的轮询,而是随机选择一个后端。
- 最短队列优先 (sqf) 类似于轮询,并优先选择等待队列最短的后端。
- 缓存数组路由协议 (carp) 有点不同,因为它能提高后端局部性。它对 URL 进行哈希处理,并始终将相同的 URL 发送到相同的后端。http://icp.ircache.net/carp.txt 解释了完整的规范。
当前未实现
故障转移处理¶
如果对后端的请求失败(连接被拒绝,连接超时等),请求将被发送到另一个后端。如果没有可用的后端,则返回“504 网关超时”。(参见 http://forum.lighttpd.net/topic/4993)
超时¶
如果您的传入请求超出了可用后端的数量,则该请求将被放入积压队列中。一旦后端再次可用,队列中的第一个连接将被唤醒并处理。
如果请求在队列中等待超过 10 秒,则该请求将被终止并返回“504 网关超时”。
选项¶
proxy-core.balancer
可以是 'round-robin'、'sqf'、'carp' 或 'static' 之一。
参见
proxy-core.protocol
可以是 'http'、'fastcgi'、'ajp13' 或 'scgi' 之一。请确保加载后端模块(参见 mod_proxy_backend_<name>)
proxy-core.backends
告诉模块将代理请求发送到哪里。
它是一个主机名/IP 地址/Unix 域套接字列表
例如:
proxy-core.backends = (
"10.0.0.1:80", ## IPv4 address
"unix:/tmp/php.socket", ## unix domain socket
"[::1]:80", ## IPv6 addresss
"google.com:80" ## hostname, resolved at startup
)
proxy-core.max-pool-size
单个后端连接池的最大大小。
- 对于 mongrel,这应设置为 1
- 对于 PHP,这应与 PHP_FCGI_CHILDREN 设置匹配
- 对于 WSGI,这应与后端线程数匹配
- 对于 HTTP 代理,您可以自行决定允许向同一后端发送多少个并行请求
默认值:1
proxy-core.allow-x-sendfile
启用使用“X-Sendfile/X-LIGHTTPD-Sendfile/X-LIGHTTPD-send-tempfile”头部。
注意:如果您正在运行启用了 zlib 压缩的 PHP,请使用 ini_set("zlib.output_compression", "off") 将其关闭,否则您尝试发送的文件将只有 1 字节且无法工作。
参见
- https://blog.lighttpd.ac.cn/articles/2006/07/22/mod_proxy_core-got-x-sendfile-support
- https://blog.lighttpd.ac.cn/articles/2006/11/29/faster-fastcgi
proxy-core.allow-x-rewrite
启用使用 X-Rewrite
使您能够通过使用响应头部“X-Rewrite-URI”和“X-Rewrite-Host”将请求从一个后端重定向到另一个后端,而客户端不会察觉。
假设您想要某种负载均衡,但其背后的逻辑比轮询或加权随机化更复杂。
客户端请求 http://host.tld/,该请求由您的 fastcgi 后端处理,后端会进行一些计算来决定应使用哪个后端。
现在,您的后端只需发送 200 OK,并附带例如“X-Rewrite-URI: /foo”和“X-Rewrite-Host: internal3.host.tld”。
这样做会使 mod_proxy_core 再次处理来自客户端的当前请求,但 URI 为“/foo”而不是“/”,主机为“internal3.host.tld”而不是“host.tld”。
参见
proxy-core.rewrite-request
重写请求头或请求 URI。
目前支持以下键:
- “_uri”:请求的完整路径 + 查询字符串,例如“/some/file/in/some/dir.fcgi?request&uri=1”
- “_docroot”:文档根目录路径,如果请求发送到具有不同文件系统布局的另一台服务器,则此选项很有用
- “_pathinfo”:CGI 环境变量 PATH_INFO(例如,对于到 /myfcgiapp/foobar 的请求,为 /foobar)
- “_scriptname”:CGI 环境变量 SCRIPT_NAME(例如,对于到 /myfcgiapp 的请求,为 /myfcgiapp)
注意,参见 #1600。
示例
trac 需要一个猜测的 PATH_INFO
$HTTP["url"] =~ "^/trac/" {
proxy-core.backends = ( "127.0.0.1:9090" )
proxy-core.protocol = "fastcgi"
proxy-core.rewrite-request = (
"_pathinfo" => ( "^/trac(/.*)" => "$1" ),
"_scriptname" => ( "^(/trac/)" => "$1" )
)
}
我们从请求 URI(与 $HTTP["url"] 中的相同)构建 PATH_INFO,并从中提取 trac-base 之后的部分作为 PATH_INFO。SCRIPT_NAME 相应地缩短。
trac will only see:
SCRIPT_NAME=/trac
PATH_INFO=/wiki
For proxies can make a relative part of your URL:
$HTTP["url"] =~ "^/blog" {
proxy-co...
proxy-core.rewrite-request = (
"_uri" => ( "^/blog/?(.*)" => "/$1" ),
"Host" => ( ".*" => "blog.example.org" ),
)
}
All requests to http://example.org/blog will be fetched from http://blog.example.org/ transparently for the user.
proxy-core.rewrite-response
重写响应头。
proxy-core.max-keep-alive-requests
关闭长连接之前的请求数。
默认值:0
proxy-core.split-hostnames
如果后端使用具有多个 IP 地址的 DNS 主机名,则将每个地址拆分为一个单独的后端。
禁用此选项可将 IP 地址放入该后端的地址池中。
默认值:已启用
示例¶
在 8 个 Squid 前使用 lighttpd + mod_proxy_core,由它们为您处理动态内容的缓存。对主机 www.example.org 的所有请求都应转发到代理。所有代理都侦听端口 80 以处理请求。
server.modules += ( "mod_proxy_backend_http" )
$HTTP["host"] == "www.example.org" {
proxy-core.protocol = "http"
proxy-core.balancer = "carp"
proxy-core.backends = ( "10.0.0.10",
"10.0.0.11",
"10.0.0.12",
"10.0.0.13",
"10.0.0.14",
"10.0.0.15",
"10.0.0.16",
"10.0.0.17" )
}
如果其中一个主机宕机,则该服务器的所有请求将平均转移到其他服务器。如果您想了解更多关于此处使用的算法,请在 Google 上搜索“Microsoft CARP”。
对于使用 Unix 域套接字“/tmp/php-fastcgi.sock”的 PHP
server.modules += ( "mod_proxy_backend_fastcgi" )
$PHYSICAL["existing-path"] =~ "\.php$" {
proxy-core.balancer = "round-robin"
proxy-core.protocol = "fastcgi"
proxy-core.allow-x-sendfile = "enable"
proxy-core.backends = ( "unix:/tmp/php-fastcgi.sock" )
proxy-core.max-pool-size = 16
proxy-core.rewrite-request = (
"_pathinfo" => ( "\.php(/.*)" => "$1" )
)
}
对于 SCGI
server.modules += ( "mod_proxy_backend_scgi" )
$PHYSICAL["existing-path"] =~ "\.scgi$" {
proxy-core.balancer = "round-robin"
proxy-core.protocol = "scgi"
proxy-core.allow-x-sendfile = "enable"
proxy-core.backends = ( "127.0.0.1:9090" )
proxy-core.max-pool-size = 16
}
对于带有主机和文件扩展名条件的 HTTP 代理
server.modules += ( "mod_proxy_backend_http" )
$HTTP["host"] == "www.example.org" {
proxy-core.protocol = "http"
proxy-core.balancer = "carp"
$HTTP["url"] =~ "\.php$" {
proxy-core.backends = ( "10.0.0.10:80" )
}
else $HTTP["url"] =~ "\.scgi$" {
proxy-core.backends = ( "10.0.0.11:80" )
}
}
反向代理
server.modules += ( "mod_proxy_backend_http" )
$HTTP["url"] =~ "^/proxyme(/|$)" {
proxy-core.balancer = "round-robin"
proxy-core.protocol = "http"
proxy-core.backends = ( "en.wikipedia.org" )
proxy-core.rewrite-response = (
"Location" => ( "^http://en.wikipedia.org/(.*)" => "http://127.0.0.1:1025/proxyme/$1" ),
)
proxy-core.rewrite-request = (
"_uri" => ( "^/proxyme/?(.*)" => "/$1" ),
"Host" => ( ".*" => "en.wikipedia.org" ),
)
}
对于使用 AJP13 协议代理到 Tomcat
server.modules += ( "mod_proxy_backend_ajp13" )
$HTTP["url"] =~ "^/tomcat/" {
proxy-core.balancer = "round-robin"
proxy-core.protocol = "ajp13"
proxy-core.backends = ( "localhost:8009" )
proxy-core.max-pool-size = 16
}
allow-x-rewrite 配置示例
server.modules += ( "mod_proxy_backend_fastcgi" )
$PHYSICAL["existing-path"] =~ "\.php$" {
proxy-core.balancer = "round-robin"
proxy-core.protocol = "fastcgi"
proxy-core.allow-x-rewrite = "enable"
proxy-core.backends = ( "unix:/tmp/php-fastcgi.sock" )
proxy-core.max-pool-size = 16
}
server.modules += ( "mod_proxy_backend_http" )
$HTTP["host"] == "backend-cluster" {
proxy-core.balancer = "round-robin"
proxy-core.protocol = "http"
proxy-core.max-pool-size = 4
}
X-Rewrite 脚本示例
<?php
header("X-Rewrite-URI: /");
header("X-Rewrite-Host: backend-cluster");
header("X-Rewrite-Backend: " . $_REQUEST['backend']); // dynamicaly add/select a backend to the "backend-cluster" proxy-core
?>
将 Rails 应用程序的请求代理到本地托管的 mongrel 实例组。
$HTTP["host"] == "rails.dom.ain" { # or, e.g., =~ "^([^.])+\.rails\.tld$"
proxy-core.protocol = "http"
proxy-core.balancer = "round-robin"
proxy-core.allow-x-sendfile = "enable" # avoid send_file memory ballooning by using the x_send_file plugin
proxy-core.backends = (
"127.0.0.1:8000",
"127.0.0.1:8001",
"127.0.0.1:8002",
"127.0.0.1:8003"
)
}
Django 1.x 结合 lighttpd 1.5.x 示例
$HTTP["host"] == "yourdomain.net" {
server.document-root = "/var/www/yourdomain.net/"
proxy-core.backends = ( "unix:/var/django/yourdomain/fcgi.sock" )
proxy-core.balancer = "round-robin"
proxy-core.max-pool-size = 5
proxy-core.protocol = "fastcgi"
proxy-core.allow-x-sendfile = "enable"
proxy-core.rewrite-request = (
"_pathinfo" => ( "^(/.*)" => "$1" ),
"_scriptname" => ( "^.*" => "" ),
)
url.rewrite-once = (
"^/favicon\.ico$" => "/media/favicon.ico",
)
}
$HTTP["host"] == "media.yourdomain.net" {
server.document-root = "/var/django/yourdomain/contrib/admin/media/"
expire.url = ( "" => "access 7 days" )
}