nginx负载均衡-基于客户端cookie的会话保持

通过ip_hash做会话保持有一定的缺陷,这个是通过客户端ip来实现。同一个网络下众多客户端访问服务器会被扔到同一台机器,再或者是CDN也会导致负载不均衡。所以要实现通过客户端cookie实现,包括F5、深信服设备其中的会话保持也是通过插入cookie值来实现会话保持。下次客户端访问服务器,带上本地cookie,nginx中的sticky模块分析并扔到对应服务器中。

软件版本:
nginx-1.6.0 (后来用nginx-1.2.3)
nginx-sticky-module-1.1

安装:
[root@localhost nginx-1.6.0]# ./configure –prefix=/usr/local/nginx/ –add-module=../nginx-sticky-module-1.1
[root@localhost nginx-1.6.0]# make
make时报错:
objs/addon/nginx-sticky-module-1.1/ngx_http_sticky_misc.o] 错误 1

参考解决方法:

方法一:
http://www.blogjava.net/sliverfancy/archive/2014/03/28/411594.html
说安装openssl-devel,试过无效。

方法二(未测试):
nginx-1.5.x和nginx-sticky-module-1.1编译会有点问题,应该是nginx新版本没有相应的nginx-sticky-module,解决办法是把nginx-sticky-module-1.1/ngx_http_sticky_misc.c的281行修改为:

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

方法三:
降低nginx版本,我这里换为nginx-1.2.3编译通过。

sticky模块参数只用于upstream段中,并且不能和ip_hash同时存在。
支持的参数:
sticky [name=route] [domain=.foo.bar] [path=/] [expires=1h] [hash=index|md5|sha1] [no_fallback];
name: 可以为任何的string字符,默认是route
domain:哪些域名下可以使用这个cookie
path:哪些路径对启用sticky,例如path/test,那么只有test这个目录才会使用sticky做负载均衡
expires:cookie过期时间,默认浏览器关闭就过期,也就是会话方式。
no_fallbackup:如果设置了这个,cookie对应的服务器宕机了,那么将会返回502(bad gateway 或者 proxy error),建议不启用。

配置参考(反向代理部分略过):

upstream apache {
 sticky name=srv_id expires=1h domain=.test.com path=/;

 server 192.168.5.4 max_fails=3 fail_timeout=20s;
 server 192.168.5.5 max_fails=3 fail_timeout=20s;
}

参考链接:
http://nginx.org/en/docs/http/ngx_http_upstream_module.html#sticky
http://blog.csdn.net/dc_726/article/details/12348907

xshell使用密钥登陆linux服务器

使用用户名方式登陆linux服务器,存在暴力破解可能,如果使用证书就可以避免这种问题。当然也可以通过修改ssh端口的方式绕开非法的扫描。

通过密钥方式登陆,需要在xshell中创建私钥和公钥,私钥位于客户端,公钥位于服务器端,通过私钥去解公钥。

在xshell中制作密钥:

1、点击“工具”-“新建用户密钥生成向导”

2、密钥类型选择 rsa (默认可以),长度1024(默认)

3、

4、密钥名称,自己修改。

5、公钥格式选”ssh2-openssh”,并另存为到桌面上。

6、完成后会自动弹出 用户密钥 (私钥)   #主机密钥为公钥

xshell的密钥生成完毕。现在需要将桌面上的公钥id_rsa_1024_2014-12-03.pub上传到服务器中,路径:~/.ssh/

[root@g2 ~]# cd .ssh/
[root@g2 .ssh]# ll
总用量 4
-rw-r--r-- 1 root root 208 12月 3 14:30 id_rsa_1024_2014-12-03.pub
[root@g2 .ssh]# mv id_rsa_1024_2014-12-03.pub authorized_keys
[root@g2 .ssh]# chmod 400 authorized_keys
[root@g2 .ssh]# ll
总用量 4
-r-------- 1 root root 208 12月 3 14:30 authorized_keys

