nginx负载均衡和mysql主主被动模式基础架构综合部署

2017-11-22 14:28:06来源:http://goome.blog.51cto.com/4045241/1983483作者:人点击

分享

1.结构思路

准备用5个虚机,一个虚机安装nginx来配置负载均衡,两个虚机做web服务器,另外两个虚机,安装mysql,做主主被动配置,每次web只读取一个mysql服务。
2.具体实施步骤

用vmware最小化安装5个虚机,我用的是centos7,可以克隆。

配置两个虚机web服务,我这里用wordpress。架构可以用lamp,也可以用lnmp,我这里用lnmp。注意web连接的mysql不是在本地,启用的是另外一个虚机的mysql。

配置虚机的nginx负载均衡。

配置两个虚机的mysql主主。

测试:
负载均衡测试:分别关掉web服务器,看看访问是否正常。
mysql主从测试:看看数据是不是同步,两个mysql服务器调换测试。
压力测试:暂时没有方案。
3.虚机IP信息统计

nginx192.168.211.140
nginx_s1192.168.211.136
nginx_s2192.168.211.137
nginx_mysql192.168.211.138
nginx_mysql2192.168.211.139
4.配置nginx_mysql和nginx_mysql2的主主被动模式

4.1配置mysql源

我这里用mysql5.7,centos默认没有mysql5.7。需要安装mysql源。
[root@localhost~]#wgethttps://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm
##下载源安装包

[root@localhostsrc]#rpm-ivhmysql57-community-release-el7-11.noarch.rpm
Preparing...#################################[100%]
Updating/installing...
1:mysql57-community-release-el7-11#################################[100%]
##安装完成后,见如下,多了mysql的源

[root@localhostyum.repos.d]#ls
CentOS-Base.repoCentOS-Debuginfo.repoCentOS-Media.repoCentOS-Vault.repomysql-community-source.repo
CentOS-CR.repoCentOS-fasttrack.repoCentOS-Sources.repomysql-community.repo
4.2用源安装mysql

yum-yinstallmysql-servermysql-devel
4.3mysql基础设置,修改密码设置开机启动
[root@localhost~]#systemctlstartmysqld.service##启动
[root@localhost~]#systemctlenablemysqld.service##设置开机启动
[root@localhost~]#systemctlstatusmysqld.service##查看状态
mysql安装完成之后,在/var/log/mysqld.log文件中给root生成了一个临时的默认密码。

[root@localhostlog]#catmysqld.log|greppassword
2017-11-15T02:30:48.422591Z1[Note]Atemporarypasswordisgeneratedforroot@localhost:jyjzify=j0sA##这就是密码
2017-11-15T02:32:48.309585Z3[Note]Accessdeniedforuser'root'@'localhost'(usingpassword:NO)
临时密码登录mysql后,必须先修改root密码,而且密码有规则,必须包含大小写字母数字还有符号,必须8位以上。

mysql>alteruser'root'@'localhost'identifiedby'Alex2010@';
QueryOK,0rowsaffected(0.01sec)
4.4配置主主被动模式

配置说明

配置主-主服务器对。

两台服务器有相同的数据
启用二进制日志,选择唯一的ID,并创建复制账号
启用备库更新的日志记录
把被动服务器配置成只读,防止可能与主动服务器上的更新产生冲突。可选。
启动每个服务器的mysql实例。
每个主库设置为对方的备库,使用新创建的二进制日志开始工作。

两个服务器都是新安装的,数据相同。
启动二进制日志,设置唯一的serverid,创建复制账号,如下:

[root@localhostvar]#cat/etc/my.cnf
#Foradviceonhowtochangesettingspleasesee
#http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html

[mysqld]
#log_bin=ON
#log_bin_basename=/var/lib/mysql/mysql-bin
#log_bin_index=/var/lib/mysql/mysql-bin-index
log-bin=/var/lib/mysql/logs/mysql-bin##注意这个路径,这个路径的权限如果不是mysql:mysql,将无法启动mysql.
server-id=6##两个mysql服务器配置一样,只是server-id不同,另外一个我设置为数字8.
创建复制账号:##两个mysql都创建

