Iawen's Blog

我喜欢这样自由的随手涂鸦, 因为我喜欢风......

1. Nginx的负载均衡

负载均衡可以把用户的请求分摊到多个服务器上进行处理, 从而实现了对海量用户的访问支持。负载均衡的架构如图所示: 0

1.1 upstream

upstream用于设置后端服务器组的主要指令, 类似于之前的server块或http块, 用法如下:

upstream Myserver{ 
    #ip_hash;
    #least_conn; 
    #fair;

    #hash $request_uri;
    #hash_method crc32;
    server 192.168.0.2:8080 #weight 2 max_fails 3 fail_timeout 60;
    192.168.0.3:8080 backup;
    192.168.0.4:8080 down; 
}
  • Myserver是后端服务器组的名称, 在大括号里面填写后端服务器的IP和端口信息, 默认情况下服务器组被调用以后会使用轮询调度的方式调用组内的后端服务器
  • keepalived_timeout 保持的空闲会话的时常, 在此时间内客户端不进行操作, 服务器将断开与客户端的连接。此数值不能太大, Nginx从1.1.4开始支持
  • ip_hash; 实现会话保持功能, 即将某个客户端的请求定向到组内的同一台服务器, 保证客户端与服务器之间建立稳定的会话, 只有服务器处于无效状态时, 会话才会被转发给组内其他的服务器
  • server 用于定义一台后端服务器
    • 192.168.0.2:8080 是后端服务器的IP, 端口是8080
    • weight = number; #配置权重, 与ip_hash有冲突, 因为ip_hash是将请求固定在同一个后端服务器的, 而weight是根据权重轮训的, 因此不能同时配置在一个upstream内
    • max_fails = number #设置一个失败的请求次数, 在一定时间内超过这个次数就认为服务器是无效的, 如可以设置为3: 在失败3次以后的60秒将不再将请求分发给失效的server也不在检查此server的状态, 默认时间是10
    • backup 将一台服务器标记为备份服务器, 只有当所有正常服务器全部不可用的时候才会使用备份的服务器
    • down 将一台服务器标记为永久不可用的状态, 通常与ip_hash配合使用。

1.2 nginx 的 upstream支持的集中调度算法

1.2.1 轮询(默认)

每个请求按时间顺序逐一分配到不同的后端服务器, 如果后端服务器down掉, 能自动删除。

1.2.2 weight

指定轮询几率, weight和访问比率成正比, 用于后端服务器性能不均的情况。

1.2.3 ip_hash

每个请求按访问ip的hash结果分配, 这样每个访客固定访问一个后端服务器, 可以解决session 保持的问题

1.2.4 fair(第三方)

可以依据页面大小和加载时间长短智能地进行负载均衡, 也就是根据后端服务器的响应时间来分配请求, 响应时间短的优先分配,Nginx本身默认是不支持fair的, 如果需要使用这种调度算法, 必须下载Nginx的upstream_fair模块。

1.2.5 url_hash(第三方)

按访问url的hash结果来分配请求, 使每个url定向到同一个后端服务器, 可以进一步提高后端缓存服务器的效率, Nginx本身默认是不支持url_hash的, 如果需要这种高度算法, 必须安装Nginx的hash软件包。

1.2.6 least_conn

根据后端服务器的连接状况进行分配客户请求, 连接最少的服务器将被有限分配客户端请求

2. Nginx服务器的rewrite功能介绍

Nginx服务器利用ngx_http_rewrite_module 模块解析和处理rewrite请求, 所以说此功能依靠 PCRE(perl compatible regularexpression), 因此编译之前要安装PCRE库, rewrite功能时nginx服务器的基本功能之一, 用于实现URL的重写, URL的重写是非常有用的功能, 比如它可以在我们改变网站结构之后, 不需要客户端修改原来的书签, 也无需其他网站修改我们的链接, 就可以设置为访问, 另外还可以在一定程度上提高网站的安全性。

2.1 nginx重定向规则详细介绍