修改/etc/ssh/sshd_config下面4项:
RSAAuthentication yes #RSA加密方式认证
PubkeyAuthentication yes #公钥验证
AuthorizedKeysFile .ssh/authorized_keys #公钥文件
PasswordAuthentication no #禁止密码登陆
重启ssh服务

xshell认证方式修改为密钥验证:

方法:Public Key 用户名:root 用户密钥:生成密钥时的私钥。 密码没有设置,为空。

这样就可以密钥登陆了。

PS:

一个服务器上会有多个人员的账号,这样就需要为不同人员创建不同的密钥实现权限分离,比如说为用户A创建密钥,将公钥放到/home/A/.ssh下,给用户A私钥让其登陆,用户B也如此操作。如果用同一个私钥及公钥,那么其他用户直接可以在xshell中修改用户为root,直接跃为root权限,风险太大,所以为不同用户创建不同密钥。

分布式文件系统MFS、Ceph、GlusterFS、Lustre的比较

MooseFS(MFS) Ceph GlusterFS Lustre
Metadata server 单个MDS。存在单点故障和瓶颈。 多个MDS,不存在单点故障和瓶颈。MDS可以扩展,不存在瓶颈。 无,不存在单点故障。靠运行在各个节点上的动态算法来代替MDS,不需同步元数据,无硬盘I/O瓶颈。 双MDS(互相备份)。MDS不可以扩展,存在瓶颈。
FUSE 支持 支持 支持 支持
访问接口 POSIX POSIX POSIX POSIX/MPI
文件分布/数据分布 文件被分片,数据块保存在不同的存储服务器上。 文件被分片,每个数据块是一个对象。对象保存在不同的存储服务器上。 Cluster Translators(GlusterFS集群存储的核心)包括AFR、DHT(和Stripe三种类型。AFR相当于RAID1,每个文件都被复制到多个存储节点上。Stripe相当于RAID0,文件被分片,数据被条带化到各个存储节点上。Translators可以组合,即AFR和stripe可以组成RAID10,实现高性能和高可用。 可以把大文件分片并以类似RAID0的方式分散存储在多个存储节点上。
冗余保护/副本 多副本 多副本 镜像
数据可靠性 由数据的多副本提供可靠性。 由数据的多副本提供可靠性。 由镜像提供可靠性。 由存储节点上的RAID1或RAID5/6提供可靠性。假如存储节点失效,则数据不可用。
备份 提供备份工具。支持远程备份。
故障恢复 手动恢复 当节点失效时,自动迁移数据、重新复制副本。 当节点、硬件、磁盘、网络发生故障时,系统会自动处理这些故障,管理员不需介入。
扩展性 增加存储服务器,可以提高容量和文件操作性能。但是由于不能增加MDS,因此元数据操作性能不能提高,是整个系统的瓶颈。 可以增加元数据服务器和存储节点。容量可扩展。文件操作性能可扩展。元数据操作性能可扩展。 容量可扩展。 可增加存储节点,提高容量可文件操作性能,但是由于不能增加MDS,因此元数据操作性能不能提高,是整个系统的瓶颈。
安装/部署 简单 简单 简单 复杂。而且Lustre严重依赖内核,需要重新编译内核。
开发语言 C C++ C C
适合场景 大量小文件读写 小文件 适合大文件。对于小文件,无元数据服务设计解决了元数据的问题。但GlusterFS并没有在I/O方面作优化,在存储服务器底层文件系统上仍然是大量小文件,本地文件系统元数据访问是瓶颈,数据分布和并行性也无法充分发挥作用。因此,GlusterFS的小文件性能还存在很大优化空间。 大文件读写
产品级别 小型 中型 中型 重型
应用 国内较多 较多用户使用 HPC领域。
优缺点 实施简单,但是存在单点故障。 不稳定,目前还在实验阶段,不适合于生产环境。 无元数据服务器,堆栈式架构(基本功能模块可以进行堆栈式组合,实现强大功能)。具有线性横向扩展能力。由于没有元数据服务器,因此增加了客户端的负载,占用相当的CPU和内存。但遍历文件目录时,则实现较为复杂和低效,需要搜索所有的存储节点。因此不建议使用较深的路径。 很成熟、很庞大。

nginx502和504错误分析

本文整理于网络

在使用Nginx时,经常会碰到502 Bad Gateway和504 Gateway Time-out错误,下面以Nginx+PHP-FPM来分析下这两种常见错误的原因和解决方案。

1.502 Bad Gateway错误
在php.ini和php-fpm.conf中分别有这样两个配置项:max_execution_timerequest_terminate_timeout
这两项都是用来配置一个PHP脚本的最大执行时间的。当超过这个时间时,php-fpm不仅会终止脚本的执行,
还会终止执行脚本的worker进程。所以nginx会发现与自己通信的连接断掉了,就会返回给客户端502错误。

以php-fpm的request_terminate_timeout=30 秒时为例,报502 Bad Gateway错误的具体信息如下:
1)Nginx错误访问日志:
2013/09/19 01:09:00 [error] 27600#0: *78887 recv() failed (104: Connection reset by peer) while reading response header from upstream,
client: 192.168.1.101, server: test.com, request: “POST /index.php HTTP/1.1”, upstream: “fastcgi://unix:/dev/shm/php-fcgi.sock:”,
host: “test.com”, referrer: “http://test.com/index.php”

