Teaser Image

Nie&Gao

Anyway, life is elsewhere and we all know it.




 「Nginx」

正向代理服务器是一个为用户(user)转发请求(http request)到Internet上的服务器的中介服务器。而反向代理服务器reverse proxy server 是代理服务器的特例,它代理的用户是公司的后端服务器。当反向代理服务器收到来自internet上的请求时候,它转发请求到公司内部网络的上游服务器,并将从服务器上返回的结果返回给用户。此时反向代理服务器对外表现就是一个服务器。

反向代理服务器的作用:

  1. 负载均衡

  2. 网络加速
    2.1 cache

    2.2 compress inbound and outbound data

    2.3 perform additional taks such as SSL encrpyion to take load off of your web servers.

  3. 安全和匿名

一个反向代理服务器通常具有的功能 : 负载均衡 + 反向代理 + 页面缓存


1. 负载均衡

upstream是Nginx的HTTP Upstream模块,这个模块通过一个简单的调度算法来实现客户端IP到后端服务器的负载均衡。

upstream 支持的负载均衡算法:

Nginx的负载均衡模块目前支持4种调度算法,其中后两项属于第三方调度算法。

  • 轮询(默认)。每个请求按时间顺序逐一分配到不同的后端服务器,如果后端某台服务器宕机,故障系统被自动剔除,使用户访问不受影响。Weight 指定轮询权值,Weight值越大,分配到的访问机率越高,主要用于后端每个服务器性能不均的情况下。
  • ip_hash。每个请求按访问IP的hash结果分配,这样来自同一个IP的访客固定访问一个后端服务器,有效解决了动态网页存在的session共享问题。
  • fair。这是比上面两个更加智能的负载均衡算法。此种算法可以依据页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间来分配请求,响应时间短的优先分配。Nginx本身是不支持fair的,如果需要使用这种调度算法,必须下载Nginx的upstream_fair模块。
  • url_hash。此方法按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,可以进一步提高后端缓存服务器的效率。Nginx本身是不支持url_hash的,如果需要使用这种调度算法,必须安装Nginx 的hash软件包。

2. 反向代理

  1. proxy_pass 此配置项将当前请求反向代理到URL参数指定的服务器上,URL可以是主机名or IP地址加端口形式
  2. proxy_method Nginx会将上游服务器的响应转发给客户端,但默认不会转发以下HTTP头部字段:Date, Server,X-Pad 和X-Access-*。
  3. proxy_hide_header 使用proxy_hide_header后可以任意地指定那些HTTP头部字段不能被转发。
  4. proxy_pass_header 与proxy_hide_header相反,proxy_pass_header会将原来禁止转发的header设置为允许转发。
  5. proxy_set_header 设置请求头并将请求头信息传递给服务器端。 使用场景:需要获取用户IP地址,比如做异地登录判断,或者统计IP访问次数等。通常情况下可以在后端使用request.getRemoteAddr()获取客户端ip,但是当我们使用nginx做反向代理后,使用request.getRemoteAddr() 获取到的就是nginx的ip地址。但是,nginx是可以获得用户的真实ip的,也就是说nginx使用$remote_addr变量时获得的是用户的真实ip,如果我们想要在web端获得用户的真实ip,就必须在nginx这里作一个赋值操作,如下: proxy_set_header X-real-ip $remote_addr; 其中这个X-real-ip是一个自定义的变量名,名字可以随意取,这样做完之后,用户的真实ip就被放在X-real-ip这个变量里了,然后,在web端可以这样获取: request.getHeader("X-real-ip")

3. 页面缓存

nginx为了实现页面缓存的需求而增加了一个ngx_http_proxy_module模块。http://nginx.org/en/docs/http/ngx_http_proxy_module.html

关于页面缓存

静态资源,比如新闻等这类基本不变化的页面,提供一个静态页面缓存机制,避免每次都动态拉取数据渲染生成HTML. 总体原则:应用服务器(tomcat)不处理静态资源的缓存,由前端缓存来处理。前端缓存主要包括Nginx缓存,CDN缓存,浏览器缓存。这些缓存都是针对HTTP请求和相应的静态HTML资源。所以都是遵循HTTP协议中关于缓存的控制的。应用通过HTTP head 控制前端静态资源缓存的缓存时间和机制。应用服务器这边缓存的是数据(redis等cache),而不是静态页面。这样的好处是系统的边界和职责更加明确,也不需要再次实现一套静态资源缓存机制。[2]