nginx的rewrite相当于apache的rewriterule(大多数情况下可以把原有apache的rewrite规则加上引号就可以直接使用), 它可以用在server,location 和IF条件判断块中,命令格式如下:
rewrite 正则表达式 替换目标 flag标记 flag标记可以用以下几种格式:
last – 基本上都用这个Flag。 break – 中止Rewirte, 不在继续匹配 redirect – 返回临时重定向的HTTP状态302 permanent – 返回永久重定向的HTTP状态301

例如下面这段设定nginx将某个目录下面的文件重定向到另一个目录,$2对应第二个括号(.*)中对应的字符串:

location /download/ { 
    rewrite ^(/download/.*)/m/(.*)\..*$ $1/nginx-rewrite/$2.gz break; 
}

2.2 地址重写与地址转发

地址重写和地址转发是两个不同的概念, 地址重写是实际上是为了实现址标准化, 就像访问www.baidu.cn可以出现www.baidu.com的首页, 服务器会把www.baidu.cn重写成www.baidu.com, 浏览器的地址栏也会显示www.baidu.com, 而转发指的是将一个域名指向另一个已有站点的过程, 地址栏的地址保持不变, 因此地址转发和地址重写的大致区别如下:

  • 地址转发后客户端浏览器地址栏中的地址显示是不变的, 而地址重写后地址栏中的地址会变成正确的地址。
  • 在一次地址转发过程中只会产生一次网络请求, 而一次地址重写产生两次请求。
  • 址转发一般发生在同一站点项目内, 而地址重写则没有限制。
  • 地址转发到的页面可以不用全路径名表示, 而地址重写到的页面必须使用完全的路径名表示。
  • 地址转发过程中, 可以将客户端请求的request范围内的属性传递给新的页面, 但地址重写不可以。
  • 地址转发的速度比地址重写的速度快。

2.3 if指令

根据条件判断结果选择不同的Nginx配置, 可以配置在server或location块中进行配置, 用法如下:

if ($变量) { 
action
}

注: 如果$变量的值为空字符串或是以0开头的任意字符串, 则if指令认为该条件为false, 其他条件为true。条件里的字符串不需要加引号.

2.3.1 正则表达式

如:
匹配判断

~      为区分大小写匹配;
!~     为区分大小写不匹配 
~*     为不区分大小写匹配; 
!~     为不区分大小写不匹配 
^~     如果把这个前缀用于一个常规字符串, 那么告诉nginx 如果路径匹配那么不测试正则表达式

例如下面设定nginx在用户使用ie的使用重定向到/nginx-ie目录下:

if ($http_user_agent ~ MSIE) { 
    rewrite ^(.*)$ /nginx-ie/$1 break; 
}

2.3.2 文件和目录判断

-f和!-f        判断是否存在文件 
-d和!-d        判断是否存在目录 
-e和!-e        判断是否存在文件或目录 
-x和!-x        判断文件是否可执行 

例如下面设定nginx在文件和目录不存在的时候重定向:

if (!-e $request_filename) { 
    proxy_pass http://127.0.0.1/; 
}

2.3.3 return 和 break

break指令用于中断当前相同作用域中的其他Nginx配置, 与该指令处于同一作用域的Nginx配置中, 位于它前面的配置生效, 位于后面的指令配置就不再生效了, Nginx服务器在根据配置处理请求的过程中遇到该指令的时候, 回到上一层作用域继续向下读取配置, 该指令可以在server块和location块以及if块中使用, 使用语法如下:

location /test {
    root html;
    index index.html index.htm;
    break; #return之后的将不再执行, 之前的可以执行
}

return用于完成对请求的处理, 并直接向客户端返回响应状态码, 处于此指令后的所有配置都将不被执行, return可以在server、if和location块进行配置,

  • return (text); #返回给客户端的响应体内容, 可以调用变量
  • return code; #返回给客户端HTTP状态码, 范围为0-999
  • return URL; #返回给客户端的URL地址

例如设置nginx防盗链:

location ~* \.(gif|jpg|png|swf|flv)$ { 
    valid_referers none blocked http://www.jefflei.com/ http://www.leizhenfang.com/; 
    if ($invalid_referer) { 
        return 404; 
    } 
}
# none是用户正常在浏览器输入地址访问的请求连接 
# blocked 类似于防火墙法则, 只要不符合给定条件的就认定是不合法的, 就拒绝访问。

