文章列表
 
您正在查看 "Webserver" 分类下的文章

2010年02月22日 星期一 下午 2:27
欢迎访问我的新主页:http://huoding.com/

作者:老王

获得客户端IP原本是一个非常简单的事情,程序里很多时候使用REMOTE_ADDR环境变量就可以了,但随着网络结构复杂性越来越高,比如说Apache前有Nginx,或者Nginx前有Squid,这时就复杂了,还得考虑诸如:HTTP_CLIENTADDRESS,HTTP_CLIENT_IP,HTTP_X_FORWARDED_FOR等环境变量,当然可以通过编写程序代码来处理此类逻辑,不过这样的解决方法不够透明,毕竟很多第三方程序并没有考虑这些情况,而且后面服务器的日志里面记录的IP全变成了前面服务器的IP,如此一来,Awstats之类的软件就失效了。下面看看如何透明处理:

案例1:Apache前有Nginx

有些网站使用这样的方式来分离静态请求和动态请求,Nginx放在前面处理静态请求,然后再把动态请求转发给后面的Apache,不过如此一来,Apache日志里看到的IP就是Nginx的IP了,为了能让Apache透明获取IP,可以使用mod_rpaf

配置很简单,只需在配置文件里加上如下内容:

LoadModule rpaf_module libexec/apache2/mod_rpaf-2.0.so
RPAFenable On
RPAFsethostname On
RPAFproxy_ips 127.0.0.1 192.168.0.1

RPAFheader X-Forwarded-For


说明:192.168.0.1指的是Nginx内网IP,可以设置多个IP。

最后确认一下Nginx配置文件里在把动态请求转发给Apache的时候是否设置了如下内容:

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;


重新加载一下服务,差不多就OK了。

案例2:Nginx前有Squid

有些网站使用这样的方式来搭建分布式缓存,若干台Squid放在前面提供缓存服务,内容从后面的Nginx获取。不过如此一来,Nginx日志里看到的IP就是Squid的IP了,为了能让Nginx透明获取IP,可以使用NginxHttpRealIpModule

NginxHttpRealIpModule缺省并没有激活,可以在编译的时候使用--with-http_realip_module选项激活它。

配置很简单,只需在配置文件里加上如下内容:

set_real_ip_from   192.168.1.0/24;
set_real_ip_from   192.168.2.1;
real_ip_header     [X-Real-IP|X-Forwarded-For];


需要说明的地方就是设置IP源的时候可以设置单个IP,也可以设置IP段,另外是使用X-Real-IP还是X-Forwarded-For,取决于前面的服务器有哪个头

重新加载一下服务,差不多就OK了。

另外:Lighttpd有一个类似的模块叫mod_extforward,功能差不多,就不多说了。
 
2010年01月09日 星期六 上午 9:44
欢迎访问我的新主页:http://huoding.com/

作者:老王

虽说rewrite不难,但有些细节可能不是每个人都清楚,比如说rewrite在per-server和per-dir两种配置下的效率,下面我们通过开启日志来判断到底哪个效率好,在实验前请下做好相关配置,并编辑适当的测试文件a.html,b.html,每次测试后通过tail -f /usr/local/apache2/logs/rewrite.log来实时监控发生了什么。

先看per-server配置:


01 <VirtualHost *:80>
02     ServerName _default_
03
04     RewriteEngine on
05
06     RewriteLog /usr/local/apache2/logs/rewrite.log
07     RewriteLogLevel 9
08
09     # RewriteRule ^/a.html$ /usr/local/apache2/htdocs/b.html [L]
10     # RewriteRule ^/a.html$ /b.html
[L]
11 </VirtualHost>

规则:RewriteRule ^/a.html$ /usr/local/apache2/htdocs/b.html

日志:

init rewrite engine with requested uri /a.html
applying pattern '^/a.html$' to uri '/a.html'
rewrite '/a.html' -> '/usr/local/apache2/htdocs/b.html'
local path result: /usr/local/apache2/htdocs/b.html
go-ahead with /usr/local/apache2/htdocs/b.html [OK]


规则:RewriteRule ^/a.html$ /b.html

日志:

init rewrite engine with requested uri /a.html
applying pattern '^/a.html$' to uri '/a.html'
rewrite '/a.html' -> '/b.html'
local path result: /b.html
prefixed with document_root to /usr/local/apache2/htdocs/b.html
go-ahead with /usr/local/apache2/htdocs/b.html [OK]


再看per-dir配置:

01 <Directory "/usr/local/apache2/htdocs">
02     RewriteEngine on
03
04     RewriteLog
/usr/local/apache2/logs/rewrite.log
05     RewriteLogLevel 9
06
07     # RewriteRule ^a.html$ /usr/local/apache2/htdocs/b.html
[L]
08     # RewriteRule ^a.html$ /b.html [L]
09     # RewriteRule ^a.html$ b.html [L]
10 </Directory>

规则:RewriteRule ^a.html$ /usr/local/apache2/htdocs/b.html

日志:

