| 
	相信很多人有已经从apache之类的web服务器转到Nginx了,然而Nginx除了单纯的web服务器用途外,可以当做反向代理服务器使用,配合proxy_cache功能基本可以代替squid了。 
	1. 编译安装Nginx 
	
		
			
				| 
						12
 | 
						./configure --user=www --group=www --prefix=/opt/nginx --with-http_stub_status_module --with-http_ssl_modulemake && make install
 |  
	2. nginx.conf配置文件如下: 
	
		
			
				| 
						12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 | 
						user  www www;worker_processes 8;
 error_log  /opt/nginx/logs/nginx_error.log  crit;
 pid        /opt/nginx/nginx.pid;
 
 #Specifies the value for maximum file descriptors that can be opened by this process.
 worker_rlimit_nofile 65535;
 
 events
 {
 use epoll;
 worker_connections 65535;
 }
 
 http
 {
 include       mime.types;
 default_type  application/octet-stream;
 
 charset  utf-8;
 
 server_names_hash_bucket_size 128;
 client_header_buffer_size 32k;
 large_client_header_buffers 4 32k;
 client_max_body_size 300m;
 
 sendfile on;
 tcp_nopush     on;
 
 keepalive_timeout 60;
 
 tcp_nodelay on;
 
 client_body_buffer_size  512k;
 proxy_connect_timeout    5;
 proxy_read_timeout       60;
 proxy_send_timeout       5;
 proxy_buffer_size        16k;
 proxy_buffers            4 64k;
 proxy_busy_buffers_size 128k;
 proxy_temp_file_write_size 128k;
 
 gzip on;
 gzip_min_length  1k;
 gzip_buffers     4 16k;
 gzip_http_version 1.1;
 gzip_comp_level 2;
 gzip_types       text/plain application/x-javascript text/css application/xml;
 gzip_vary on;
 
 #注:proxy_temp_path和proxy_cache_path指定的路径必须在同一分区
 proxy_temp_path   /data/proxy_temp_dir;
 #设置Web缓存区名称为cache_one,内存缓存空间大小为200MB,1天没有被访问的内容自动清除,硬盘缓存空间大小为30GB。
 proxy_cache_path  /data/proxy_cache_dir  levels=1:2   keys_zone=cache_one:200m inactive=1d max_size=30g;
 
 upstream backend_server {
 server   192.168.8.43:80 weight=1 max_fails=2 fail_timeout=30s;
 server   192.168.8.44:80 weight=1 max_fails=2 fail_timeout=30s;
 server   192.168.8.45:80 weight=1 max_fails=2 fail_timeout=30s;
 }
 
 server
 {
 listen       80;
 server_name  *.yourdomain.com;
 index index.html index.htm;
 root  /data/htdocs/www;
 
 location /
 {
 #如果后端的服务器返回502、504、执行超时等错误,自动将请求转发到upstream负载均衡池中的另一台服务器,实现故障转移。
 proxy_next_upstream http_502 http_504 error timeout invalid_header;
 proxy_cache cache_one;
 #对不同的HTTP状态码设置不同的缓存时间
 proxy_cache_valid  200 304 12h;
 #以域名、URI、参数组合成Web缓存的Key值,Nginx根据Key值哈希,存储缓存内容到二级缓存目录内
 proxy_cache_key $host$uri$is_args$args;
 proxy_set_header Host  $host;
 proxy_set_header X-Forwarded-For  $remote_addr;
 proxy_pass http://backend_server;
 expires      1d;
 }
 
 #扩展名以.php、.jsp、.cgi结尾的动态应用程序不缓存。
 location ~ .*\.(php|jsp|cgi)?$
 {
 proxy_set_header Host  $host;
 proxy_set_header X-Forwarded-For  $remote_addr;
 proxy_pass http://backend_server;
 }
 
 access_log  off;
 }
 }
 |  
	3. 接下来启动nginx吧 
	4. 能否将缓存按照域名分文件夹存放?由于我们的运营的是一个网站集群,所以子站是通过域名泛解析解析到本机的,所以希望能否按照域名存放,便于整站清理缓存。比如:a.youdomain.com/a/b3/…. ,b.youdomain.com/b/ae/….,这样的目录结构。但是研究了很久nginx配置方式,并没有发现相关的设置。于是想到自己来改写nginx源代码,涉及到的文件是src/http/ngx_http_file_cache.c文件。
 以下函数的改写是基于 nginx0.8.55的。
 ngx_http_file_cache_name函数改写如下:
 
	
		
			
				| 
						12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 | 
						static ngx_int_tngx_http_file_cache_name(ngx_http_request_t *r, ngx_path_t *path)
 {
 u_char            *p;
 ngx_http_cache_t  *c;
 size_t            pathlen;
 
 c = r->cache;
 //added by Lingter
 pathlen = path->name.len;
 
 ngx_http_file_cache_domain(r,path);
 
 c->file.name.len = path->name.len + 1 + path->len
 + 2 * NGX_HTTP_CACHE_KEY_LEN;
 c->file.name.data = ngx_pnalloc(r->pool, c->file.name.len + 1);
 
 if (c->file.name.data == NULL) {
 return NGX_ERROR;
 }
 
 ngx_memcpy(c->file.name.data, path->name.data, path->name.len);
 
 p = c->file.name.data + path->name.len + 1 + path->len;
 p = ngx_hex_dump(p, c->key, NGX_HTTP_CACHE_KEY_LEN);
 *p = '\0';
 
 ngx_create_hashed_filename(path, c->file.name.data, c->file.name.len);
 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
 "cache file: \"%s\"", c->file.name.data);
 
 path->name.len = pathlen;
 
 return NGX_OK;
 }
 |  
	上一段代码中加入了一个新的函数ngx_http_file_cache_domain的调用。先申明一下函数定义:
 
	
		
			
				| 
						12
 | 
						static ngx_int_t ngx_http_file_cache_domain(ngx_http_request_t *r,ngx_path_t *path);
 |  
	具体函数内容: 
	
		
			
				| 
						12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 | 
						//added by Lingterstatic ngx_int_t ngx_http_file_cache_domain(ngx_http_request_t *r,ngx_path_t *path)
 {
 ngx_http_cache_t    *c;
 u_char              *pathname,*pos;
 size_t              i;
 ngx_str_t           *key,domain;
 
 c = r->cache;
 key = c->keys.elts;
 
 domain.len  = key[0].len;
 domain.data = ngx_pstrdup(r->pool,& key[0]);
 pos = (u_char *) ngx_strchr(domain.data,'/');
 if(pos){
 *pos = '\0';
 domain.len = ngx_strlen(domain.data);
 
 pathname = path->name.data;
 i = path->name.len+1;
 pathname[i-1] = '/';
 ngx_memcpy(&pathname[i],domain.data,domain.len);
 path->name.len = i + domain.len;
 }
 return NGX_OK;
 }
 |  
	实际上上面的代码仅仅是找出key中的第一个出现字符’/'的地方,并且将/前的字符串作为域名拼接到缓存路径里去。由于本人不会C语言,所以写得比较粗糙,但是基本实现了这一需求。
 
	看看最终的成果吧: 
	 
	附上完整的 ngx_http_file_cache.c文件吧:ngx_http_file_cache.c(责任编辑:IT) |