1、一级调度器;

   选择使用工作在四层的LVS。因为它工作在内核空间。它的调度效率要比七层调度器高几百倍。

它直接面向用户的请求。

2、二级调度器;

  选择使用工作在七层的:haproxy。因为它工作在七层,能够识别用户请求的资源是什么,方便做访问控制。

如:

  根据用户请求的资源类别做动静分离。请求动态内容由动态服务器响应,静态资源由静态服务器响应。这样大大提高动态服务器处理动态内容的效率。

  当用户上传数据时,把用户的请求调度到专门服务用户上传数据的服务器组。

拓扑图如下:

实现两级调度 Discuz! 论坛服务器_第1张图片

地址使用情况如下:

LVS 的VIP 10.10.60.22

      DIP 192.168.60.99

keepalived 双主模型的流动VIP:192.168.60.78(RIP) 

                     流动VIP: 192.168.60.55(RIP)

server1.9527.com:172.16.0.88

server2.9527du.com:172.16.0.99

dataserver.9527du.com:172.16.0.44


一、解决两台Discuz!论坛服务器的非结构化数据的共享

使用:rsync + inotify 解决两台Diacuz!论坛服务器数据共享问题。

1、rsync 的服务器的设置

创建rsync服务器输出的存储空间

[root@server1 /]# mkdir we

因为rsync工作在服务器模式要为其提供配置文件,配置文件如下:

[root@server1 ~]# cat /etc/rsyncd.conf
uid = nobody
gid = nobody
use chroot = no
max connections = 10             # 最大并发连接数
strict modes = yes               # 当启用基于口令认证客户端时,是否检查口令文件的权限
pid file = /var/run/rsyncd.pid
log file = /var/log/rsyncd.log   # 日志文件的输出路径

[web]                            # rsync服务器输出的存储空间叫啥名
path = /web                      # 定义rsync服务器输出的存储空间的位置
ignore errors  =yes              # 在数据传输中,出现错误是否忽略继续传输数据
read only = no                   # 允许客户端下载数据(从rsync服务器拉取数据)
write only = no                  # 允许客户端上传数据(往rsync服务器推送数据)

hosts allow = 172.16.0.0/24      # 允许访问rsync服务器的客户端地址
hosts deny = *                   # 只允许hostsallow指令定义的客户端访问,其它的都不允许

list = false                      # 当客户端请求服务器输出的存储空间列表时,是否列出来。
uid = root
gid = root

2、rsync的服务端设置

(1)、安装inotify

[root@server2 /]# mkdir data
[root@server2 admin]# tar -xf inotify-tools-3.14.tar.gz
[root@server2 admin]# cd inotify-tools-3.14
[root@server2 inotify-tools-3.14]# ./configure --prefix=/usr/local/inotify
[root@server2 inotify-tools-3.14]# make && make install

(2)、创建监控脚本,当/data文件系统中有:delete、move、modify、create事件发生,就触发rsync客户端推送数据到rsync服务器输出的存储空间。

脚本如下:

[root@server2 ~]# vim inotify.sh
#/bin/bash
# rsync服务器
rsyncServer=172.16.0.88
#初监控的文件系统(也就是同步数据源)
src=/data/
#远程rsync服务器导出的存储空间
dst=web
#一开始就进行一次数据同步操作
rsync -azrtopg --delete $src $rsyncServer::$dst

/usr/local/inotify-tools/bin/inotifywait -mrq  -e create,move,delete,modify  $src | while read files;do
   rsync -azrtopg --delete $src $rsyncServer::$dst
done

给脚本添加执行权限

[root@server2 ~]# chmod u+x inotify.sh
[root@server2 ~]# ll inotify.sh
-rwxr--r-- 1 root root 389 Sep 19 11:46 inotify.sh

3、测试rsync + inotify 是否能够实现数据实时同步

(1)、启动rsync服务端

让rsync服务以实时守护进程方式工作

[root@server1 ~]# rsync --daemon --config=/etc/rsyncd.conf -4

查看rsync服务监听的端口

[root@server1 ~]# netstat -anptl | grep rsync
tcp        0      0 0.0.0.0:873                 0.0.0.0:*                   LISTEN      3480/rsync

(2)、以后台方式启动rsync客户端监控脚本

[root@server2 ~]# ./inotify.sh &
[1] 6629

(3)、测试/data文件系统那生下述事件是否会向rsync服务器推送数据

测试当/data文件系统发生create事件,是否能够实现数据同步

[root@server2 data]# touch test.txt
[root@server2 data]# ssh 172.16.0.88 'hostname;ls -l /web '
server1.9527du.com
total 4
-rw-r--r-- 1 root root 0 Sep 19 11:56 test.txt

说明:

    从上述结果可以看出,当/data文件系统中有create事件发生时,rsync客户端会向rsync输出的存空间推送数据。


测试当/data文件系统发生modify 事件,是否能够实现数据同步

[root@server2 data]# echo "test inotify is ok ?" > test.txt
[root@server2 data]# ssh 172.16.0.88 'hostname;cat /web/test.txt '
server1.9527du.com
test inotify is ok ?

说明:

    从上述结果可以看出,当/data文件系统中有modify事件发生时,rsync客户端会向rsync输出的存空间推送数据。


测试当/data文件系统发生move事件,是否能够实现数据同步

[root@server2 data]# mkdir test
[root@server2 data]# mv test.txt test
[root@server2 data]# ssh 172.16.0.88 'hostname;tree /web/ '
server1.9527du.com
/web/
|-- 172.16.0.88
`-- test
    `-- test.txt

1 directory, 2 files

说明:

    从上述结果可以看出,当/data文件系统中有move事件发生时,rsync客户端会向rsync输出的存空间推送数据。


测试当/data文件系统发生delete事件,是否能够实现数据同步