2.3.4 set

用于设置一个新的变量, 其用法结构为:

set variable value;

variable为变量的名称, 要使用$作为变量的第一个字符, 且变量名不能与nginx服务器预设的全局变量相同 value: 为变量的值, 可以是字符串、其他变量和变量组合等。

2.3.5 301重定向方法

  • 301: 永久重定向, 一般资源都在服务器内部, 客户端请求一次即可完成数据的返回
  • 302: 临时重定向, 当nginx作为代理服务器, 并使用rewrite重写用户请求的URL的到其他服务器的时候, 就是临时重定向

进行了301重定向, 把www.jb51.net和jb51.net合并, 并把之前的域名也一并合并. 有两种实现方法,第一种方法是判断nginx核心变量host(老版本是http_host):

server { 
    server_name www.jb51.net jb51.net ; 
    if ($host != 'www.jb51.net' ) { 
        rewrite ^/(.*)$ http://www.jb51.net/$1 permanent; 
    } 
} 

第二种方法:

server { 
    server_name jb51.net; 
    rewrite ^/(.*) http://www.jb51.net/$1 permanent; 
}

测试了第一种方法ok, 这两种方法中, permanent是关键, 详细说明见nginx重定向规则说明。第二种方法没有测试成功…

2.3.6 flag

  • last 终止继续在本location块中处理接受到的URL, 并将在本location中重新的URL作为一个新的URL, 继续使用后面的各location块进行处理, 该标志将重写后的URL重新再server块中执行, 为重写后的URI转入到其他location块并继续处理的机制, nginx服务器的last处理超过10次循环之后将返回错误代码500, 使用方法如下:
location / {
    rewrite ^(/test/.*)/msie(.*)\..*$ $1/test/mp3/$2.html break;
    rewrite ^(/test/.*)/other(.*)\.*$ $1/test/other/$2.html break; 
}

注: 如果URI在第二行被匹配成功并处理, Nginx服务器不会继续使用第三行的配置和匹配处理新的URL, 而是让所有的location快重新匹配和处理新的URI, 即一旦在本location中匹配成功一行, 就跳出本location并在下一个location匹配, 直到在下一个location匹配成功后再跳出下一个location继续下下一个, 直到最后一个为止。

  • redirect 将重写后的URI返回给客户端, 状态码为302, 指明是临时重定向URI, 主要用在replacement变量不是以http或https开头的情况下

  • permanent 将重写后的URI返回给客户端, 代码为301, 注明是永久重定向

2.4 重定向方法总结

2.4.1 访问 A 站定向到 B 站

server { 
    server_name www.a.com ; 
    rewrite ^(.*) http://www.b.com$1 permanent; 
}

2.4.2 不是访问 A 站的全部重定向到指定页面

server { 
    server_name www.a.com; 
    if ($host != ‘a.com' ) {
        rewrite ^/(.*)$ http://www.b.com/$1 permanent;
    }
}

如果写在第一个server段 使用IP访问时也将被重定向

2.4.3 带WWW或者不带WWW之间的跳转

server { 
    server_name c.net 
    rewrite ^/(.*)$ http://www.c.net/$1 permanent; 
}

3. 代理服务器

3.1 反向代理服务器

nginx rewrite功能使用模块ngx_http_rewrite_module, rewrite是nginx服务器的重要模块之一, 它一方面实现了URL的重写功能, 另一方面为Nginx服务器提供反向代理服务器的支持, 使用如下:

3.1.1 proxy_pass

反向代理, 将用户的请求代理至后端服务器

server {
    server_name hfnginx.chinacloudapp.cn;
    #access_log logs/host.access.log main;
    location / {
        root html/hfnginx;
        index index.html index.htm;
    }
    location /form/ { #匹配一个访问的目录
        proxy_pass http://192.168.0.201/bbs/; #/form后面的斜杠要和http://192.168.0.201/bbs后面的斜杠要么都有要么都没有, 否则访问匹配会出现错误。
    }
}