mysql>grantreplicationslave,replicationclienton*.*torepl@'%'identifiedby'Passw0rd!';
QueryOK,0rowsaffected,1warning(0.02sec)

记录binlogposition##两个mysql的分别记录等下要用
mysql>showmasterstatus;
+------------------+----------+--------------+------------------+-------------------+
|File|Position|Binlog_Do_DB|Binlog_Ignore_DB|Executed_Gtid_Set|
+------------------+----------+--------------+------------------+-------------------+
|mysql-bin.000001|457||||
+------------------+----------+--------------+------------------+-------------------+
1rowinset(0.00sec)

mysql>
启动复制

changemastertomaster_host='server1',#主库的名字两个mysql互相写对方的IP
master_user='repl',#创建的用户名
master_password='password',#repl的密码
master_log_file='mysql-bin.000001',#记录的position值
master_log_pos=0;#master_log_pos参数设置为0,因为要从日志的开头读起。

执行命令:showslavestatus#备库执行检查复制是否正确执行

执行命令:startslave#备库执行,启动开始复制
启动成功每个mysql都会启动三个线程

mysql>showprocesslist
->;
+----+-------------+-----------------------+------+-------------+------+---------------------------------------------------------------+------------------+
|Id|User|Host|db|Command|Time|State|Info|
+----+-------------+-----------------------+------+-------------+------+---------------------------------------------------------------+------------------+
|4|systemuser||NULL|Connect|1006|Waitingformastertosendevent|NULL|
|5|systemuser||NULL|Connect|1553|Slavehasreadallrelaylog;waitingformoreupdates|NULL|
|6|root|localhost|NULL|Query|0|starting|showprocesslist|
|7|repl|192.168.211.138:41590|NULL|BinlogDump|396|Masterhassentallbinlogtoslave;waitingformoreupdates|NULL|
测试

192.168.211.139:

mysql>showdatabases;
+--------------------+
|Database|
+--------------------+
|information_schema|
|logs|
|mysql|
|performance_schema|
|sys|
+--------------------+
5rowsinset(0.04sec)

mysql>createdatabaseutec;
QueryOK,1rowaffected(0.01sec)

mysql>showdatabases;
+--------------------+
|Database|
+--------------------+
|information_schema|
|logs|
|mysql|
|performance_schema|
|sys|
|utec|
+--------------------+
6rowsinset(0.00sec)
看看192.168.211.138
mysql>showdatabases;
+--------------------+
|Database|
+--------------------+
|information_schema|
|logs|
|mysql|
|performance_schema|
|sys|
|utec|
+--------------------+
6rowsinset(0.00sec)

mysql>

138创建个:
mysql>useutec;
Databasechanged
mysql>createtablet1(iint);
QueryOK,0rowsaffected(0.04sec)

mysql>showtables;
+----------------+
|Tables_in_utec|
+----------------+
|t1|
+----------------+
1rowinset(0.00sec)

mysql>

139检查看看:
mysql>useutec;
Readingtableinformationforcompletionoftableandcolumnnames
Youcanturnoffthisfeaturetogetaquickerstartupwith-A

Databasechanged
mysql>showtables;
+----------------+
|Tables_in_utec|
+----------------+
|t1|
+----------------+
1rowinset(0.00sec)

mysql>

主主已经搭建成功。但是这种模式容易出问题,我们如果同时更新数据会冲突。
我们把数据库修改成被动模式,只允许其中一个数据库允许写入数据。
mysql>showvariableslike'%read_only%';
+-----------------------+-------+
|Variable_name|Value|
+-----------------------+-------+
|innodb_read_only|OFF|
|read_only|OFF|
|super_read_only|OFF|
|transaction_read_only|OFF|
|tx_read_only|OFF|
+-----------------------+-------+
5rowsinset(0.02sec)

mysql>