2)php-fpm报错日志:
WARNING: child 25708 exited on signal 15 (SIGTERM) after 21008.883410 seconds from start

所以只需将这两项的值调大一些就可以让PHP脚本不会因为执行时间长而被终止了。request_terminate_timeout可以覆盖max_execution_time,
所以如果不想改全局的php.ini,那只改php-fpm的配置就可以了。

此外要注意的是nginx的upstream模块中的 max_fail 和 fail_timeout 两项。有时Nginx与上游服务器(如Tomcat、FastCGI)的通信只是偶然断掉了,
但max_fail如果设置的比较小的话,那么在接下来的fail_timeout时间内,nginx都会认为上游服务器挂掉了,都会返回502错误。
所以可以将 max_fail 调大一些,将 fail_timeout 调小一些。

2.504 Gateway Time-out错误
php-fpm设置的脚本最大执行时间已经够长了,但执行耗时php脚本时,发现nginx报错从502变为504了。这是为什么呢?
因为我们修改的只是php的配置,nginx中也有关于与上游服务器通信超时时间的配置:

fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;

以nginx超时时间为90秒,php-fpm超时时间为300秒为例,报504 Gateway Timeout错误时的Nginx错误访问日志如下:
2013/09/19 00:55:51 [error] 27600#0: *78877 upstream timed out (110: Connection timed out) while reading response header from upstream,
client: 192.168.1.101, server: test.com, request: “POST /index.php HTTP/1.1”, upstream: “fastcgi://unix:/dev/shm/php-fcgi.sock:”,
host: “test.com”, referrer: “http://test.com/index.php”

调高这三项的值(主要是read和send两项,默认不配置的话Nginx会将超时时间设为60秒)之后,504错误也解决了。
而且这三项配置可以配置在http、server级别,也可以配置在location级别。担心影响其他应用的话,就配置在自己应用的location中。

注意:
以下部分是对FastCGI生效
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;

以下部分是对proxy_pass生效
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;

配置举例:
location ~ \.php$ {
root /home/test.com;
include fastcgi_params;
fastcgi_connect_timeout 180;
fastcgi_read_timeout 600;
fastcgi_send_timeout 600;
fastcgi_pass unix:/dev/shm/php-fcgi.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /home/cdai/test.com$fastcgi_script_name;
}

GlusterFS分布式文件系统-安装配置

GlusterFS是一个开源的分布式文件系统,用户可以使用多台服务器,并通过以太网或者Infiniband RDMA互联从而组成一个GlusterFS的集群。
GlusterFS集群对外提供NFS,CIFS和Gluster Native(通过FUSE进行挂载)的接口以便用户访问GlusterFS的存储池。
GlusterFS使用了弹性哈希算法来定位文件存储的位置。 由于使用了弹性哈希算法,GlusterFS不需要专门的Meta-Data Server来保存元数据,因此可以避免因为元数据服务器宕机导致的整个集群不可用。
也正是因为不需要元数据服务器,所以GlusterFS在多个挂载点同时进行数据读写的时候,其整体性能很突出。

