1.七层负载均衡-静态

环境准备

机器

lb

web01、web02

web01配置

[root@web01 ~]$ mkdir -p /code/proxy
[root@web01 ~]$ echo “proxy.dmxsp.com” `hostname` `hostname -I` >/code/proxy/index.html
[root@web01 ~]$ cat /code/proxy/index.html
proxy.dmxsp.com web01 10.0.0.45 172.16.1.45

写配置文件

[root@web01 ~]$ cat /etc/nginx/conf.d/proxy.dmxsp.com.conf
server {
listen 80;
server_name proxy.dmxsp.com;
location / {
root /code/proxy;
index index.html;
}
}

检查语法

[root@web01 ~]$ nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

重启nginx

[root@web01 ~]$ systemctl reload nginx.service

命令行测试

[root@web01 ~]$ curl -H Host:proxy.dmxsp.com 10.0.0.45
proxy.dmxsp.com web01 10.0.0.45 172.16.1.45

web02配置

[root@web02 ~]$ mkdir -p /code/proxy
[root@web02 ~]$ echo “proxy.dmxsp.com” `hostname` `hostname -I` >/code/proxy/index.html
[root@web02 ~]$ cat /code/proxy/index.html
proxy.dmxsp.com web02 10.0.0.145 172.16.1.145

写配置文件

[root@web02 ~]$ cat /etc/nginx/conf.d/proxy.dmxsp.com.conf
server {
listen 80;
server_name proxy.dmxsp.com;
location / {
root /code/proxy;
index index.html;
}
}

检查语法

[root@web01 ~]$ nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

重启nginx

[root@web01 ~]$ systemctl reload nginx.service

命令行测试

[root@web02 ~]$ curl -H Host:proxy.dmxsp.com 10.0.0.145
proxy.dmxsp.com web02 10.0.0.145 172.16.1.145

lb配置

upstream模块

Syntax upstream name { … }
Default
Context http

写配置文件

[root@lb ~]$ cat /etc/nginx/conf.d/proxy.dmxsp.com.conf
upstream dmxsp {
server 10.0.0.45:80;
server 10.0.0.145:80;
}
server {
listen 80;
server_name proxy.dmxsp.com;
location / {
proxy_pass http://dmxsp;
include proxy_params;
}
}

检查语法

[root@lb ~]$ nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

重启nginx

[root@lb ~]$ systemctl reload nginx.service

页面测试

2.七层负载均衡-动态

web01、02准备