strip per-dir prefix: /usr/local/apache2/htdocs/a.html -> a.html
applying pattern '^a.html$' to uri 'a.html'
rewrite 'a.html' -> '/usr/local/apache2/htdocs/b.html'
strip document_root prefix: /usr/local/apache2/htdocs/b.html -> /b.html
internal redirect with /b.html [INTERNAL REDIRECT]
strip per-dir prefix: /usr/local/apache2/htdocs/b.html -> b.html
applying pattern '^a.html$' to uri 'b.html'
pass through /usr/local/apache2/htdocs/b.html


规则:RewriteRule ^a.html$ /b.html

日志:

strip per-dir prefix: /usr/local/apache2/htdocs/a.html -> a.html
applying pattern '^a.html$' to uri 'a.html'
rewrite 'a.html' -> '/b.html'
internal redirect with /b.html [INTERNAL REDIRECT]
strip per-dir prefix: /usr/local/apache2/htdocs/b.html -> b.html
applying pattern '^a.html$' to uri 'b.html'
pass through /usr/local/apache2/htdocs/b.html



即便简单通过日志的行数,我们也能看到per-server的效率高于per-dir,仔细查看日志,会发现当在per-dir配置下使用rewrite时,系统会发生一次“INTERNAL REDIRECT”,所以以后写rewrite时,除非必要,否则不要使用pre-dir配置,而应尽可能使用per-server配置,至于是使用file路径,还是url路径,差别不大,不过url路径的看上去更短些,也更好维护一些。
 
2009年08月15日 星期六 下午 8:17
作者:老王

优雅的重启Apache:


/path/to/apache/to/apachectl graceful


安装简单的Apache模块:


/path/to/apache/bin/apxs -cia module.c


cia三个字母分别表示编译compile,安装install,启用activate。

安装把.so文件放入apache可以找到的位置,启用表示将模块加入到httpd.conf文件中。

不记录来自本机的图片请求:

<FilesMatch \.(gif|jpg|png)>
SetEnvIfNoCase Referer "^http://www.foobar.com/" local_referrer=1
</FilesMatch>

CustomLog logs/access_log combined env=!local_referrer


或者

<directory ...>
RewriteEngine On
RewriteRule "\.(gif|jpg|png)$" "-" [ENV=local_referrer:1]
</directory>

CustomLog logs/access_log combined env=!local_referrer


记录任意环境变量,其实就是%{...}e语法:

CustomLog logs/accept_log "%{UNIQUE_ID}e"

记录任意请求头,其实就是%{...}i语法:

CustomLog logs/accept_log "%{Accept}i"

记录任意响应头,其实就是%{...}o语法:

CustomLog logs/accept_log "%{Last-Modified}o"

拒绝未被引用的请求:

RewriteEngine On
RewriteCond %{HTTP_REFERER} !=""
RewriteCond %{HTTP_REFERER} "!^http://www.foobar.com/.*$" [NC]
RewriteCond %{REQUEST_URI} "\.(gif|jpg|png)$"
RewriteRule ".*" "-" [F]


依据查询字符串来重写:

RewriteEngine on
RewriteCond "%{QUERY_STRING}" "^user=([^=]*)"
RewriteRule "/userdirs" "http://%1.foobar.com/" [R]


以Rewirte规则建立大量的虚拟主机:

RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www\.)?([^.]+)\.com$
RewriteRule "^(.*)$" /home/%2$1
 
2009年04月19日 星期日 上午 10:20
作者:老王

Nginx分布式负载的设置是通过Upstream模块实现的,而且相当简单。

upstream www.foobar.com {
server backend1.foobar.com;
server backend2.foobar.com;
}

server {
location / {
proxy_pass http://www.foobar.com;
}
}

如此一来,我们就可以把foobar的负载分布到backend1和backend2。

有几个参数可以进行细节调整:weight,max_fails,fail_timeout

upstream www.foobar.com {
server backend1.foobar.com weight=5;
server backend2.foobar.com max_fails=3 fail_timeout=30s;
}

你可以通过参数ip_hash调整请求分布的去向按照ip确定:

upstream www.foobar.com {
ip_hash
server backend1.foobar.com;
server backend2.foobar.com;
}

这样每个访客固定访问一个后端服务器。可以解决一些特定的问题,比如说session。
 
2007年12月24日 星期一 下午 7:51
作者:老王

一台运行Apache的Web服务器,前面有Squid,出现大量的CLOSE_WAIT连接,直接占满TCP队列,导致Apache失去响应。

一般来说,在一次正常的HTTP连接结束时,按正常的次序应该是服务器先发出FIN信号,客户端确认,然后客户端再发出FIN信号,服务端确认。如果客户端因为某种原因先于服务端发出了FIN信号,就会导致服务端被动关闭。

-------------------------------------

通过下列Linux内核参数来解决问题:

sysctl -w net.ipv4.tcp_keepalive_time=30
sysctl -w net.ipv4.tcp_keepalive_probes=2
sysctl -w net.ipv4.tcp_keepalive_intvl=2

注意:Linux的内核参数我调整的可能有些猛,到底合不合适要注意观察。

参考链接:
http://ipsysctl-tutorial.frozentux.net/
http://haka.sharera.com/blog/BlogTopic/32309.htm
 
   
 
 
文章存档
 
     
 
最新文章评论
  

[表情]
 

不错!
 

linux大师之路,www.linuxmr.com
 

引导一直没有整明白说。
 

[表情]
   
帮助中心 | 空间客服 | 投诉中心 | 空间协议
©2012 Baidu