对于数据库读写状态,主要靠“read_only”全局参数来设定;默认情况下,数据库是用于读写操作的,所以read_only参数也是0或faluse状态,
这时候不论是本地用户还是远程访问数据库的用户,都可以进行读写操作;如需设置为只读状态,将该read_only参数设置为1或TRUE状态,但设置read_only=1
状态有两个需要注意的地方:
1.read_only=1只读模式,不会影响slave同步复制的功能,所以在MySQLslave库中设定了read_only=1后,通过showslavestatus/G命令查看salve状态,
可以看到salve仍然会读取master上的日志,并且在slave库中应用日志,保证主从数据库同步一致;
2.read_only=1只读模式,可以限定普通用户进行数据修改的操作,但不会限定具有super权限的用户的数据修改操作;在MySQL中设置read_only=1后,
普通的应用用户进行insert、update、delete等会产生数据变化的DML操作时,都会报出数据库处于只读模式不能发生数据变化的错误,但具有super权限的用户,
例如在本地或远程通过root用户登录到数据库,还是可以进行数据变化的DML操作;

为了确保所有用户,包括具有super权限的用户也不能进行读写操作,就需要执行给所有的表加读锁的命令“flushtableswithreadlock;”,
这样使用具有super权限的用户登录数据库,想要发生数据变化的操作时,也会提示表被锁定不能修改的报错。

这样通过设置“read_only=1”和“flushtableswithreadlock;”两条命令,就可以确保数据库处于只读模式,不会发生任何数据改变,
在MySQL进行数据库迁移时,限定master主库不能有任何数据变化,就可以通过这种方式来设定。

但同时由于加表锁的命令对数据库表限定非常严格,如果再slave从库上执行这个命令后,slave库可以从master读取binlog日志,但不能够应用日志,
slave库不能发生数据改变,当然也不能够实现主从同步了,这时如果使用“unlocktables;”解除全局的表读锁,slave就会应用从master读取到的binlog日志,
继续保证主从库数据库一致同步。

为了保证主从同步可以一直进行,在slave库上要保证具有super权限的root等用户只能在本地登录,不会发生数据变化,其他远程连接的应用用户只按需分配为select,
insert,update,delete等权限,保证没有super权限,则只需要将salve设定“read_only=1”模式,即可保证主从同步,又可以实现从库只读。
相对的,设定“read_only=1”只读模式开启的解锁命令为设定“read_only=0”;设定全局锁“flushtableswithreadlock;”,对应的解锁模式命令为:“unlocktables;”.

当然设定了read_only=1后,所有的select查询操作都是可以正常进行的。
设置:

[mysqld]

read_only=1
#log_bin=ON

#log_bin_basename=/var/lib/mysql/mysql-bin
#log_bin_index=/var/lib/mysql/mysql-bin-index
log-bin=/var/lib/mysql/logs/mysql-bin
server-id=6##在my.cnf[mysqld]下面设定read_only=1即可。

设置好后重启mysql查看

mysql>showvariableslike'%read_only%';
+-----------------------+-------+
|Variable_name|Value|
+-----------------------+-------+
|innodb_read_only|OFF|
|read_only|ON|##已经on了。
|super_read_only|OFF|
|transaction_read_only|OFF|
|tx_read_only|OFF|
+-----------------------+-------+
5rowsinset(0.03sec)

测试下,新建个账户,看看能写数据吗,root是可以的,因此要新建账户测试。
mysql>grantallprivilegesonutec.*to'k'@'%'identifiedby'Passw0rd!';
QueryOK,0rowsaffected,1warning(0.01sec)

mysql>

用这个新建的用户分别登录mysql

mysql>createtablet5(jint);
ERROR1290(HY000):TheMySQLserverisrunningwiththe--read-onlyoptionsoitcannotexecutethisstatement##139开启了read_only
mysql>

138上执行正常

mysql>createtablet4(kint);
QueryOK,0rowsaffected(0.03sec)

mysql>
到此主主被动模式配置成功。

5.配置web,两个web服务器一样配置

5.1安装nginx

必要软件准备
pcre支持rewrite功能
yum–yinstallpcre*
opensslssl支持
yum–yinstallopenssl*
tar-zxvfnginx-1.12.1.tar.gz