[root@web01 ~]$ cat /etc/nginx/conf.d/blog.wordpress.com.conf
server {
listen 80;
server_name blog.wordpress.com;
root /code/wordpress;
location / {
index index.html index.php;
}

location ~ \.php {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}

[root@web02 ~]$ cat /etc/nginx/conf.d/blog.wordpress.com.conf
server {
listen 80;
server_name blog.wordpress.com;
root /code/wordpress;
location / {
index index.html index.php;
}

location ~ \.php {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}

bl配置文件

[root@lb ~]$ cat /etc/nginx/conf.d/web.wordpress.com.conf
upstream wordpress {
server 10.0.0.45:80;
server 10.0.0.145:80;
}
server {
listen 80;
server_name blog.wordpress.com;
location / {
proxy_pass http://wordpress;
include proxy_params;
}
}

检查语法

[root@lb ~]$ nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

重启nginx

[root@lb ~]$ systemctl reload nginx.service

测试

wireshark抓包

过滤条件 http and ( ip.dst == 10.0.0.45 or ip.dst == 10.0.0.145 )

ip.addr 过滤ip
ip.dst 目标ip是….
ip.src 源ip是…..

3.动静分离

lb配置

[root@lb ~]$ cat /etc/nginx/conf.d/web.wordpress.com.conf
upstream wordpress {
server 10.0.0.45:80;
}
upstream wordpress_jt {
server 10.0.0.145:80;
}
server {
listen 80;
server_name web.wordpress.com;
location / {
proxy_pass http://wordpress;
include proxy_params;
}
location ~ \.php$ {
proxy_pass http://wordpress;
include proxy_params;
}
location ~ \.(jpg|png|bmp|jpeg|gif|ico|js|css)$ {
proxy_pass http://wordpress_jt;
include proxy_params;
}
}

测试

4.调度算法

静态算法

rr 轮询算法: 1一次1个
wrr 加权轮询:(后端节点 服务器配置不同)

web01 1c1g
web02 1c1g
web03 4c8g

upstream blog {
server 10.0.0.45:80 weight=1;
server 10.0.0.145:80 weight=1;
server 10.0.0.235:80 weight=4;
}

动态算法

least_conn

最小连接数,负载均衡会定期检查后端服务器的连接数

指定upstream使用的负载均衡算法,将请求传递到活动连接数最少的服务器,并考虑服务器的权重

如果有多个这样的服务器,则结合wrr和least_conn一起调度

upstream blog {
least_conn;
server 10.0.0.45:80 weight=1;
server 10.0.0.145:80 weight=1;
server 10.0.0.235:80 weight=4;
}

ip_hash

对用户客户端ip进行hash,每次用户都会访问同一台服务器

好处: 解决用户登录状态问题(会话共享/登录会话)
缺点: 导致后端节点负载不均

upstream blog {
ip_hash;
server 10.0.0.45:80 weight=1;
server 10.0.0.145:80 weight=1;
server 10.0.0.235:80 weight=1;
}

url_hash

对应用户请求中的url进行hash,每次用户访问相同的url,访问相同的后端节点

应用场景: 配置缓存服务器,让用户指定的url/uri,访问缓存服务器

upstream blog {
hash $requst_uri; #对指定的变量进行hash
server 10.0.0.45:80 weight=1;
server 10.0.0.145:80 weight=1;
server 10.0.0.235:80 weight=1;
}

5.upstream模块配置

upstream 模块中的 server可用的参数

Syntax server address [parameters]
Default
Context upstream

server中可用的参数

weight 设置权重
max_conns 设置某个节点最大连接数
max_fails 设置nginx负载均衡检查后端节点失败次数 3 次(一般公司) 10次(CDN)
fail_timeout 超过最大失败次数后,经过fail_timeout时间,再次检查节点是否可用 默认10秒
backup 设置为备用模式,其他节点都挂了的时候启动backup服务器
down 处于关闭状态,一般用来指定服务器(处于维护状态)

写配置文件

[root@lb ~]$ cat /etc/nginx/conf.d/proxy.dmxsp.com.conf
upstream dmxsp {
server 10.0.0.45:80 weight=1 max_fails=3 fail_timeout=20;
server 10.0.0.145:80 weight=1 max_fails=3 fail_timeout=20;
}
server {
listen 80;
server_name proxy.dmxsp.com;
location / {
proxy_pass http://dmxsp;
include proxy_params;
}
}

测试

[root@lb ~]$ for n in {1..10000};do curl -H Host:proxy.dmxsp.com 10.0.0.63 ; date +%T;sleep 1 ; done
proxy.dmxsp.com web01 10.0.0.45 172.16.1.45
17:25:45
proxy.dmxsp.com web02 10.0.0.145 172.16.1.145
17:25:46
proxy.dmxsp.com web01 10.0.0.45 172.16.1.45
17:25:47
proxy.dmxsp.com web02 10.0.0.145 172.16.1.145
17:25:48
proxy.dmxsp.com web01 10.0.0.45 172.16.1.45
17:25:49
proxy.dmxsp.com web02 10.0.0.145 172.16.1.145
17:25:50
proxy.dmxsp.com web01 10.0.0.45 172.16.1.45
17:25:51
proxy.dmxsp.com web02 10.0.0.145 172.16.1.145
17:25:52
proxy.dmxsp.com web01 10.0.0.45 172.16.1.45
17:25:53

6.负载均衡与会话保持

什么是会话保持,有什么作用

会话保持是指在负载均衡器上有一种机制,在作负载均衡的同时,还保证同一用户相关连的访问请求会被分配到同一台服务器上。
会话保持有什么作用呢,举例说明一下
如果有一个用户访问请求被分配到服务器A,并且在服务器A登录了,并且在很短的时间,这个用户又发出了一个请求,如果没有会话保持功能的话,这个用户的请求很有可能会被分配到服务器B去,这个时候在服务器B上是没有登录的,所以你要重新登录,但是用户并不知道自己的请求被分配到了哪里,用户的感觉就是登录了,怎么又要登录,用户体验很不好。
还有你在淘宝上面买东西,从登录=》拍得东西=》添加地址=》付款,这是一个一系列的过程,也可以理解成一次操作过程,所有这一系列的操作过程都应当由一台服务器完成,而不能被负载均衡器分配到不同的服务器上。
会话保持都会有时间的限制(映射到固定某一台的服务器除外,如:ip_hash),各种负载均衡工具都会提供这种会话保持时间的设置,LVS,apache等。连php语言都提供了会话保持时间的设定session.gc_maxlifetime
会话保持时间的设定要大于session生存时间的设定,这样可以减少需要同步session的情况,但是不能杜绝。所以同步session还是要做的。

session同步

为什么要进行session同步,说会话保持的时候已经提到了。具体方法请参考web集群时session同步的3种方法

在做了web集群后,你肯定会首先考虑session同步问题,因为通过负载均衡后,同一个IP访问同一个页面会被分配到不同的服务器上,如果session不同步的话,一个登录用户,一会是登录状态,一会又不是登录状态。所以本文就根据这种情况给出三种不同的方法来解决这个问题

利用数据库同步session

在做多服务器session同步时我没有用这种方法,如果非要用这种方法的话,我想过二种方法:

用一个低端电脑建个数据库专门存放web服务器的session,或者,把这个专门的数据库建在文件服务器上,用户访问web服务器时,会去这个专门的数据库check一下session的情况,以达到session同步的目的。

这种方法是把存放session的表和其他数据库表放在一起,如果mysql也做了集群了话,每个mysql节点都要有这张表,并且这张session表的数据表要实时同步。

说明:用数据库来同步session,会加大数据库的负担,数据库本来就是容易产生瓶颈的地方,如果把session还放到数据库里面,无疑是雪上加霜。上面的二种方法,第一点方法较好,把放session的表独立开来,减轻了真正数据库的负担

利用cookie同步session

session是文件的形势存放在服务器端的,cookie是文件的形势存在客户端的,怎么实现同步呢?方法很简单,就是把用户访问页面产生的session放到cookie里面,就是以cookie为中转站。你访问web服务器A,产生了session把它放到cookie里面了,你访问被分配到web服务器B,这个时候,web服务器B先判断服务器有没有这个session,如果没有,在去看看客户端的cookie里面有没有这个session,如果也没有,说明session真的不存,如果cookie里面有,就把cookie里面的sessoin同步到web服务器B,这样就可以实现session的同步了。

说明:这种方法实现起来简单,方便,也不会加大数据库的负担,但是如果客户端把cookie禁掉了的话,那么session就无从同步了,这样会给网站带来损失;cookie的安全性不高,虽然它已经加了密,但是还是可以伪造的

利用memcache同步session

memcache可以做分布式,如果没有这功能,他也不能用来做session同步。他可以把web服务器中的内存组合起来,成为一个”内存池”,不管是哪个服务器产生的sessoin都可以放到这个”内存池”中,其他的都可以使用。

优点:以这种方式来同步session,不会加大数据库的负担,并且安全性比用cookie大大的提高,把session放到内存里面,比从文件中读取要快很多。

缺点:memcache把内存分成很多种规格的存储块,有块就有大小,这种方式也就决定了,memcache不能完全利用内存,会产生内存碎片,如果存储块不足,还会产生内存溢出。

会话共享-phpmyadmin

环境准备

lb

web01、web02

phpmyadmin官网

安装phpmyadmin

[root@web01 ~]$unzip phpMyAdmin-5.2.0-all-languages.zip

[root@web01 ~]$mv phpMyAdmin-5.2.0-all-languages /code/phpmyadmin

web01、02配置文件

[root@web01 ~]$ cat /etc/nginx/conf.d/blog.phpmyadmin.com.conf
server {
listen 80;
server_name blog.phpmyadmin.com;
root /code/phpmyadmin;
location / {
index index.html index.php;
}

location ~ \.php {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}

修改phpmyadmin文件

[root@web01 ~]$ cd /code/phpmyadmin/
[root@web01 /code/phpmyadmin]$ cp config.sample.inc.php config.inc.php
[root@web01 /code/phpmyadmin]$ vim +30 config.inc.php

$cfg[‘Servers’][$i][‘host’] = ‘172.16.1.26’;

页面访问

解决方案

[root@web01 /code/phpmyadmin]$ chown -R nginx.nginx /var/lib/php/session

负载均衡

配置文件

[root@lb ~]$ cat /etc/nginx/conf.d/blog.phpmyadmin.com.conf
upstream php {
server 10.0.0.45:80;
server 10.0.0.145:80;
}
server {
listen 80;
server_name blog.phpmyadmin.com ;
location / {
proxy_pass http://php;
include proxy_params;
}
}

页面登录时会发现一直在登录界面进不去

解决方案一

ip_hash(每次用户都会访问同一台服务器缺点,导致后端节点负载不均)

配置文件

[root@lb ~]$ cat /etc/nginx/conf.d/blog.phpmyadmin.com.conf
upstream php {
ip_hash;
server 10.0.0.45:80;
server 10.0.0.145:80;
}
server {
listen 80;
server_name blog.phpmyadmin.com ;
location / {
proxy_pass http://php;
include proxy_params;
}
}

解决方案二

redis

数据库安装redis

[root@mysqldb ~]$ yum install -y redis

修改配置文件

[root@mysqldb ~]$ vim /etc/redis.conf

[root@mysqldb ~]$ grep ^bind -n /etc/redis.conf
61:bind 127.0.0.1 172.16.1.26 10.0.0.26

启动

[root@mysqldb ~]$ systemctl restart redis.service

查看端口是否启动

[root@mysqldb ~]$ ss -lntup |grep redis
tcp LISTEN 0 128 10.0.0.26:6379 *:* users:((“redis-server”,pid=11134,fd=6))
tcp LISTEN 0 128 172.16.1.26:6379 *:* users:((“redis-server”,pid=11134,fd=5))
tcp LISTEN 0 128 127.0.0.1:6379 *:* users:((“redis-server”,pid=11134,fd=4))

修改web01、02配置文件php.ini

[root@web01 ~]$ grep -m 2 -n ^session. /etc/php.ini
1231:session.save_handler = redis
1264:session.save_path = “tcp://172.16.1.26:6379”

;session.save_path = “tcp://172.16.1.26:6379?auth=123“ 如果redis存在密码,使用该方式

注释默认的配置

[root@web01 ~]$ tail -4 /etc/php-fpm.d/www.conf
;php_value[session.save_handler] = files
;php_value[session.save_path] = /var/lib/php/session
php_value[soap.wsdl_cache_dir] = /var/lib/php/wsdlcache

重启

[root@web01 ~]$ systemctl reload php-fpm

页面测试

解决方案

[root@web01 ~]$ yum install php72w-pecl-redis.x86_64

redis查看共享

[root@mysqldb ~]$ redis-cli
127.0.0.1:6379> keys *
1) “PHPREDIS_SESSION:3ab0ca7566c75c1c2d1940bd4b086097”
2) “PHPREDIS_SESSION:6cb72dca399147fc2487ab8a5f9113d9”
3) “PHPREDIS_SESSION:1d87fe3424f0b78e1d3fb407ce31aeda”
4) “PHPREDIS_SESSION:98cc7553f81c4c4b868e60023df06b1a”