[root@server2 data]# rm -rf test/
[root@server2 data]# ssh 172.16.0.88 'hostname;ls -l /web '
server1.9527du.com

说明:

    从上述结果可以看出,当/data文件系统中有move事件发生时,rsync客户端会向rsync输出的存空间推送数据。


inotify+rsync已经能够实现数据实现同步。


二、由于部署的是Discuz!论坛程序是由php语言开发的,提供的是动态页面程序 ,所以这里提供LAMP平台运行Discuz!应用程序。

这里选择使用rpm包安装httpd和php。php以模块的方式与httpd结合。数据库做为单台服务器(172.16.0.44)

<一>、安装数据库

1、创建数据库数据目录的存放位置;

使用lvm逻辑卷作为数据库数据目录存储位置。考滤到使用lvm的快照功能备份数据。

(1)、查看逻辑卷组是否有空闲空间

[root@dataserver /]# vgdisplay myvg | grep "PE[[:space:]]*\/[[:space:]]*Size"
  Alloc PE / Size       256 / 2.00 GiB
  Free  PE / Size       1024 / 8.00 GiB

(2)、创建lvm

[root@dataserver /]# lvcreate -L 2G -n mysqldata myvg
  Logical volume "mysqldata" created

(3)、格式化

[root@dataserver /]# mke2fs -t ext4 /dev/myvg/mysqldata ^C
[root@dataserver /]# echo $?
0

2、创建安装mysql数据时使用的用户

把mysql创建在系统用户

[root@dataserver /]# groupadd -r mysql
[root@dataserver /]# useradd -r -g mysql -s /sbin/nologin mysql
[root@dataserver /]# id mysql
uid=403(mysql) gid=403(mysql) groups=403(mysql)

3、挂载数据目录,并创建mysql目录用为数据库的datadir.

(1)、创建挂载点

[root@dataserver /]# mkdir  /mydata

(2)、编辑/etc/fstab文件,开机的时候可以自动挂载

[root@dataserver /]# vim /etc/fstab
/dev/mapper/myvg-mysqldata /mydata              ext4    defaults        0 0

(3)、挂载

[root@dataserver /]# mount -a
[root@dataserver /]# mount | grep mysqldata
/dev/mapper/myvg-mysqldata on /mydata type ext4 (rw)

(4)、创建mysql目录

[root@dataserver /]# mkdir /mydata/mysql

(5)、把该目录的属主属组修改成:mysql

[root@dataserver /]# chown mysql:mysql /mydata/mysql/
[root@dataserver /]# ll -d  /mydata/mysql/
drwxr-xr-x 2 mysql mysql 4096 Sep 19 12:28 /mydata/mysql/

2、安装数据库

(1)、把mysql的二进制程序安装包解压到指定目录下

[root@dataserver user]# tar -xf mysql-5.5.22-linux2.6-i686.tar.gz -C /usr/local/
[root@dataserver user]# cd /usr/local/

做软连接

[root@dataserver local]# ln -sv mysql-5.5.22-linux2.6-i686 mysql
`mysql' -> `mysql-5.5.22-linux2.6-i686'
[root@dataserver local]# ll mysql
lrwxrwxrwx 1 root root 26 Sep 19 12:33 mysql -> mysql-5.5.22-linux2.6-i686

(2)、初始化数据库

改变mysql的程序的属主属组为mysql,因为初始化数据库的时候,使用mysql用户运行一些程序。

[root@dataserver mysql]# chown -R  mysql:mysql ./*
[root@dataserver mysql]# ll
total 76
drwxr-xr-x  2 mysql mysql  4096 Sep 19 12:33 bin
-rw-r--r--  1 mysql mysql 17987 Mar  3  2012 COPYING
drwxr-xr-x  4 mysql mysql  4096 Sep 19 12:33 data
drwxr-xr-x  2 mysql mysql  4096 Sep 19 12:33 docs
drwxr-xr-x  3 mysql mysql  4096 Sep 19 12:33 include
-rw-r--r--  1 mysql mysql  7604 Mar  3  2012 INSTALL-BINARY
drwxr-xr-x  3 mysql mysql  4096 Sep 19 12:33 lib
drwxr-xr-x  4 mysql mysql  4096 Sep 19 12:33 man
.....

初始化数据库

[root@dataserver mysql]# ./scripts/mysql_install_db --datadir=/mydata/mysql/ --user=mysql
Installing MySQL system tables...
OK
Filling help tables...
OK

说明:

   从上述可以看出,初始化数据已经成功。

(3)、为启动数据库做准备工作

提供数据库运行所需的匹配文件

[root@dataserver mysql]# cp support-files/my-large.cnf /etc/mysql/my.cnf

在配置文件中设置数据库的数据目录的位置

[root@dataserver mysql]# vim /etc/mysql/my.cn
thread_concurrency = 2
datadir = /mydata/mysql/

提供LSB风格的启动脚本

[root@dataserver mysql]# cp support-files/mysql.server /etc/init.d/mysqld
[root@dataserver mysql]# ll /etc/init.d/mysqld
-rwxr-xr-x 1 root root 10650 Sep 19 12:37 /etc/init.d/mysqld

改变mysql的程序的属主为root。属组为mysql

[root@dataserver mysql]# chown -R root:mysql ./*
[root@dataserver mysql]# ll
total 76
drwxr-xr-x  2 root mysql  4096 Sep 19 12:33 bin
-rw-r--r--  1 root mysql 17987 Mar  3  2012 COPYING
drwxr-xr-x  4 root mysql  4096 Sep 19 12:33 data
drwxr-xr-x  2 root mysql  4096 Sep 19 12:33 docs
drwxr-xr-x  3 root mysql  4096 Sep 19 12:33 include
-rw-r--r--  1 root mysql  7604 Mar  3  2012 INSTALL-BINARY
drwxr-xr-x  3 root mysql  4096 Sep 19 12:33 lib
。。。