[root@localhostsrc]#cdnginx-1.12.1
[root@localhostnginx-1.12.1]#ls
autoCHANGESCHANGES.ruconfconfigurecontribhtmlLICENSEmanREADMEsrc
[root@localhostnginx-1.12.1]#
编译

./configure--prefix=/usr/local/nginx-1.12.1--with-http_ssl_module--with-http_v2_module--with-http_stub_status_module--with-pcre

编译完成,执行:make&&makeinstall

建立执行文件的link,方便执行命令

[root@localhostnginx-1.12.1]#ln-s/usr/local/nginx-1.12.1/sbin/nginx/usr/sbin/nginx

启动nginx
执行命令

[root@localhostnginx-1.12.1]#nginx

检查服务是不是起来了

[root@localhostnginx-1.12.1]#ps-ef|grepnginx
root63291003:37?00:00:00nginx:masterprocessnginx
nobody63306329003:37?00:00:00nginx:workerprocess
root63332216003:38pts/000:00:00grep--color=autonginx
[root@localhostnginx-1.12.1]#netstat-antpl|grepnginx
tcp000.0.0.0:800.0.0.0:*LISTEN6329/nginx:master
[root@localhostnginx-1.12.1]#
可以看到服务已经起来
5.2安装php

先安装安装php必须的软件:
yum–yinstallgd-devllibjpeg-devellibpng-devellibxml2-develbzip2-devellibcurl-devel
我这边是官网下载的php-7.1.8

解压缩
tar–zxvfphp-7.1.8.tar.gz
进入php-7.1.8编译
[root@localhostphp-7.1.8]#./configure--prefix=/usr/local/php-7.1.8--with-config-file-path=/usr/local/php-7.1.8/etc
--with-bz2--with-curl--enable-ftp--enable-sockets--disable-ipv6--with-gd--with-jpeg-dir=/usr/local
--with-png-dir=/usr/local--with-freetype-dir=/usr/local--enable-gd-native-ttf--with-iconv-dir=/usr/local
--enable-mbstring--enable-calendar--with-gettext--with-libxml-dir=/usr/local--with-zlib
--with-pdo-mysql=mysqlnd--with-mysqli=mysqlnd--with-mysql=mysqlnd--enable-dom--enable-xml
--enable-fpm--with-libdir=lib64

配置php

配置php
cpphp.ini-production/usr/local/php-7.1.8/etc/php.ini
cp/usr/local/php-7.1.8/etc/php-fpm.conf.default/usr/local/php-7.1.8/etc/php-fpm.conf
启动php
/usr/local/php-7.1.8/sbin/php-fpm

如果报错:
[15-Aug-201713:55:33]WARNING:Nothingmatchestheincludepattern'/usr/local/php-7.1.8/etc/php-fpm.d/*.conf'from/usr/local/php-7.1.8/etc/php-fpm.confatline125.
[15-Aug-201713:55:33]ERROR:Nopooldefined.atleastonepoolsectionmustbespecifiedinconfigfile
[15-Aug-201713:55:33]ERROR:failedtopostprocesstheconfiguration
[15-Aug-201713:55:33]ERROR:FPMinitializationfailed

/usr/local/php-7.1.8/etc/php-fpm.d
把此目录下的www.conf.default
改成www.conf
然后启动,启动成功。

检查下:

[root@bogonphp-fpm.d]#psaux|grepphp
root26700.00.72160163864?Ss01:180:00php-fpm:masterprocess(/usr/local/php-7.1.8/etc/php-fpm.conf)
nobody26710.00.62160163424?S01:180:00php-fpm:poolwww
nobody26720.00.62160163424?S01:180:00php-fpm:poolwww
root26740.00.1112664968pts/0S+01:190:00grep--color=autophp
[root@bogonphp-fpm.d]#
5.3配置wordpress

我们用的数据库不是在本地,是在192.168.211.138

须先在mysql建立一个wordpress数据库,和一个存取wordpress数据库的用户

mysql>createdatabasewordpress;
QueryOK,1rowaffected(0.00sec)