官方网站:http://www.gluster.org/

下载:
fuse-2.9.3.tar.gz         #依赖于fuse
glusterfs-3.6.0.tar.gz #本文用的版本

准备2台机器,系统为centos6.5 64位。
IP地址               主机名
192.168.0.107   g1
192.168.0.136   g2

首先关闭iptables和selinux。
修改主机名,并添加hosts映射:
g1:
[root@localhost ~]# cat /etc/sysconfig/network
NETWORKING=yes
HOSTNAME=g1
[root@localhost ~]# hostname
g1
[root@localhost ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.0.107 g1
192.168.0.136 g2
g2:
[root@localhost ~]# cat /etc/sysconfig/network
NETWORKING=yes
HOSTNAME=g2
[root@localhost ~]# hostname
g2
[root@localhost ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.0.107 g1
192.168.0.136 g2

安装预编译环境:
[root@localhost ~]# yum install -y gcc gcc-c++ flex flex-devel bison bison-devel openssl openssl-devel libxml2 libxml2-devel
安装fuse:
[root@localhost ~]# cd fuse-2.9.3
[root@localhost fuse-2.9.3]# ./configure && make && make install
[root@localhost fuse-2.9.3]# cd

安装gluster:
[root@localhost ~]# cd glusterfs-3.6.0

[root@localhost glusterfs-3.6.0]# ./configure --prefix=/usr/local/glusterfs && make && make install

g1和g2均执行上面操作。

g1和g2启动gluster:
[root@localhost ~]# service glusterd start

添加集群:
[root@localhost ~]# ln -s /usr/local/glusterfs/sbin/gluster /usr/bin/gluster #做一个软链接方便执行命令
[root@localhost ~]# gluster peer probe g2 #在g1中将g2加入到gluster集群中,本机(g1)不需要加入。
peer probe: success. Probe on localhost not needed
查看集群信息:
[root@localhost ~]# gluster peer status
Number of Peers: 1

Hostname: g2
Uuid: c7aa664a-3161-4716-9f81-2dc4b4718fa1
State: Peer in Cluster (Connected) #已连接

剔除机器:
[root@localhost ~]# gluster peer detach g2
peer detach: success

创建卷:
[root@localhost ~]# gluster volume create test-volume replica 2 transport tcp g1:/data g2:/data force
volume create: test-volume: success: please start the volume to access data
test-volume 卷名 replica 副本数 transport 传输协议 g1:/data 服务器名及存储路径

启动卷:
[root@localhost ~]# gluster volume start test-volume
volume start: test-volume: success

查看卷:
[root@localhost ~]# gluster volume info
Volume Name: test-volume
Type: Replicate
Volume ID: 104d73c5-17f5-4150-a40d-b97cd78dd6bb
Status: Started
Number of Bricks: 1 x 2 = 2
Transport-type: tcp
Bricks:
Brick1: g1:/data
Brick2: g2:/data

客户端1挂载(同样安装fuse和glusterfs才能支持glusterfs文件系统):
[root@localhost ~]# mkdir /mnt/gfs
[root@localhost ~]# mount -t glusterfs g1:test-volume /mnt/gfs/
[root@localhost ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 77G 3.7G 70G 6% /
tmpfs 499M 0 499M 0% /dev/shm
g1:test-volume 77G 3.8G 70G 6% /mnt/gfs

客户端2挂载:
[root@localhost ~]# mkdir /mnt/gfs
[root@localhost ~]# mount -t glusterfs g2:test-volume /mnt/gfs
[root@localhost ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 77G 3.8G 70G 6% /
tmpfs 499M 0 499M 0% /dev/shm
g2:test-volume 77G 3.8G 70G 6% /mnt/gfs

可以看到g1和g2都支持挂载。

gluster支持的参数:
[root@localhost ~]# gluster help #查看参数

安装配置完成。