4、测试是否能够启动数据库

(1)、启动数据库

[root@dataserver mysql]# service mysqld start
Starting MySQL..                                           [  OK  ]

(2)、连接数据库给数据库设置密码

[root@dataserver mysql]# mysql
Welcome to the MySQL monitor.  Commands end with ; or \g.
......
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| test               |
+--------------------+
4 rows in set (0.00 sec)

根据需要删除安装数据库默认的用户

mysql> drop user 'root'@'dataserver.9527du.com';
mysql> drop user 'root'@'::1';
mysql> drop user ''@'dataserver.9527du.com';
mysql> drop user ''@'localhost';

给保留的用户设置密码

mysql> set password for 'root'@'localhost' = password('root');
mysql> set password for 'root'@'127.0.0.1' = password('root');

设置能够远程管理数据库的用户

mysql> grant all on *.* to 'admin'@'%.%.%.%' identified by 'admin';
Query OK, 0 rows affected (0.00 sec)

5、创建Discuz! 所用的数据库,并创建仅能操作使用Discuz!论坛的数据库的用户

(1)、创建Discuz!论坛使用的数据库

mysql> create database discuz;
Query OK, 1 row affected (0.00 sec)

(2)、创建并授权具有discuz数据库一切权限的用户discuz

mysql> grant all on  discuz.* to 'discuz'@'172.16.0.%' identified by 'discuz';
Query OK, 0 rows affected (0.00 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

修改后数据的用户如下:

mysql> select user,host,password from mysql.user;
+--------+------------+-------------------------------------------+
| user   | host       | password                                  |
+--------+------------+-------------------------------------------+
| root   | localhost  | *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B |
| root   | 127.0.0.1  | *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B |
| admin  | %.%.%.%    | *4ACFE3202A5FF5CF467898FC58AAB1D615029441 |
| discuz | 172.16.0.% | *B085E56614DFB3DF10A282ACE192776DE8BB4FA4 |
+--------+------------+-------------------------------------------+
4 rows in set (0.00 sec)

6、测试两台服务是否能够连接数据库

(1)、测试server1.9527du.com(172.16.0.88)

[root@server1 web]# mysql -udiscuz -h 172.16.0.44 -p
Enter password:
Welcome to the MariaDB monitor.  Commands end with ; or \g.
,。。。。。。

MySQL [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| discuz             |
| test               |
+--------------------+
3 rows in set (0.00 sec)

MySQL [(none)]>

说明:

    从上述结果,得知该服务器可以连接数据库了。

(2)、测试server2.9527du.com(172.16.0.99)

[root@server2 data]# mysql -udiscuz -h 172.16.0.44 -p
Enter password:
Welcome to the MariaDB monitor.  Commands end with ; or \g.
......
MySQL [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| discuz             |
| test               |
+--------------------+
3 rows in set (0.00 sec)

说明:

    从上述结果,得知该服务器可以连接数据库了。

数据库已经安装成功!!!


<二>、分别在两台主机安装httpd 和 php 


1、在server2.9527du.com(172.16.0.99)主机安装程序;

(1)、安装:httpd、php以及php也MySQL数据库交互的驱动 

[root@server2 html]# yum install httpd php php-mysql


(2)、启动httpd服务器,并测试; 

启动httpd服务

[root@server2 ~]# service  httpd start
Starting httpd:                                            [  OK  ]

提供测试页面

[root@server2 html]# vim test.php
 如果能够连接数据库就会输出:Success....
   else
      echo "Failure...";  ------> 如果不能够连接数据库就会输出:Failure...
?>

使用【curl】访问测试页

[root@server2 /]# curl  http://172.16.0.99/test.php
Success...

说明:

   连接数据库成功。

关闭数据库服务器再进行访问测试

[root@server2 /]# ssh 172.16.0.44 'hostname;service mysqld stop'
dataserver.9527du.com
Shutting down MySQL.[  OK  ]

[root@server2 /]# curl  http://172.16.0.99/test.php
Failure...

说明:

   server2.9527du.com的lamp平台已经搭建成功


2、在server1.9527du.com(172.16.0.88)主机安装程序;

(1)、安装:httpd、php以及php也MySQL数据库交互的驱动 

[root@server1 ~]# yum install php httpd php-mysql

(2)、复制远程主机172.16.0.88的测试页test.php到当前服务器

[root@server1 ~]# scp 172.16.0.99:/var/www/html/test.php /var/www/html/
test.php                                      100%  140     0.1KB/s   00:00

(3)、启动httpd服务

[root@server1 ~]# service  httpd start
Starting httpd:                                            [  OK  ]

(4)、访问测试lamp平台

使用【curl】命令访问测试页,看看是否能够与MySQL交互。

[root@server1 ~]# curl http://172.16.0.88/test.php
Failure...

说明:

     从测试结果看出,连接数据库失败。

开户数据库,再次访问测试页查看结果是否还是:Failure....

开启远程数据库服务

[root@server1 ~]# ssh 172.16.0.44 'hostname;service mysqld start'
dataserver.9527du.com
Starting MySQL..[  OK  ]

访问测试

[root@server1 ~]# curl http://172.16.0.88/test.php
Success...

说明:

   从上述测试结果得知server1.9527du.com 的lamp平台已经搭建成功。


到此为止,Discuz!论坛程序工作的环境已经准备好。


三、部署Discuz!论坛程序

提供的Discuz!论坛程序包:

                        Discuz_X2.5_SC_GBK.zip

部署方法:

       先在server2.9527du.com(172.16.0.9)主机部署安装好Discuz!论坛程序,再开启rsync + inotify 数据同步服务,把应用程序同步到server1.9527du.com(172.16.0.88)服务器。

1、在server2.9527du.com 部署Discuz!

(1)、解压

[root@server2 /data]# unzip Discuz_X2.5_SC_GBK.zip

(2)、修改httpd服务器的网页根目录位置

[root@server2 upload]# vim /etc/httpd/conf/httpd.conf
DocumentRoot "/data/upload"

    Options -Indexes FollowSymLinks
    AllowOverride None
    Order allow,deny
    Allow from all

(3)、重启 httpd服务

[root@server2 upload]# service httpd restart
Stopping httpd:                                            [  OK  ]
Starting httpd:                                            [  OK  ]

(4)、访问Discuz!进入安装引导页面,进行安装操作

如图:

实现两级调度 Discuz! 论坛服务器_第2张图片下一步:

实现两级调度 Discuz! 论坛服务器_第3张图片

下一步:

实现两级调度 Discuz! 论坛服务器_第4张图片

下一步:

实现两级调度 Discuz! 论坛服务器_第5张图片

安装完成:

实现两级调度 Discuz! 论坛服务器_第6张图片


2、开如rsync 服务,让Discuz!论坛程序同步到server1.9527du.com(172.16.0.88),并访问测试

(1)、修改该服务器的httpd服务的网页根目录。

[root@server1 /]# vim /etc/httpd/conf/httpd.conf
DocumentRoot "/web/upload"

    Options -Indexes FollowSymLinks
     AllowOverride None
      Order allow,deny
    Allow from all

(2)、重启httpd服务

[root@server1 /]# service httpd restart
Stopping httpd:                                            [  OK  ]
Starting httpd:                                            [  OK  ]

(3)、开启rsync服务器

[root@server1 /]# rsync --daemon --config=/etc/rsyncd.conf --ipv4
[root@server1 /]# netstat -anptl | grep rsync
tcp        0      0 0.0.0.0:873                 0.0.0.0:*                   LISTEN      3530/rsync

(4)、启动rsync客户端的inotify脚本,让它触动rsync客户端程序把数据推送到rsync服务器输出的存储空间。

[root@server2 ~]# ./inotify.sh &
[1] 3650

(5)、查看数据是否已经同步过去

[root@server2 ~]# ssh 172.16.0.88 'hostname;ls -l /web'
[email protected]'s password:
server1.9527du.com
total 9352
-rw-r--r--  1 root root 9522601 Sep 19 16:14 Discuz_X2.5_SC_GBK.zip
drwxr-xr-x  2 root root    4096 Oct 31  2012 readme
drwxr-xr-x 12 root root    4096 Oct 31  2012 upload
drwxr-xr-x  4 root root    4096 Oct 31  2012 utility

说明:

   从上述结果可以看出数据已经从172.16.0.99同步到172.16.0.88主机上去了。


(6)、通过访问172.16.0.88主机的Discuz!论坛程序,查看是否能够正常工作。

如下图:

实现两级调度 Discuz! 论坛服务器_第7张图片

说明:

    该台服务器已经能够正常工作了!!!!

四、配置haproxy调度两台Discuz!论坛服务器;

使用七层调度程序:haproxy来调度两台提供Discuz!论坛服务的服务器。

提供论坛服务的服务器要有两种类型的数据要处理:

1、结构化的数据;

   如:用户在Discuz!中注册的帐号和发的贴子,要保存在数据库中;

   使用数据库共享来解决。

2、非结构化的数据;

   如:用户上传的附件、图片要保存在文件系统中;


由于,使用两台服务器同时向外提供Discuz!论坛服务,所以两台服务器要共享上述的两种数据。上传两种数据的共享解决方案:

1、非结构数据的共享

   rsync + inotify 提供数据实时同步是单方向的数据共享解决方案。如果用户上传附件或图片时,被haproxy调度到server1.9527du.com(172.16.0.88)该服务器(也就是rsync的服务器端),当下一个用户访问Discuz!论坛时,被调度到server2.9527du.com(172.16.0.99)服务器(也就是rsync的客户端),是无法下载附件以及无法浏览刚才用户上传的图片的。

   所以,最好在用户上传附件或图片时,把它路由到server2.9527du.com服务器,再把数据同步到另一台服务器。

   根据客户端向服务器请求资源的方法,用户上传附件或图片,属于客户端向服务器发起POST请求。所以,这里使用七层调度器haproxy,接收用户的请求报文后,拆开请求报文分析http报文中请求资源的方法。haproxy根据请求方法把用户路由到不同的后端服务器。这就是haproxy的访问控制列表acl,

2、结构化数据的共享

   MySQL数据库解决结构化数据的共享。

(1)、配置haproxy

frontend main *:80
    acl  http_method method  -i  POST    -------> 设置访问控制列表,只有客户端使用POST方法向服务器请求资源,都符合该acl.
    use_backend updataserver  if http_method  ------> 如果用户的请求报文中,请求资源的方法是:POST。都把它路由到:updataserver定义的后端服务器中。
    default_backend webservers            ---------> 非POST方法的请求,都反它路由到webservers定义的后端服务器中。

backend    webservers        ---------> 定义后端服务器组的
    balance   roundrobin     --------->  调度方法
    server s1 172.16.0.88:80  check weight 1    ----> 后端服务器。
    server s2 172.16.0.99:80  check weight 1
  
    server b1 127.0.0.1:8080    ------> 为haproxy提供状态页。
    stats  enable
    stats  hide-version
    stats  uri /haproxy?stats
    stats  scope .
    stats  realm  HAPorxy\ Statistics
    stats  auth   admin:admin
    stats  admin  if TRUE      ------> 开户状态页的管理功能。

backend    updataserver        -------> 定义后端服务器组 
    balance   roundrobin
    server  s2 172.16.0.99:80 check

(2)、启动 haproxy 服务

[root@haproxy ~]# service haproxy start
Starting haproxy [ ok ]

(3)、访问上传附件或图片测试,是否能够把用户路由到指定的updataserver上传服务组中。

停止上传服务器

[root@haproxy ~]# ssh 172.16.0.99 'service httpd stop'
[email protected]'s password:
Stopping httpd: [  OK  ]

上传附件时候出现错误如图:

实现两级调度 Discuz! 论坛服务器_第8张图片

启动上传服务器,查看是否能够上传成功

[root@haproxy ~]# ssh 172.16.0.99 'service httpd start'
[email protected]'s password:
Starting httpd: [  OK  ]

如下图:

实现两级调度 Discuz! 论坛服务器_第9张图片

实现两级调度 Discuz! 论坛服务器_第10张图片

从上图可以看出,当用户使用,上传附件或图片时,已经能够,把用户请求路由至指定服务器172.16.0.99。

这样,通过innotify就可以把附件同步到server1.9527du.com(172.16.0.88)服务器了。


(4)、通过日志也可以查看用户向服务器请求资源时使用POST方法,把它路由到哪台服务器。

查看:server2.9527du.com(172.16.0.99)服务器的访问日志

[root@server2 ~]# ifconfig | grep "[[:space:]]*inet[[:space:]]*addr:[1][^2]"; echo "Total_POST= `cat  /var/log/httpd/access_log | grep "\" | wc -l`"
          inet addr:172.16.0.99  Bcast:172.16.255.255  Mask:255.255.0.0
Total_POST= 7

查看:server1.9527du.com(172.16.0.88)服务器的访问日志

[root@server1 ~]#  ifconfig | grep "[[:space:]]*inet[[:space:]]*addr:[1][^2]"; echo "Total_POST= `cat  /var/log/httpd/access_log | grep "\" | wc -l`"
          inet addr:172.16.0.88  Bcast:172.16.255.255  Mask:255.255.0.0
Total_POST= 0

说明:

    POST请求已经定向到 server2.9527du.com(172.16.0.99)服务器。


(5)、由于http协议是无状态的,要基于session的方式识别用户。由于使用haproxy做上游服务器的负载均衡,假如用户现在被调度到的上游服务器是:RealServer1,

用户一刷新页面,有可能用户的请求就会被haproxy重新调度到的上游服务器是:RealServer2.由于cookie信息是保存在RealServer1服务器的,这时候会提示用户输入

用户名和密码才可以登陆系统进行发贴等操作的。所以,使用调度器调度用户的请求,要考虑session保持的。意思是说,始终把用户的请求定向到同一个上游服务器。

在haproxy中实现session保持的方法有:

A、使用 source 调度访求;
   根据用户的来源地址做调度
B、基于cookie的绑定,实现session保持;
D、使用共享存储,存储所有用户的sesssion信息;

基于,现在用户上网的方式考滤和易用性,以及对haproxy负载均衡效果影响等方面考滤,这里使用:基于cookie绑定的方式,实现session的保持。

配置如下:

backend   webservers
   cookie webserver insert nocache  
   option  httpchk
   server  s1 172.16.0.99 cookie s1 check port 80 weight 1
   server  s2 172.16.0.88 cookie s2 check port 80 weight 1

如图:

实现两级调度 Discuz! 论坛服务器_第11张图片再次刷新访问

实现两级调度 Discuz! 论坛服务器_第12张图片

五、为了避免haproxy调度器成为单点故障,使用keepalived为其提供高可用。考滤到,资源的利用率把keepalived做成双主模型。

1、配置HA高可用服务,的准备工作。

使用两台主机基于主机名或IP地址都能够通讯

[root@node2 ~]# cat /etc/hosts
192.168.60.22   haproxy.9527du.com haproxy
192.168.60.128  haproxy2.9527du.com haproxy2

让新的主机名立即生效

[root@node2 ~]# hostname haproxy2.9527du.com

通过编辑配置文件,让主机名永久有效

[root@node2 ~]# vim /etc/sysconfig/network
HOSTNAME=haproxy2.9527du.com haproxy2

为了,操作方便把两台主机配置成基于ssh的密钥通讯

[root@haproxy2 ~]# ssh-keygen -t rsa
[root@haproxy2 ~]# ssh-copy-id -i /root/.ssh/id_rsa.pub 192.168.60.22
[root@haproxy ~]# ssh-copy-id -i /root/.ssh/id_rsa.pub 192.168.60.128
[root@haproxy ~]# ssh-keygen -t rsa

[root@haproxy2 ~]# scp /etc/hosts 192.168.60.22:/etc/
hosts                                         100%   83     0.1KB/s   00:00

要保证两个节点的时间同步

[root@haproxy2 ~]# hostname;date;ssh haproxy.9527du.com  -- 'hostname;date'
haproxy2.9527du.com
Sat Sep 20 13:16:56 CST 2014
haproxy.9527du.com
Sat Sep 20 13:16:11 CST 2014

2、配置文件如下:

(1)、为haproxy2.9527du.com主机提供配置文件

[root@haproxy2 ~]# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived

global_defs {  ----> 全局配置段。使用邮件接收keepalive的信息。可以通过监测节点的状态转换的管理员发自定义邮件:
              -----> notify_master “bash shell 脚本” 说明:当该节点从backup状态转为master状态,就执行双引号("")的脚本。
	      ------>notify_backup "bash shell 脚本"
	      ------>notify_fault "bash shell 脚本"
   notification_email {
    root@localhost
   }
   notification_email_from [email protected]
   smtp_server 192.168.60.128 -----> 邮件服务器的地址
   smtp_connect_timeout 30
}

vrrp_script chk_haproxy {  -----> 检测haproxy服务的脚本
   script "killall -0 haproxy"  -----> 通过向服务发送“0”信号检测服务是否在线
   interval 2   ---> 检测的时间间隔
   weight -5    ---> 当检测失败了,调整节点的分在先级的
   fall 2       ---> 当检测失败,检测两次都是失败的结果,才判断最终结果为失败的。为了避免误判。
   rise 1       ----> 检测结果从失败转为成功,只需要检测一次就可以确定最终结果
}

vrrp_instance VI_1 { -----> 定义vrrp实例为:VI_1。在该实例中,该节点是工作在BACKUP状态。
    state BACKUP     
    interface eth0
    virtual_router_id 53  -----> 虚拟路由ID
    priority 99 -----> 该节点在VRRP实例VI_1中拥有的优先级
    advert_int 1   -----> 每隔多长时间向vrrp实例的成员通告自己的优先级。
    authentication {  ----> vrrp实例VI_1的成员之间的认证
        auth_type PASS
        auth_pass 2222
    }
    virtual_ipaddress { ----->vrrp实例VT_1的流动IP
        192.168.60.78
    }
    track_script { 在vrrp实例VI_1中调用检测脚本chk_harproxy
        chk_haproxy
    }
    notify_master "/etc/init.d/haproxy  start"  ------> 当该节点的状态转为MASTER就执行后面的脚本
    notify_fault "/etc/init.d/haproxy stop"   --------> 当节点错误就会执行后面的脚本
}


vrrp_instance VI_3 { -----> 定义的又一个vrrp实例为:VI_3。 在该实例中,该节点是工作在MASTER状态。
    state MASTER
    interface eth0
    virtual_router_id 56
    priority 105  -------> 该节点在vrrp实例VT_3中拥有的优先级为:105
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress { ----> VRRP实例VT_3的流动VIP
        192.168.60.55
    }
    track_script {
        chk_haproxy
    }
    notify_master "/etc/init.d/haproxy  start"
    notify_fault "/etc/init.d/haproxy stop"
}

(2)、为haproxy.9527du.com 主机提供的配置文件

[root@haproxy ~]# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived

global_defs {
   notification_email {
    root@localhost
   }
   notification_email_from [email protected]
   smtp_server 192.168.60.22
   smtp_connect_timeout 30
}

vrrp_script chk_haproxy {
   script "killall -0 haproxy"
   interval 2
   weight -5
   fall 2
   rise 1
}

vrrp_instance VI_1 { ----> vrrp实例VI_1, 在该实例中开节点拥有的最高的优先级,它工作在MASTER状态
    state MASTER
    interface eth0
    virtual_router_id 53
    priority 105  -----> 在vrrp实例VT_1中,该节点拥有的优先级.
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 2222
    }
    virtual_ipaddress {
        192.168.60.78
    }
    track_script {
        chk_haproxy
    }
    notify_master "/etc/init.d/haproxy  start"
    notify_fault "/etc/init.d/haproxy stop"
}


vrrp_instance VI_3 { -----> vrrp实例VI_3,在该实例中,该节点工作在BACKUP状态。
    state BACKUP
    interface eth0
    virtual_router_id 56
    priority 99
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.60.55
    }
    track_script {
        chk_haproxy
    }
    notify_master "/etc/init.d/haproxy  start"
    notify_fault "/etc/init.d/haproxy stop"
}

3、启动测试

(1)、启动haproxy2.9527du.com节点

[root@haproxy2 ~]# service keepalived start
Starting keepalived:                                       [  OK  ]

(2)、查看配置的VIP

[root@haproxy2 ~]# ip add show eth0 | grep "[[:space:]]*inet[[:space:]]"
    inet 192.168.60.128/24 brd 192.168.60.255 scope global eth0
    inet 192.168.60.55/32 scope global eth0
    inet 192.168.60.78/32 scope global eth0

(3)、查看haproxy服务

[root@haproxy2 ~]# netstat  -anptl | grep haproxy
tcp        0      0 0.0.0.0:80                  0.0.0.0:*                   LISTEN      4890/haproxy     
tcp        0      1 172.16.0.1:54298        172.16.0.99:80              SYN_SENT    4890/haproxy  ------> haproxy 检测后端RealServer使用的方法。   
tcp        0      1 172.16.0.1:54297        172.16.0.99:80              SYN_SENT    4890/haproxy     
tcp        0      1 172.16.0.1:51605        172.16.0.88:80              SYN_SENT    4890/haproxy

(4)、启动haproxy.9527du.com 节点

[root@haproxy ~]# service keepalived start
Starting keepalived:                                       [  OK  ]

(5)、查看VI_1实例中,流动IP:192.168.60.78 是否流动到haproxy1.9527du.com节点,

[root@haproxy ~]# hostname; ip add show eth0 | grep "[[:space:]]*inet[[:space:]]"
haproxy.9527du.com
    inet 192.168.60.22/24 brd 192.168.60.255 scope global eth0
    inet 192.168.60.78/32 scope global eth0

说明:

    从上述结果,看得出,在VI_3实例,主节点已经获取到配置VIP的权限。

 也可以查看日志

[root@haproxy ~]# tail /var/log/messages
ep 21 14:10:57 haproxy Keepalived_vrrp[4034]: VRRP_Instance(VI_1) Transition to MASTER STATE  -----> 该节点向外通告自己的优先级
Sep 21 14:10:58 haproxy Keepalived_vrrp[4034]: VRRP_Instance(VI_1) Entering MASTER STATE  -----> 该节点处于 MASTER状态
Sep 21 14:10:58 haproxy Keepalived_vrrp[4034]: VRRP_Instance(VI_1) setting protocol VIPs. ----> 配置VIP
Sep 21 14:10:58 haproxy Keepalived_vrrp[4034]: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 192.168.60.78 ---> 向外发送ARP广播
Sep 21 14:10:58 haproxy Keepalived_healthcheckers[4033]: Netlink reflector reports IP 192.168.60.78 added
Sep 21 14:10:58 127.0.0.1 haproxy[4052]: Proxy main started.
Sep 21 14:10:58 127.0.0.1 haproxy[4052]: Proxy webservers started.
Sep 21 14:10:58 127.0.0.1 haproxy[4052]: Proxy updataserver started.
Sep 21 14:11:03 haproxy Keepalived_vrrp[4034]: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 192.168.60.78

(6)、查看haproxy服务

[root@haproxy ~]# netstat  -anptl | grep haproxy
tcp        0      0 0.0.0.0:80                  0.0.0.0:*                   LISTEN      4053/haproxy

(7)、查看另一台主机

[root@haproxy ~]# ssh 192.168.60.128 'hostname; netstat -anptl | grep haproxy'
haproxy2.9527du.com
tcp        0      0 0.0.0.0:80                  0.0.0.0:*                   LISTEN      2035/haproxy  
tcp        0      1 172.16.13.1:38386           172.16.0.99:80              SYN_SENT    2035/haproxy  
tcp        0      1 172.16.13.1:43858           172.16.0.88:80              SYN_SENT    2035/haproxy  
tcp        0      1 172.16.13.1:38387           172.16.0.99:80              SYN_SENT    2035/haproxy

4、再进行测试

(1)、关闭server2.9527du.com(192.168.60.128)的keepalived服务器查看VI_3实例的:VIP,192.168.60.55 是否流动过来

关闭keepalived服务

 [root@haproxy ~]# ssh 192.168.60.128 'hostname;service keepalived stop'
haproxy2.9527du.com
Stopping keepalived: [  OK  ]

查看实例VI_3的VIP是否配置上

[root@haproxy ~]#  ip add show eth0 | grep "[[:space:]]*inet[[:space:]]"
    inet 192.168.60.22/24 brd 192.168.60.255 scope global eth0
    inet 192.168.60.78/32 scope global eth0
    inet 192.168.60.55/32 scope global eth0

查看是否影响当前主机的haproxy服务

[root@haproxy ~]# netstat  -anplt | grep haproxy
tcp        0      0 0.0.0.0:80                  0.0.0.0:*                   LISTEN      2193/haproxy  
tcp        0      1 172.16.0.2:50880            172.16.0.99:80              SYN_SENT    2193/haproxy  
tcp        0      1 172.16.0.2:50879            172.16.0.99:80              SYN_SENT    2193/haproxy

(2)、启动;server2.9527du.com(192.168.60.22)的keepalived服务器,关闭server1.9527du.com的keepalived服务,查看VI_1实例的VIP:192.168.60.78 是否流动过来

[root@haproxy2 ~]# service keepalived start
Staring keepalived: [ ok ]

停止haproxy.9527du.com的keepalived服务。

[root@haproxy2 ~]# ssh 192.168.60.22 'hostname;service keepalived stop'
haproxy.9527du.com
Stopping keepalived: [  OK  ]

查看实例VI_1的VIP是不流动过来

[root@haproxy2 ~]# ip add show eth0 | grep "[[:space:]]*inet[[:space:]]"
    inet 192.168.60.128/24 brd 192.168.60.255 scope global eth0
    inet 192.168.60.55/32 scope global eth0
    inet 192.168.60.78/32 scope global eth0

查看是否影响当前节点的haproxy服务

[root@haproxy2 ~]# netstat -anptl | grep haproxy
tcp        0      0 0.0.0.0:80                  0.0.0.0:*                   LISTEN      2035/haproxy
tcp        0      1 172.16.13.1:38519           172.16.0.99:80              SYN_SENT    2035/haproxy
tcp        0      1 172.16.13.1:38520           172.16.0.99:80              SYN_SENT    2035/haproxy
tcp        0      1 172.16.13.1:43991           172.16.0.88:80              SYN_SENT    2035/haproxy

说明:

    两个流动VIP已经能够随着节点的状态转变在两个节点流动。

5、启动haproxy.9527.com节点后,查看两个节点的VIP以及haproxy服务。

[root@haproxy2 ~]# ssh 192.168.60.22 'hostname;service keepalived start;ip add show eth0 | grep "[[:space:]]*inet[[:space:]]";netstat  -anptl | grep haproxy'
haproxy.9527du.com
    inet 192.168.60.22/24 brd 192.168.60.255 scope global eth0
    inet 192.168.60.78/32 scope global eth0
tcp        0      0 0.0.0.0:80                  0.0.0.0:*                   LISTEN      2193/haproxy      
tcp        0      1 172.16.0.2:51197            172.16.0.99:80              SYN_SENT    2193/haproxy      
tcp        0      1 172.16.0.2:51196            172.16.0.99:80              SYN_SENT    2193/haproxy
[root@haproxy2 ~]# hostname;ip add show eth0 | grep "[[:space:]]*inet[[:space:]]";netstat -anptl | grep haproxy
haproxy2.9527du.com
    inet 192.168.60.128/24 brd 192.168.60.255 scope global eth0
    inet 192.168.60.55/32 scope global eth0
tcp        0      0 0.0.0.0:80                  0.0.0.0:*                   LISTEN      2035/haproxy      
tcp        0      1 172.16.13.1:38728           172.16.0.99:80              SYN_SENT    2035/haproxy      
tcp        0      1 172.16.13.1:44200           172.16.0.88:80              SYN_SENT    2035/haproxy      
tcp        0      1 172.16.13.1:38729           172.16.0.99:80              SYN_SENT    2035/haproxy

说明:

    基于keepalived 实现haproxy的双主高可用已经搭建成功。


六、前端使用 LVS 的nat工作模型负载均衡两台haproxy服务器。

1、为lvs的nat工作模型提供条件

(1)、开启lvs所在服务器的ip地址转发功能。

[root@lvs network-scripts]# echo 1 > /proc/sys/net/ipv4/ip_forward

(2)、在后端各个RealServer设置默认网关,把响应的数据报文送达Director,由lvs进行源地址转换后发送给客户端。

在haproxy.9527du.com主机设置默认网关。

[root@haproxy ~]# route add default gw 192.168.60.99
[root@haproxy ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.60.0    0.0.0.0         255.255.255.0   U     0      0        0 eth0
172.16.0.0      0.0.0.0         255.255.0.0     U     0      0        0 eth1
169.254.0.0     0.0.0.0         255.255.0.0     U     1002   0        0 eth0
0.0.0.0         192.168.60.99   0.0.0.0         UG    0      0        0 eth0

在haproxy2.9527du.com主机设置默认网关

[root@haproxy2 ~]# route add default gw 192.168.60.99
[root@haproxy2 ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.60.0    0.0.0.0         255.255.255.0   U     1      0        0 eth0
172.16.0.0      0.0.0.0         255.255.0.0     U     1      0        0 eth1
0.0.0.0         192.168.60.99   0.0.0.0         UG    0      0        0 eth0
0.0.0.0         172.16.0.1      0.0.0.0         UG    0      0        0 eth

2、在Diector配置LVS规则

添加集群服务

[root@lvs /]# ipvsadm -A -t 10.10.60.22:80 -s wlc

向集群服务添加RealServer

[root@lvs /]# ipvsadm -a -t 10.10.60.22:80 -r 192.168.60.78:80 -m -w 1
[root@lvs /]# ipvsadm -a -t 10.10.60.22:80 -r 192.168.60.55:80 -m -w 1

查看配置的lvs规则

[root@lvs /]# ipvsadm -L -n
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.10.60.22:80 wlc
  -> 192.168.60.55:80             Masq    1      0          0
  -> 192.168.60.78:80             Masq    1      0          0

3、访问测试:

关闭haproxy.9527du.com这台主机的keepalive服务。

[root@haproxy ~]# service keepalived stop
Stopping keepalived:                                       [  OK  ]

在haproxy2.9527du.com查看是否有两个VIP接收LVS转发过来的请求。

[root@haproxy2 ~]# netstat  -anpt | grep "\<80\>"
tcp        0      0 0.0.0.0:80                  0.0.0.0:*                   LISTEN      10114/haproxy
tcp        0      0 192.168.60.78:80            10.10.60.1:62593            ESTABLISHED 10114/haproxy
tcp        0      0 192.168.60.55:80            10.10.60.1:62590            ESTABLISHED 10114/haproxy
tcp        0      0 192.168.60.78:80            10.10.60.1:62599            ESTABLISHED 10114/haproxy
tcp        0      0 192.168.60.55:80            10.10.60.1:62597            ESTABLISHED 10114/haproxy
tcp        0      0 192.168.60.78:80            10.10.60.1:62592            ESTABLISHED 10114/haproxy
tcp        0      0 192.168.60.55:80            10.10.60.1:62598            ESTABLISHED 10114/haproxy

说明:

    VI_1实例的VIP: 192.168.60.78 已经配置在haproxy2.9527du.com节点上,且接收LVS调度过来的请求了。


启动 haproxy.9527du.com 这台主机的keepalived服务.

[root@haproxy ~]# service keepalived start
Starting keepalived:                                       [  OK  ]

查看VI_3实例的VIP是否在,haproxy2.9527du.com接收lvs调度的请求了。

[root@haproxy2 ~]# netstat  -anpt | grep "\<80\>"
tcp        0      0 0.0.0.0:80                  0.0.0.0:*                   LISTEN      10114/haproxy
tcp        0      0 192.168.60.55:80            10.10.60.1:62729            ESTABLISHED 10114/haproxy
tcp        0      0 192.168.60.55:80            10.10.60.1:62727            ESTABLISHED 10114/haproxy
tcp        0      0 192.168.60.55:80            10.10.60.1:62645            TIME_WAIT   -
tcp        0      0 192.168.60.55:80            10.10.60.1:62724            ESTABLISHED 10114/haproxy

查看VI_1实例的VIP是否在,haproxy1.9527du.com接收lvs调度的请求了。

[root@haproxy ~]# netstat  -anpt | grep "\<80\>"
tcp        0      0 0.0.0.0:80                  0.0.0.0:*                   LISTEN      4187/haproxy
tcp        0      0 192.168.60.78:80            10.10.60.1:62646            TIME_WAIT   -
tcp        0      0 192.168.60.78:80            10.10.60.1:62725            ESTABLISHED 4187/haproxy
tcp        0      0 192.168.60.78:80            10.10.60.1:62648            TIME_WAIT   -
tcp        0      0 192.168.60.78:80            10.10.60.1:62726            ESTABLISHED 4187/haproxy
tcp        0      0 192.168.60.78:80            10.10.60.1:62650            TIME_WAIT   -
tcp        0      0 192.168.60.78:80            10.10.60.1:62647            TIME_WAIT   -
tcp        0      0 192.168.60.78:80            10.10.60.1:62728            ESTABLISHED 4187/haproxy
tcp        0      0 192.168.60.78:80            10.10.60.1:62649            TIME_WAIT   -

说明:

    从上述结果,可以看出keepalived的双主模型已经正常工作;

                lvs也能够调度前端的用户请求到不同的RealServer.

访问测试:

实现两级调度 Discuz! 论坛服务器_第13张图片一直刷新查看LVS的调度情况

实现两级调度 Discuz! 论坛服务器_第14张图片

到此为止,二层高度Discuz!论坛已经成功!!