mysql>grantallprivilegesonwordpress.*to'wordpress'@'%'identifiedby'Passw0rd!';
QueryOK,0rowsaffected,1warning(0.01sec)
wordpress路径为

[root@bogonwordpress]#pwd
/usr/local/src/wordpress
配置下数据库
[root@bogonwordpress]#pwd
/usr/local/src/wordpress
[root@bogonwordpress]#ls
index.phpwp-adminwp-config-sample.phpwp-links-opml.phpwp-settings.php
license.txtwp-blog-header.phpwp-contentwp-load.phpwp-signup.php
readme.htmlwp-comments-post.phpwp-cron.phpwp-login.phpwp-trackback.php
wp-activate.phpwp-config.phpwp-includeswp-mail.phpxmlrpc.php
[root@bogonwordpress]#

wp-config.php是由wp-config-sample.php复制而来,修改下里面的数据库连接信息
5.4设置nginx
删除默认页面的server配置,就是第一个server段。
加入下面的

server{
listen80;
indexindex.phpindex.htmlindex.htm;
access_loglogs/wordpress.access.logmain;
root/usr/local/src/wordpress;
location/{
try_files$uri$uri//index.php?q=$uri&$args;
}
error_page404/404/html;
error_page500502503504/50x.html;
location=/50x.html{
root/usr/local/src/wordpress;
}

location~/.php${
try_files$uri=404;
fastcgi_pass127.0.0.1:9000;
fastcgi_indexindex.php;
fastcgi_paramSCRIPT_FILENAME$document_root$fastcgi_script_name;
includefastcgi_params;
}
}
打开浏览器输入IP,可以访问wordpress了。
记录下密码:P@ssword!
两个webserver都要配置nginx。
到这里,已经实现了两个webserver共用一个mysql,同时mysql做了主主被动模式的备份。


6.配置负载均衡

前面我们已经部署了两个web(192.168.211.136192.168.211.137)
现在通过第三台服务器部署nginx,来实现这两台服务器的负载均衡。
服务器IP是192.168.211.140

6.1解压缩nginx

[root@localhostsrc]#pwd
/usr/local/src
[root@localhostsrc]#ls
haproxy-1.7.9.tar.gznginx-1.12.1.tar.gzwordpress-4.8.1-zh_CN.tar.gz
nginx-1.12.1php-7.1.8.tar.gzzabbix-2.2.2.tar.gz
[root@localhostsrc]#
6.2编译安装
[root@localhost~]#./configure--prefix=/usr/local/nginx-1.12.1--with-http_ssl_module
--with-http_v2_module--with-http_stub_status_module--with-pcre
[root@localhost~]#make&&makeinstall

设置link

[root@localhost~]#ln-s/usr/local/nginx-1.12.1/sbin/nginx/usr/sbin/nginx

6.3

配置

以下是完整参考文件

worker_processes1;
events{
worker_connections1024;
}
http{
includemime.types;
default_typeapplication/octet-stream;
sendfileon;
keepalive_timeout65;
upstreambackend{
server192.168.211.136:80;#真实server的IP
server192.168.211.137:80;#真实server的IP
}
server{
listen80;
server_name192.168.211.140;#这个是访问用到的域名,我这里没有域名,直接用了nginx设置负载均衡那台服务器的IP
location/{
proxy_passhttp://backend;#backend对应上面upstream
proxy_set_headerHost$host;
proxy_set_headerX-Real-IP$remote_addr;
proxy_set_headerX-Forwarded-For$proxy_add_x_forwarded_for;
}
}
}
6.4测试
配置成功,我们访问配置nginx负载服务器的IP(192.168.211.140),读取的页面就是我们前面配置的那两台web服务器(136,137)的web内容。

我们关闭136137两台服务器的nginx服务,访问192.168.211.140web无法打开。

打开任何一个136137的nginx服务,访问192.168.211.140web访问正常。

6.5

到这里一个基础的架构做出来了。

前端是nginx负载均衡,后端是mysql主主被动模式。

微信扫一扫

第七城市微信公众平台