7.基于URI转发

web01配置

[root@web01 ~]$ mkdir -p /code/uri/static
[root@web01 ~]$ echo web01 static > /code/uri/static/index.html

[root@web01 ~]$ cat /etc/nginx/conf.d/dmxsp.uri.com.conf
server {
listen 80;
server_name dmxsp.uri.com;
root /code/uri;
location /static {
index index.html;
}
}

web02配置

[root@web02 ~]$ mkdir -p /code/uri/dong
[root@web02 ~]$ echo web02 dong > /code/uri/dong/index.html

[root@web02 ~]$ cat /etc/nginx/conf.d/dmxsp.uri.com.conf
server {
listen 80;
server_name dmxsp.uri.com;
root /code/uri;
location /dong {
index index.html;
}
}

测试

[root@lb ~]$ curl -H Host:dmxsp.uri.com 10.0.0.45/static/
web01 static
[root@lb ~]$ curl -H Host:dmxsp.uri.com 10.0.0.145/dong/
web02 dong

lb配置

[root@lb ~]$ cat /etc/nginx/conf.d/dmxsp.uri.com.conf
upstream static {
server 10.0.0.45:80;
}
upstream dong {
server 10.0.0.145:80;
}

server {
listen 80;
server_name dmxsp.uri.com;
location / {
proxy_pass http://static;
include proxy_params;
}
location /static {
proxy_pass http://static;
include proxy_params;
}
location /dong {
proxy_pass http://dong;
include proxy_params;
}
}