缓存及时清理出现问题。目前清理Nginx缓存两种方式:

  1. 手动清理proxy_cache_path目录,重启Nginx服务

  2. 使用proxy_cache_purge模块清空。需要安装此模块。推荐

主要配置: - proxy_cache:指定用于页面缓存的共享内存

  • proxy_cache_bypass:定义nginx不从缓存取响应的条件
  • proxy_no_cache: 定义nginx不将响应写入缓存的条件。可以和proxy_cache_bypass指令一起使用
  • proxy_cache_key:定义如何生成缓存的键
  • proxy_cache_path:设置缓存的路径和其他参数。缓存数据是保存在文件中的,缓存的键和文件名都是在代理URL上执行MD5的结果
  • proxy_cache_use_stale:如果后端服务器出现状况,nginx是可以使用过期的响应缓存的
  • proxy_cache_valid:为不同的响应状态码设置不同的缓存时间
  • proxy_store:开启将文件保存到磁盘上的功能
  • proxy_store_access: 设置缓存目录和文件的访问权限

### 配置文件

#user  nobody;
worker_processes  1;

#pid        logs/nginx.pid;

events {
    worker_connections  1024;
}
http {
    proxy_buffering on;

     #在日志格式中加入$upstream_cache_status
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent $request_body "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"'
                      '"$upstream_cache_status" $request_time';

    # Begin Proxy Cache Config
    # keys_zone=cache:1024m 表示这个zone名称为cache,分配的内存大小为1024MB
    # D:/data/nginx/cache 表示cache这个zone的文件要存放的目录
    # levels=1:2 表示缓存目录的第一级目录是1个字符,第二级目录是2个字符,即/usr/local/nginx/proxy_cache_dir/cache1/a/1b这种形式
    # inactive=1d 表示这个zone中的缓存文件如果在1天内都没有被访问,那么文件会被cache manager进程删除掉
    # max_size=10g 表示这个zone的硬盘容量为10GB
    proxy_cache_path D:/data/nginx/cache levels=1:2 keys_zone=cache:1024m max_size=1g;
    proxy_temp_path D:/data/nginx/proxy_temp 1 2;

    #设置缓存的key
    # Putting the host name in the cache key allows different virtual hosts to share the same cache zone
    proxy_cache_key "$scheme://$host$request_uri";

    # Pass some client identification headers back to the backend_server  
    proxy_set_header   Host             $host;
    proxy_set_header   X-Real-IP        $remote_addr;
    proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;

    # Cache different return codes for different lengths of time 
    # We cached normal pages for 10 minutes
    proxy_cache_valid 200 302  10m;
    proxy_cache_valid 404      1m;

    server_names_hash_bucket_size 64; 
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;

    keepalive_timeout  65;

    gzip  on;

    ## 反向代理-设置代理的后端tomcat集群
    upstream web_server{
        ip_hash;
        server 10.14.138.164 max_fails=2 fail_timeout=3s;
        server 10.14.135.242:8080  max_fails=2 fail_timeout=3s;
    }
   
    ## 反向代理
    server {
        listen 80;
        server_name gsm.com;

        add_header Server-Address $server_addr;
        # $upstream_cache_status表示资源缓存的状态,有HIT MISS EXPIRED UPDATING STALE BYPASS几种状态
        add_header Nginx-Cache $upstream_cache_status;

        # nginx的proxy_cache不支持if判断,所以规定/cache的走缓存
        location ~/cache {
            proxy_cache cache;
            # 也可以单独配缓存失效时间
            # proxy_cache_valid 200;

            # # If it's not in the cache pass back to the backend-server 
            proxy_pass http://web_server;
        }

        # Proxy all remaining content to the backend-server
        location / {
            proxy_pass http://web_server;
        }
        error_page 404 /404.html;
        # redirect server error pages to the static page /50x.html
        #
        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
               root html;
        }
    }
}


参考

  1. 深入理解Nginx 陶辉[著] 出版社: 机械工业出版社
  2. http://blog.arganzheng.me/posts/http-caching.html
  3. http://seanlook.com/2015/06/02/nginx-cache-check/
  4. Nginx 查看命中率 http://www.361way.com/nginx-cache/2665.html