0%

Nginx追加sticky的那些坑

问题:在集群中有多台服务器的情形下,开发者会在Cookie中记录一些字段,甚至是登录态。所以需要让访问者访问到某台机器后,后续的请求仍然在同一台服务器上处理。

一、需求分析

目前,负载分发问题的约束条件是:

  • 众多访问者的请求尽可能均匀地被分发到后端集群的机器中。
  • 同一个访问者再次访问,多个请求被同一台机器处理。

解决方案

  • IP Hash:利用用户在上网时,一段时间内的ip是不会改变的原理。将用户的ip做哈希,对其请求进行分发。因为用户的ip暂时不变,所以其请求会被分发到同一台机器上。
  • 基于Cookie做跟踪:第一次请求时,服务器给客户端下发一个cookie,具有特定cookie的请求会分配给同一个服务器。

上述两种方案中显然第二种更优。因为约束条件第一条,请求尽可能均匀地被分发。用IP做Hash的情况,当属于某种类型IP的用户请求非常多的话,负载会出现不均匀的情况。另外,如果前置还有代理服务器的话,IP相同的情况,也会出现请求分布不均匀。所以采用第二种方案较好,Sticky第三方模块就是利用第二种方案的思路。

二、下载安装

下载

下载地址:http://code.google.com/p/nginx-sticky-module/downloads/list

或者

wget https://code.google.com/p/nginx-sticky-module/downloads/detail?name=nginx-sticky-module-1.1.tar.gz

解压:
tar -xzvf nginx-sticky-module-1.1.tar.gz

我这里解压到

/usr/local/nginx/sticky/nginx-sticky

安装

在Nginx源码编译的目录下,运行代码:

./configure —prefix=/usr/local/nginx —add-module=/usr/local/nginx/sticky/nginx-sticky

make
(不要make install,要不然就相当于重新安装了。)

复制编译后的二进制文件到目录(拷贝前把服务停掉):

1
2
cp /usr/local/nginx/nginx  /usr/local/nginx/nginx.bak
cp /usr/local/nginx-1.9.3/objs/nginx /usr/local/nginx/nginx
使用

在nginx.conf配置文件中,对upstream块添加sticky;即可。

1
2
3
4
5
6
7
upstream myproject{
#添加sticky模块后加入此配置
sticky;
#被代理的服务
server 192.168.1.100:8081;
server 192.168.1.101:8080;
}

三、问题及解决

编译出现类型转换错误
1
2
3
4
cc1: warnings being treated as errors
ngx_http_sticky_module.c: In function ‘ngx_http_get_sticky_peer’:
/ngx_http_sticky_module.c:333: 警告:赋值时将整数赋给指针,未作类型转换
ake[1]: *** [objs/addon/nginx-sticky-module-1.1/ngx_http_sticky_module.o] 错误 1

解决:

第一步:根据资料 把ngx_http_sticky_misc.c 的281行修改如下:

原digest->len = ngx_sock_ntop(in,digest
->data, len, 1);

改成digest->len = ngx_sock_ntop(in,sizeof(struct sockaddr_in),digest
->data, len, 1);

第二步:对nginx-sticky-module-1.1/ngx_http_sticky_module.c文件也进行修改(主要是1.9.x版本会出现这问题)
修改两个地方,如下图:

第6行添加:

1
#include <nginx.h>

第340行左右修改(iphp->rrp.current = iphp->selected_peer;)为:

1
iphp->rrp.current = peer;

版本问题,修改stick代码后,问题得以解决。


编译出现hash和md5问题

问题描述:

1
2
3
ngx_http_sticky_misc.c: In function 「ngx_http_sticky_misc_md5」:
ngx_http_sticky_misc.c:152:15: ERROR:「MD5_DIGEST_LENGTH」 undeclared (first use in this function)
u_char hash[MD5_DIGEST_LENGTH];

解决:
解决方式就是在下载解压缩之后的sticky模块文件夹中,修改ngx_http_sticky_misc.c文件
将这两个模块 and 包含到文件ngx_http_sticky_misc.c
下面红色标注地方

1
2
#include <openssl/sha.h>
#include <openssl/md5.h>

引入的问题,引入之后再重新编译就不会出现这种原因的错误了。


编译出现依赖的模块问题

描述:

1
fatal error: openssl/aes.h:No such file or directory

解决:
尝试编译的程序使用OpenSSL,但是需要和OpenSSL链接的文件(库和头文件)在Linux平台系统上缺少。(其它类似的错误也可以照此处理)

要解决这个问题,安装OpenSSL。
要在Debian、Ubuntu或者其他衍生版上安装OpenSSL:

1
sudo apt-get install libssl-dev

要在Fedora、CentOS或者RHEL上安装OpenSSL开发包:

1
sudo yum install openssl-devel

安装完后,尝试重新编译程序。

参考&致谢

nginx-sticky-module文档

nginx-sticky-module-ng文档问题

觉得不错?