测试

[root@lb ~]$ curl -H Host:dmxsp.uri.com 10.0.0.63/static/
web01 static
[root@lb ~]$ curl -H Host:dmxsp.uri.com 10.0.0.63/dong/
web02 dong

8.基于user_agent转发

lb配置

[root@lb ~]$ cat /etc/nginx/conf.d/dmxsp.uri.com.conf
upstream static {
server 10.0.0.45:80;
}
upstream dong {
server 10.0.0.145:80;
}

server {
listen 80;
server_name dmxsp.uri.com;
location / {
if ($http_user_agent ~* “android|iphone|ipad”) {
proxy_pass http://static;
}
if ($http_user_agent ~* MSIE ) {
return 200 “please do not use ie”;
}
proxy_pass http://dong;
include proxy_params;
}
}

9.负载均衡多级代理及多级代理真实IP

一级代理

lb配置

[root@lb ~]$ vim /etc/nginx/conf.d/3log.dmxsp.com.conf
server {
listen 80;
server_name 3log.dmxsp.com;
location / {
proxy_pass http://10.0.0.45;
include proxy_params;
}
}

二级代理

web01配置

[root@web01 ~]$ vim /etc/nginx/conf.d/3log.dmxsp.com.conf
server {
listen 80;
server_name 3log.dmxsp.com;
location / {
proxy_pass http://10.0.0.145;
}
}

web02 web服务

[root@web02 ~]$ vim /etc/nginx/conf.d/3log.dmxsp.com.conf
server {
listen 80;
server_name 3log.dmxsp.com;
root /code/3log;
location / {
index index.php;
}
location ~ \.php {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}

真实iphttp_realip_module

配置文件

server {
listen 80;
server_name 3log.dmxsp.com;
root /code/3log;
set_real_ip_from 10.0.0.63;
set_real_ip_from 10.0.0.45;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
location / {
index index.php;
}
location ~ \.php {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}

set_real_ip_from 10.0.0.45;:指定代理的ip地址
set_real_ip_from 10.0.0.63;:指定代理的ip地址
real_ip_header X-Forwarded-For;:真实的客户端ip地址记录再来 XFF头中.
real_ip_recursive on;:在XFF头中把代理的ip排除掉

proxy_params配置文件书写

[root@lb ~]$ cat /etc/nginx/proxy_params
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;

proxy_connect_timeout 30;
proxy_read_timeout 60;
proxy_send_timeout 60;

proxy_buffering on;
proxy_buffer_size 8k;
proxy_buffers 4 64k;

作者 dmxsp

发表回复

您的电子邮箱地址不会被公开。