之前因为公司的产品需求,研究过分布式方案,最近抽空整理了下
解决方案
- 主要是以
nginx
搭载keepalived
实现 web 业务服务器keepalives
防止单点故障 reids
分布式缓存fastdfs
分布式文件postgre-xl
分布式数据库服务器
简单说,分布式是以缩短单个任务的执行时间来提升效率的,而集群则是通过提高单位时间内执行的任务数来提升效率。
以下是实验中遇到的问题以及安装方法
CentOS7 安装问题集
远程无法访问(防火墙问题)
|
|
nginx
参考另一篇nginx 安装
keepalives
简介
Keepalived 是一个基于 VRRP 协议来实现的服务高可用方案,可以利用其来避免 IP 单点故障,类似的工具还有 heartbeat、corosync、pacemaker。
但是它一般不会单独出现,而是与其它负载均衡技术(如 lvs、haproxy、nginx)一起工作来达到集群的高可用。
Keepalived 的作用是检测服务器的状态,如果有一台 web 服务器死机,或工作出现故障,Keepalived 将检测到,并将有故障的服务器从系统中剔除,同时使用其他服务器代替该服务器的工作;
当服务器工作正常后 Keepalived 自动将服务器加入到服务器群中,这些工作全部自动完成,不需要人工干涉,需要人工做的只是修复故障的服务器。
原理
|
|
首先 Keepalived 可以在主机上产生一个虚拟的 ip, 这里叫做 vip(v 是 virtual 的意思):192.168.200.150, keepalived 会将这个 vip 绑定到交换机上.
当用户访问主机:192.168.200.129 时, 交换机会通过这个 ip 和 vip 的对应找到 192.168.200.129 上的 Nginx 进行处理.
如果当有一天 192.168.200.129 上的 Nginx 挂掉的时候, Keepalived 会立即在备机上生成一个相同的 vip: 192.168.200.150, 当用户继续访问 192.168.200.129 时, 交换机上已经绑定了 vip, 这时发现这个 vip 是存在于 192.168.200.130 上面的, 所以直接将请求转发到了备机上.
如果主机被修复好能够继续对外提供服务时, 这时 keepalived 会将主机上继续生成这个 vip, 同时回收在备机上生成的 vip. 这个是通过心跳检查来判断主机已恢复使用.
安装
下载
wget http://www.keepalived.org/software/keepalived-1.2.23.tar.gz
解压
tar -zxvf keepalived-1.2.23.tar.gz
cd keepalived-1.2.23
安装
./configure –prefix=/usr/local/keepalived #prefix 指定安装目录
如果提示错误 openssl 不存在
sudo apt-get install openssl
sudo apt-get install libssl-dev
make
make install
配置
|
|
启动
|
|
默认的配置文件中,指定了虚拟可使用ip addr(或ip a)命令验证之。查看网卡下是否有虚拟ip
如果虚拟ip ping不同
1.vim /etc/keepalived/keepalived.conf
把这个注释就可以了
vrrp_strict
2.可能上级交换机或路由器绑定了apr,也就是ip与mac地址绑定
可以使用 arping -I [网卡名] -c 5 -s [本机IP或vip] [网关] 看一下接收情况
应用
keepalived两种模式:主-备、主-主
主-备
虚拟IP:192.168.0.110 主节点:192.168.0.50 备用节点:192.168.0.51
主配置文件
【/usr/local/keepalived/etc/keepalived/keepalived.conf】
global_defs {
notification_email { #指定keepalived在发生事情的时候,发送邮件告知,可以有多个地址,每行一个。
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc #指定发件人
smtp_server 127.0.0.1 #发送email的smtp地址
smtp_connect_timeout 30 #超时时间
router_id LVS_DEVEL #运行keepalived的机器的一个标识,多个节点标识可以相同,也可以不同
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_instance VI_1 {
state MASTER #指定当前节点为主节点 备用节点上设置为BACKUP即可
interface eth0 #绑定虚拟IP的网络接口 使用ip a查看
virtual_router_id 51 #VRRP组名,两个节点的设置必须一样,以指明各个节点属于同一VRRP组
priority 100 #主节点的优先级(1-254之间),备用节点必须比主节点优先级低
advert_int 1
authentication { #设置验证信息,两个节点必须一致
auth_type PASS
auth_pass 1111
}
virtual_ipaddress { #指定虚拟IP, 两个节点设置必须一样
192.168.0.110/24
}
}
备配置文件
【/usr/local/keepalived/etc/keepalived/keepalived.conf】
global_defs {
notification_email { #指定keepalived在发生事情的时候,发送邮件告知,可以有多个地址,每行一个。
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc #指定发件人
smtp_server 127.0.0.1 #发送email的smtp地址
smtp_connect_timeout 30 #超时时间
router_id LVS_DEVEL #运行keepalived的机器的一个标识,多个节点标识可以相同,也可以不同
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_instance VI_1 {
state BACKUP #指定当前节点为主节点 备用节点上设置为BACKUP即可
interface eth0 #绑定虚拟IP的网络接口
virtual_router_id 51 #VRRP组名,两个节点的设置必须一样,以指明各个节点属于同一VRRP组
priority 99 #主节点的优先级(1-254之间),备用节点必须比主节点优先级低
advert_int 1
authentication { #设置验证信息,两个节点必须一致
auth_type PASS
auth_pass 1111
}
virtual_ipaddress { #指定虚拟IP, 两个节点设置必须一样
192.168.0.110/24
}
}
主-主
虚拟IP:192.168.1.21、192.168.1.22 A节点:192.168.1.23 B节点:192.168.1.24
主备模式的缺点就是始终只有一台机器位于工作状态,另外一台机器永远是备用状态,存在资源浪费之问题。
双主模式允许两台机器均处于工作状态并互相作为备份。搭建keepalived双方模式的要素:
1.必须有两个虚拟IP, 分别绑定至两个节点上
2.每个节点作为某个虚拟IP的主节点,并同时作为另外一个虚拟IP的备用节点。
3.当某个节点产生故障时,两个虚拟IP自动绑定至正常节点上
也就是说,两个节点的配置应该是交叉的,对同个虚拟IP,交叉互为主备。
节点A配置文件
【/usr/local/keepalived/etc/keepalived/keepalived.conf】
global_defs {
notification_email { #指定keepalived在发生事情的时候,发送邮件告知,可以有多个地址,每行一个。
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc #指定发件人
smtp_server 127.0.0.1 #发送email的smtp地址
smtp_connect_timeout 30 #超时时间
router_id LVS_DEVEL #运行keepalived的机器的一个标识,多个节点标识可以相同,也可以不同
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51 #本机两个vrrp_instance组的此值不能相同,但对应备用节点的此值必须相同
priority 100 #对应备用节点值应该比此值小
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.1.21/24
}
}
vrrp_instance VI_2 {
state BACKUP
interface eth0
virtual_router_id 52 #本机两个vrrp_instance组的此值不能相同,但对应备用节点的此值必须相同
priority 99 #主节点的值应该比此值大
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.1.22/24
}
}
节点B配置文件
【/usr/local/keepalived/etc/keepalived/keepalived.conf】
global_defs {
notification_email { #指定keepalived在发生事情的时候,发送邮件告知,可以有多个地址,每行一个。
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc #指定发件人
smtp_server 127.0.0.1 #发送email的smtp地址
smtp_connect_timeout 30 #超时时间
router_id LVS_DEVEL #运行keepalived的机器的一个标识,多个节点标识可以相同,也可以不同
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 51 #本机两个vrrp_instance组的此值不能相同,但对应备用节点的此值必须相同
priority 99 #对应主节点值应该比此值大
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.1.21/24
}
}
vrrp_instance VI_2 {
state MASTER
interface eth0
virtual_router_id 52 #本机两个vrrp_instance组的此值不能相同,但对应备用节点的此值必须相同
priority 100 #对应备用节点的值应该比此值小
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.1.22/24
}
}
问题
两个节点实际都处于正常工作状态,但是无法接收到彼此的组播通知,这时两个节点均强行绑定虚拟IP,导致不可预料的后果。
这时就需要设置仲裁,即每个节点必须判断自身的状态(应用服务状态及自身网络状态),要实现这两点可使用自定义shell脚本实现,通过周期性地检查自身应用服务状态,并不断ping网关(或其它可靠的参考IP)均可。当自身服务异常、或无法ping通网关,则认为自身出现故障,就应该移除掉虚拟IP(停止keepalived服务即可)。
主要借助keepalived提供的vrrp_script及track_script实现:
在keepalived的配置文件最前面加入以下代码,定义一个跟踪脚本:
vrrp_script check_local { #定义一个名称为check_local的检查脚本
script “/usr/local/keepalived/bin/check_local.sh” #shell脚本的路径
interval 5 #运行间隔
}
再在vrrp_instance配置中加入以下代码使用上面定义的检测脚本:
track_script {
check_local
}
我们在/usr/local/keepalived/bin/check_local.sh定义的检测规则是:
自身web服务故障(超时,http返回状态不是200)
无法ping通网关
产生以上任何一个问题,均应该移除本机的虚拟IP(停止keepalived实例即可)
但这里有个小问题,如果本机或是网关偶尔出现一次故障,那么我们不能认为是服务故障。更好的做法是如果连续N次检测本机服务不正常或连接N次无法ping通网关,才认为是故障产生,才需要进行故障转移。
但这么做的缺点是,如果脚本检测到故障产生,并停止掉了keepalived服务,那么当故障恢复后,keepalived是无法自动恢复的。
还可以利用独立的脚本以秒级的间隔检查自身服务及网关连接性,再根据故障情况控制keepalived的运行或是停止。
在每个节点运行shell脚本(check_service.sh)检测本机的服务是否正常,一旦检测到服务异常时,停止掉本机的keepalived, 如此虚拟IP自动转移到备用机器之上,如每隔3秒检测一次本机服务状态,如果连接3次检测失败,则停止掉keepalived实例。同时如果本机服务是正常的,但是keepalived没有启动(故障恢复之后),则启动keepalived,以达到故障恢复之目的。
check_service.sh文件的内容
两个节点上均应运行此脚本,请将此脚本加入到cron任务中(此程序已经作了单实例运行机制,加入计划任务的作用就是防止脚本意外中断后检测功能失效),可实现的功能:
如果本地服务连续三次检测失败,就尝试停止keepalived服务(如果keepalived处于运行状态)
如果本地服务连接三次检测成功,但keepalived没有启动,则启动之
关键的执行点,均已经记录到系统日志中(/var/log/messages)
执行crontab -e , 加入以下内容:
/1 * root /home/testuser/check_local.sh
停止掉本机的keepalived, 稍过一会,就会keepalived服务被自动启动了(这是因为本地服务检测正常)
停止掉本机的nginx, 稍过一会,就会发现keepalived服务也被停止掉了
再启动nginx, 稍过一会,发现keepalived也被正常启动,并绑定了正确的虚拟IP
redis
1.下载解压安装redis
1.1redis源文件
将redis源文件放在目录/usr/local/src/
下
1.2解压redis
移动到redis所在文件目录
cd /usr/local/src/
tar -zxvf redis.tar.gz
1.3编译安装redis
移动到解压后reids目录
cd redis
make
进入reids/src目录
make install
2.Redis的部署
安装成功后,下面对Redis 进行部署
如果需使用tomcat来连接的话
1.关闭安全模式
2.设置密码
2.1执行Redis-server 命令,启动Redis 服务
注意:这里直接执行Redis-server 启动的Redis服务,是在前台直接运行的,也就是说,执行完该命令后,如果Lunix关闭当前会话,则Redis服务也随即关闭。正常情况下,启动Redis服务需要从后台启动,并且指定启动配置文件。
3、后台启动redis服务
a)首先编辑conf文件,将daemonize属性改为yes(表明需要在后台运行)
cd etc/
vi redis.conf
如果redis.conf文件不存在就从安装目录复制过去
b)再次启动redis服务,并指定启动服务配置文件
redis-server /etc/redis.conf
4、服务端启动成功后,启动Redis
redis-cli
使用命令 config set requirepass admin
为redis设置密码为admin
输入验证密码
auth admin
保存密码设置信息到磁盘
save
退出
exit
3.tomcat配置
3.1 jar包
commons-logging-1.2.jar
commons-pool2-2.4.2.jar
jedis-2.9.0.jar
tomcat-redis-session-manager1.2.jar
将以上4个jar包放入tomcat/lib下
3.2 content.xml配置
配置Tomcat的conf目录下的context.xml文件:
1.单点Reids配置
1234567 <Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" /><Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager"host="192.168.0.111"port="6379"password="admin"//reids密码database="0"maxInactiveInterval="60" />2.Sentinel集群配置:
12345678910 <!-- Sentinel 配置 --><Valve className="reyo.redis.session.manager.tomcat8.RedisSessionHandlerValve" /><Manager className="reyo.redis.session.manager.tomcat8.RedisSessionManager"maxInactiveInterval="60"sentinelMaster="mymaster"sentinels="127.0.0.1:26379,127.0.0.1:26380,127.0.0.1:26381,127.0.0.1:26382" />
案例:
如果要监控两个redis实例,可以进行如下配置Redis安装目录下sentinel.conf文件:
常规配置:
特殊配置:min-slaves-to-write 1
min-slaves-max-lag 10
通过上面的配置,当一个redis是master时,如果它不能向至少一个slave写数据(上面的min-slaves-to-write指定了slave的数量),它将会拒绝接受客户端的写请求。由于复制是异步的,master无法向slave写数据意味着slave要么断开连接了,要么不在指定时间内向master发送同步数据的请求了(上面的min-slaves-max-lag指定了这个时间)。
配置Redis能随系统启动:
./utils/install_server.sh
Redis服务查看、开启、关闭:
a.通过ps -ef|grep redis命令查看Redis进程
b.开启Redis服务操作通过/etc/init.d/redis_6379 start命令,也可通过(service redis_6379 start)
c.关闭Redis服务操作通过/etc/init.d/redis_6379 stop命令,也可通过(service redis_6379 stop)
Postgres-XL
centos7安装:
在所有主机上安装Postgres-XL
在每台机器的 /etc/hosts中加入以下内容:
|
|
关闭防火墙:
|
|
selinux设置
|
|
安装依赖包:
|
|
新建用户
每个节点都建立用户postgres,并且建立.ssh目录,并配置相应的root权限:
|
|
ssh免密码登录(只在gtm下做
)
仅仅在
gtm
节点配置如下操作:
|
|
对所有提示都不要输入,直接enter下一步。
将刚生成的认证文件拷贝到datanode1到datanode2中,使得gtm节点可以免密码登录datanode1~datanode2的任意一个节点:
|
|
这里会提示如下内容 输入yes后会提示让你输入远程用户密码
|
|
Postgres-XL安装(每台服务器都要操作)
|
|
cortrib中有很多postgres很牛的工具,一般要装上。如ltree,uuid,postgres_fdw等等。
配置环境变量
进入postgres用户,修改其环境变量
在打开的文件末尾,新增如下变量配置:
|
|
按住esc,然后输入:wq!保存退出
输入以下命令对更改重启生效:
source .bashrc
检查配置是否已修改
检查ssh免密访问是否配置成功
修改文件夹所有者
将/home/postgres下所有文件的所有者变更为postgres用户[root@gtm ~]# chown -R postgres /home/postgres
生成pgxc_ctl配置文件(只在gtm下做
)
在/usr/local/src/postgres-xl/contrib/pgxc_ctl目录下
运行命令
./pgxc_ctl
后进入操作界面后输入prepare之后使用Crtl+c退出PGXC操作界面
|
|
编辑pgxc_ctl.conf文件
[postgres@localhost ~]$ vim /home/postgres/pgxc_ctl/pgxc_ctl.conf
配置内容如下:
|
|
初始化集群
pgxc_ctl -c /home/postgres/pgxc_ctl/pgxc_ctl.conf init all
启动pgxc_ctl -c /home/postgres/pgxc_ctl/pgxc_ctl.conf stop all
关闭
初始化提示内容如下:
- 遇到的问题
安装时出现permission denied
是因为权限不足 使用sudo chmod -R 777 /usr
或sudo pgxc_ctl -c /home/postgres/pgxc_ctl/pgxc_ctl.conf init all
集群验证
在datanode1节点上
连接上5432端口,即node1上的coordinator,查看集群节点状态
|
|
如上面所示,可看到2个coordinator,2个node。集群状态正常
尝试创建测试表test1,并插入数据
|
|
连接到datanode1服务器的5433端口,即node1,查看测试表的数据
可看到表中数据是不全的
再去datanode2服务器查看
先连接到5432端口,即coordinator
再切换到5433端口,即node2
正好是node1中缺少的那部分数据
证实分布式数据库集群搭建完成
数据库集群日常操作
关闭集群
在gtm服务器上执行
开启集群
在gtm服务器上执行
|
|