网站架构部署
作者 | 刘畅 |
时间 | 2021-03-02 |
目录
6配置 22
1 环境规划
1.1 架构图
1.2 主机规划表
操作系统版本:CentOS7.5
IP | 主机名 | 角色 |
172.16.1.211 vip(eth1): 172.16.1.200 | lb4-01 | LVS+Keepalived |
172.16.1.212 | lb4-02 | LVS+Keepalived |
172.16.1.213 | lb7-01 | Nginx |
172.16.1.214 | lb7-02 | Nginx |
172.16.1.215 | dy-web01 | Tomcat/php |
172.16.1.216 | dy-web02 | Tomcat/php |
172.16.1.217 | stc-web01 | Nginx |
172.16.1.218 | stc-web02 | Nginx |
172.16.1.219 | redis-01 | Redis(SESSION共享) |
172.16.1.221 | glusterfs01 | GlusterFS |
172.16.1.222 | glusterfs02 | GlusterFS |
172.16.1.223 | mysql | MySQL |
部署顺序为从后往前部署
2 数据库与存储
2.1 安装MySQL
1 安装
在172.16.1.223节点上操作
YUM或APT安装或更新MySQL是最方便的方法
部署官方文档如下:
https://dev.mysql.com/downloads/repo/yum/
https://dev.mysql.com/doc/mysql-yum-repo-quick-guide/en/
# yum -y install yum-utils
# rpm -ivh https://dev.mysql.com/get/mysql80-community-release-el7-1.noarch.rpm
# yum-config-manager --disable mysql80-community
# yum-config-manager --enable mysql57-community
# yum install mysql-community-server -y
2 MySQL服务器配置
# vim /etc/my.cnf
[client]
port = 3306
default-character-set = utf8
socket = /var/lib/mysql/mysql.sock
[mysql]
no-auto-rehash
[mysqld]
user = mysql
port = 3306
basedir = /usr
datadir = /var/lib/mysql
socket = /var/lib/mysql/mysql.sock
bind-address = 0.0.0.0
pid-file = /var/run/mysqld/mysqld.pid
character-set-server = utf8
collation-server = utf8_general_ci
log-error = /var/log/mysqld.log
slow_query_log = ON
long_query_time = 2
slow_query_log_file = /var/lib/mysql/mysql-slow.log
max_connections = 10240
open_files_limit = 65535
innodb_buffer_pool_size = 1G
innodb_flush_log_at_trx_commit = 2
innodb_log_file_size = 256M
transaction_isolation = READ-COMMITTE
default-storage-engine = innodb
innodb_file_per_table = on
symbolic-links = 0
explicit_defaults_for_timestamp = 1
skip-name-resolve
lower_case_table_names = 1
server-id = 1
[mysqldump]
quick
max_allowed_packet = 32M
3 启动服务
# systemctl start mysqld
# systemctl enable mysqld
# systemctl status mysqld
# grep 'temporary password' /var/log/mysqld.log
2021-03-02T02:33:45.484412Z 1 [Note] A temporary password is generated for root@localhost: XfqhEEpd02+O
# mysql -uroot -p'XfqhEEpd02+O'
mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'LiuChang@2021';
# 注意:密码要求包含一个大写字母,一个小写字母,一位数字和一个特殊字符,并且密码长度至少为8个字符。
4 添加用户并授权
mysql> create database wp;
mysql> grant all on wp.* to 'wp'@'172.16.1.%'
mysql> flush privileges;
2.2 安装Redis
在172.16.1.219节点上操作
# yum install redis -y
# vim /etc/redis.conf
bind 0.0.0.0
requirepass 123456
# systemctl start redis
# systemctl enable redis
# redis-cli
127.0.0.1:6379> AUTH 123456
OK
127.0.0.1:6379> keys *
(empty list or set)
2.3 安装GlusterFS
在172.16.1.221、222节点上操作
1 介绍
l volume
glustefs逻辑卷,外部使用者看到的总存储。
l brick
逻辑卷内部的各个物理存储单元,是一个挂载的目录,各个brick以不同的模式组成一个volume。
2 安装GlusterFS
在172.16.1.221、222节点上操作
# yum install centos-release-gluster -y
# ls /etc/yum.repos.d/*Gluster*
/etc/yum.repos.d/CentOS-Gluster-9.repo
# yum install -y glusterfs-server
# systemctl start glusterd.service
# systemctl enable glusterd.service
# glusterfs -V
glusterfs 9.0
Repository revision: git://git.gluster.org/glusterfs.git
补充:iptables 配置
iptables -I INPUT -p all -s `<ip-address>` -j ACCEPT
或
# iptables -I INPUT -m state --state NEW -m tcp -p tcp --dport 24007:24008 -j ACCEPT
# iptables -I INPUT -m state --state NEW -m tcp -p tcp --dport 49152:49156 -j ACCEPT
3配置信任池
在172.16.1.221节点上操作
# gluster peer probe 172.16.1.222
# gluster peer status
Number of Peers: 1
Hostname: 172.16.1.222
Uuid: 29abcdfd-3d4b-4a35-b649-68eaf693895c
State: Peer in Cluster (Connected)
4 建立一个GlusterFS卷
(1) 在172.16.1.221、222节点上创建存储目录
# mkdir -p /bricks/brick1/gv0
(2) 在172.16.1.221节点上创建卷(任意一个节点都可以操作)
# gluster volume create gv0 replica 2 172.16.1.221:/bricks/brick1/gv0 172.16.1.222:/bricks/brick1/gv0 force
说明:
由于创建的gluster卷需要在单独的磁盘上,如果不是需要添加force参数进行强制创建。
# 启动卷
# gluster volume start gv0
# 确认卷已经启动
# gluster volume info
5 测试
提供三种挂载方式:Native client,NFS,Samba(CIFS)
Native挂载方式一大优势是支持高可用,虽然我们挂载的是172.16.1.221,但是当172.16.1.221不可用时,glusterfs volume还是可以工作的。可以挂起虚拟机,模拟下172.16.1.221故障。
3 动态Web服务器
在172.16.1.215、216节点上操作
3.1 PHP-FPM
1 装PHP
(1) 安装php依赖的第三方库
# yum install gd-devel libxml2-devel libcurl-devel libjpeg-devel libpng-devel openssl-devel openssl -y
(2) 编译安装php
# http://docs.php.net/get/php-5.6.34.tar.gz/from/this/mirror
# tar -zxf php-5.6.34.tar.gz
# groupadd -g 1200 nginx
# useradd -M -s /sbin/nologin -u 1200 -g nginx nginx
# id nginx
uid=1200(nginx) gid=1200(nginx) groups=1200(nginx)
# cd php-5.6.34
# ./configure --prefix=/usr/local/php \
--with-config-file-path=/usr/local/php/etc \
--with-mysql --with-mysqli \
--with-openssl --with-zlib --with-curl --with-gd \
--with-jpeg-dir --with-png-dir --with-iconv \
--enable-fpm --enable-zip --enable-mbstring \
--with-fpm-user=nginx \
--with-fpm-group=nginx
# make -j 4 && make install
(3) 配置php
# cp php.ini-production /usr/local/php/etc/php.ini
# vim /usr/local/php/etc/php.ini
date.timezone = Asia/Shanghai
(4) 配置php-fpm
# cp /usr/local/php/etc/php-fpm.conf.default /usr/local/php/etc/php-fpm.conf
# vim /usr/local/php/etc/php-fpm.conf
pid = run/php-fpm.pid
listen = 0.0.0.0:9000
# cp sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm
# chmod +x /etc/rc.d/init.d/php-fpm
# cat /usr/lib/systemd/system/php-fpm.service
[Unit]
Description=The PHP FastCGI Process Manager
After=syslog.target network.target
[Service]
Type=simple
PIDFile=/usr/local/php/var/run/php-fpm.pid
ExecStart=/usr/local/php/sbin/php-fpm --nodaemonize --fpm-config /usr/local/php/etc/php-fpm.conf
ExecReload=/bin/kill -USR2 $MAINPID
[Install]
WantedBy=multi-user.target
# systemctl daemon-reload
# systemctl start php-fpm.service
# systemctl enable php-fpm.service
# netstat -tunlp | grep php
tcp 0 0 0.0.0.0:9000 0.0.0.0:* LISTEN 1695/php-fpm: maste
3.2基于Redis实现Seesion共享
PHP安装Redis扩展模块
https://github.com/phpredis/phpredis
https://github.com/phpredis/phpredis/releases
# yum install autoconf -y
# wget https://github.com/phpredis/phpredis/archive/3.1.6.tar.gz
# tar -zxf 3.1.6.tar.gz
# cd phpredis-3.1.6/
# /usr/local/php/bin/phpize
Configuring for:
PHP Api Version: 20131106
Zend Module Api No: 20131226
Zend Extension Api No: 220131226
# ./configure --with-php-config=/usr/local/php/bin/php-config
# make && make install
Installing shared extensions: /usr/local/php/lib/php/extensions/no-debug-non-zts-20131226/
# vim /usr/local/php/etc/php.ini
;extension=php_shmop.dll
extension=/usr/local/php/lib/php/extensions/no-debug-non-zts-20131226/redis.so
; Handler used to store/retrieve data.
; http://php.net/session.save-handler
session.save_handler = redis
session.save_path = "tcp://172.16.1.219:6379?auth=123456"
# /usr/local/php/bin/php -m |grep redis
redis
# systemctl restart php-fpm.service
# cat phpinfo.php
<?php phpinfo(); ?>
参考文档:https://blog.csdn.net/qq_31659985/article/details/97948365
在代码里配置session共享,在redis中可以查看到键值
# cat phptest.php
<?php
// 如果未修改php.ini下面两行注释去掉
// ini_set('session.save_handler', 'redis');
// ini_set('session.save_path', 'tcp://127.0.0.1:6379');
session_start();
$_SESSION['sessionid'] = 'this is session content!';
echo $_SESSION['sessionid'];
echo '<br/>';
# $redis = new redis();
# $redis->connect('127.0.0.1', 6379);
// redis 用 session_id 作为 key 并且是以 string 的形式存储
echo $redis->get('PHPREDIS_SESSION:' . session_id());
3.3 创建代码目录
# mkdir -p /dy/php/html
4静态Web服务器
在172.16.1.217、218节点上操作
4.1 Nginx安装
1 网络源安装
# 替换OS为rhel或centos,OSRELEASE为6或7
# vim /etc/yum.repos.d/nginx.repo
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
enabled=1
# yum install nginx
# nginx -v
# nginx -V
# rpm -ql nginx # 查看已安装包在系统安装了哪些文件
# systemctl start nginx
# ps -ef |grep nginx
2 编译安装及编译参数(推荐)
# yum install -y gcc gcc-c++ make openssl-devel pcre-devel
# groupadd -g 1200 nginx
# useradd -M -s /sbin/nologin -u 1200 -g nginx nginx
# curl -o nginx-1.12.2.tar.gz http://nginx.org/download/nginx-1.12.2.tar.gz
# tar -zxf nginx-1.12.2.tar.gz
# cd nginx-1.12.2/
# ./configure --prefix=/usr/local/nginx \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-http_stub_status_module \
--with-stream=dynamic
# make -j 4 && make install
常用编译参数:
参数 | 描述 |
--prefix=PATH | 安装目录 |
--sbin-path=PATH | nginx可执行文件目录 |
--modules-path=PATH | 模块路径 |
--conf-path=PATH | 配置文件路径 |
--error-log-path=PATH | 错误日志路径 |
--http-log-path=PATH | 访问日志路径 |
--pid-path=PATH | pid路径 |
--lock-path=PATH | lock文件路径 |
--user=USER | 运行用户 |
--group=GROUP | 运行组 |
--with-threads | 启用多线程 全局先定义池子: thread_pool one threads=32 max_queue=65535; 在里面引用: aio threads=one; |
--with-http_ssl_module | 提供HTTPS支持 |
--with-http_v2_module | HTTP2.0协议 |
--with-http_realip_module | 获取真实客户端IP |
--with-http_image_filter_module | 图片过滤模块,比如缩略图、旋转等 |
--with-http_geoip_module | 基于客户端IP获取地理位置 |
--with-http_sub_module | 在应答数据中可替换静态页面源码内容 |
--with-http_dav_module | 为文件和目录指定权限,限制用户对页面有不同的访问权限 |
--with-http_flv_module --with-http_mp4_module | 支持flv、mp4流媒体播放 |
--with-http_gzip_static_module | 针对静态文件,允许发送.gz文件扩展名的预压缩文件给客户端,使用是gzip_static on |
--with-http_gunzip_static_module | Content-Encoding:gzip 用于对不支持gzip压缩的客户端使用,先解压缩后再响应。 |
--with-http_secure_link_module | 检查链接,比如实现防盗链 |
--with-http_stub_status_module | 获取nginx工作状态模块 |
--with-mail_ssl_module | 启用邮件SSL模块 |
--with-stream | 启用TCP/UDP代理模块 |
--add-module=PATH | 启用扩展模块 |
--with-stream_realip_module | 流形式,获取真实客户端IP |
--with-stream_geoip_module | 流形式,获取客户端IP地理位置 |
--with-pcre | 启用PCRE库,rewrite需要的正则库 |
--with-pcre=DIR | 指定PCRE库路径 |
--with-zlib=DIR | 指定zlib库路径,gzip模块依赖 |
--with-openssl=DIR | 指定openssl库路径,ssl模块依赖 |
--with 这些模块在编译时默认没启用
--without 默认启用的模块
dynamic 1.9.11版本后支持nginx运行时动态加载模块,像以前需要在编译时指定才会加载此模块,现在不主动加载模块,当使用时才会加载。在安装目录会创建一个目录modules,里面存放着动态加载的模块。
暂时支持这几个模块动态加载,
# ./configure --help |grep dynamic
同时也增加了一个指令:load_module modules/ngx_http_geoip_module.so;# 要放到nginx.conf最上面
要想第三方模块为动态加载,需要再编译时指定:
./configure --add-dynamic-module=PATH
这样动态模块的共享文件会被安装到modules目录下,可以再通过load_module指令动态加载这个模块。
tengine早些版本已经实现动态加载模块了。
gzip压缩体积越小,对CPU消耗越大
第三方模块地址:https://www.nginx.com/resources/wiki/modules/
nginx命令行参数:
# /usr/local/nginx/sbin/nginx –h
-c file 指定配置文件
-g directives 设置全局配置指令,例如nginx -g“pid /var/run/nginx.pid”
-t 检查配置文件语法
-v 打印nginx版本
-V 打印nginx版本,编译器版本和配置
-s 向master进程发送信号
信号:
stop 快速关闭
quit 正常关闭,等待工作进程完成当前请求后停止nginx进程
reload 重新加载配置文件
reopen 重新打开日志文件
4.2 Nginx配置
# cp /usr/local/nginx/conf/nginx.conf{,.bak}
# 创建静态文件存放目录
# mkdir -p /static/php/html
# cat /usr/local/nginx/conf/nginx.conf
user nginx;
# worker进程的数量
worker_processes auto;
# 绑定Nginx的worker进程到指定的CPU内核
worker_cpu_affinity auto;
error_log logs/error.log warn;
pid logs/nginx.pid;
# worker进程可以打开的最大句柄描述符个数
# 调整至1w以上,负荷较高建议2-3w以上
worker_rlimit_nofile 65535;
events {
use epoll;
# 每个worker进程的最大连接数
# worker_processes乘以worker_connections等于nginx总体最大连接数
worker_connections 10240;
}
http {
include mime.types;
default_type application/octet-stream;
# 统一使用utf-8字符集
charset utf-8;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" $upstream_addr';
access_log logs/access.log main;
# Core module
sendfile on;
# 静态资源服务器建议打开
tcp_nopush on;
# 动态资源服务建议打开,需要打开keepalived
tcp_nodelay on;
keepalive_timeout 65;
# Gzip module
gzip on;
gzip_disable "MSIE [1-6]\.";
gzip_http_version 1.1;
# Virtal Server
# include conf.d/*.conf;
# 上传文件大小限制
client_max_body_size 8m;
# 隐藏nginx版本号
server_tokens off;
# 关闭目录浏览功能
autoindex off;
server {
listen 80;
server_name localhost;
location / {
root /static/php/html;
}
}
}
# /usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
# cat /usr/lib/systemd/system/nginx.service
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
# systemctl daemon-reload
# systemctl start nginx.service
# systemctl enable nginx.service
# netstat -tunlp | grep nginx
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 5128/nginx: master
4.3挂载GlusterFS卷
# mkdir -p /static/php/html
# yum install glusterfs-fuse -y
# mount -t glusterfs 172.16.1.221:/gv0 /static/php/html
# df -hT
172.16.1.221:/gv0 fuse.glusterfs 58G 2.4G 56G 5% /static/php/html
# echo "172.16.1.221:/gv0 /static/php/html glusterfs defaults 0 0" >> /etc/fstab
说明:
FUSE:Filesystem Userspace是一个可加载的内核模块,其支持非特权用户创建自己的文件系统而不需要修改内核代码。通过在用户空间运行文件系统的代码通过FUSE代码与内核进行桥接。
创建文件和删除文件需要将卷先挂载到一台机器上,然后再对挂载卷上的数据进行操作,如果直接在gluster服务器上进行操作,会导致数据不一致。
5 七层负载均衡
在172.16.1.213、214节点上操作
5.1 Nginx安装
1 编译安装
# yum install -y gcc gcc-c++ make openssl-devel pcre-devel
# groupadd -g 1200 nginx
# useradd -M -s /sbin/nologin -u 1200 -g nginx nginx
# curl -o nginx-1.12.2.tar.gz http://nginx.org/download/nginx-1.12.2.tar.gz
# tar -zxf nginx-1.12.2.tar.gz
# cd nginx-1.12.2/
# ./configure --prefix=/usr/local/nginx \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-http_stub_status_module \
--with-stream=dynamic
# make -j 4 && make install
5.2 Nginx主配置文件
# cp /usr/local/nginx/conf/nginx.conf{,.bak}
# mkdir -p /usr/local/nginx/conf/conf.d
# cat /usr/local/nginx/conf/nginx.conf
user nginx;
# worker进程的数量
worker_processes auto;
# 绑定Nginx的worker进程到指定的CPU内核
worker_cpu_affinity auto;
# error_log logs/error.log warn;
pid logs/nginx.pid;
# worker进程可以打开的最大句柄描述符个数
# 调整至1w以上,负荷较高建议2-3w以上
worker_rlimit_nofile 65535;
events {
use epoll;
# 每个worker进程的最大连接数
# worker_processes乘以worker_connections等于nginx总体最大连接数
worker_connections 10240;
}
http {
include mime.types;
default_type application/octet-stream;
# 统一使用utf-8字符集
charset utf-8;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" $upstream_addr';
# access_log logs/access.log main;
# Core module
sendfile on;
# 静态资源服务器建议打开
tcp_nopush on;
# 动态资源服务建议打开,需要打开keepalived
tcp_nodelay on;
keepalive_timeout 65;
# Gzip module
gzip on;
gzip_disable "MSIE [1-6]\.";
gzip_http_version 1.1;
# 上传文件大小限制
client_max_body_size 8m;
# 隐藏nginx版本号
server_tokens off;
# 关闭目录浏览功能
autoindex off;
# Virtal Server
include conf.d/*.conf;
}
# /usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
5.3配置(php)
需要知道的是Nginx本身是一个静态Web服务器,并不支持解析PHP程序,但它支持了FastCGI接口来调用动态服务来解析PHP程序。
FastCGI是一个HTTP服务与脚本语言交互的接口
当客户端请求PHP页面时,Nginx通过fastcgi接口转发给本地9000端口的PHP-FPM子进程处理,处理完成后返回Nginx。
php-fpm相当于一个解析php程序动态应用服务器。
Nginx配置php程序通过FastCGI转发给php-fpm进程解析
# cat /usr/local/nginx/conf/conf.d/php.conf
upstream static.wp {
server 172.16.1.217:80;
server 172.16.1.218:80;
}
upstream dynamic.wp {
server 172.16.1.215:9000;
server 172.16.1.216:9000;
}
server {
listen 80;
server_name localhost;
access_log logs/php-access.log main;
error_log logs/php-error.log warn;
# location ~ \.php$ {
# 不能这么写,因为首页访问没有具体传递index.php,与JAVA隐藏后缀类似
location / {
fastcgi_pass dynamic.wp;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /dy/php/html$fastcgi_script_name;
include fastcgi_params;
}
location ~ \.(html|css|js|jpg|png|gif)$ {
proxy_pass http://static.wp;
}
}
ngx_http_fastcgi_module模块将请求传递给FastCGI服务器。
fastcgi_param指令设置FastCGI的参数,SCRIPT_FILENAME为key,值为php文件绝对路径
$document_root等同于root指令的值,$fastcgi_script_name等同于URI,即"/index.php"
/dy/php/html是php-fpm服务器上的网站程序目录。
5.4 发布代码
1 上传项目代码,在172.16.1.215节点上操作
# cd /dy/php/html/
# tar -xzf wordpress-5.6.2.tar.gz
# rm -f wordpress-5.6.2.tar.gz
# mv wordpress/* .
# ls wordpress/
# rm -rf wordpress/
# chown -R nginx.nginx /dy/php/html/
# systemctl restart php-fpm.service
2 安装服务
在172.16.1.213节点上创建端口为80的nginx服务用于初始化wordpress项目包。
之前80的服务先备份下。
# cat /usr/local/nginx/conf/conf.d/wp.conf
server {
listen 80;
server_name localhost;
location / {
fastcgi_pass 172.16.1.215:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /dy/php/html$fastcgi_script_name;
include fastcgi_params;
}
location ~ \.(html|css|js|jpg|png|gif)$ {
root html;
index index.html index.htm;
}
}
# systemctl restart nginx.service
访问wordpress:http://172.16.1.213/
3 分发项目包,在172.16.1.215节点上操作
# scp -rp /dy/php/html/* root@172.16.1.216:/dy/php/html/
# scp -rp /dy/php/html/* root@172.16.1.217:/static/php/html/
4 挂载磁盘到动态服务器上,在172.16.1.215、216节点上操作
# rm -rf /dy/php/html/wp-content/uploads/*
# yum install glusterfs-fuse -y
# mount -t glusterfs 172.16.1.221:/gv0/wp-content/uploads /dy/php/html/wp-content/uploads
# df -hT
172.16.1.221:gv0/wp-content/uploads fuse.glusterfs 58G 2.7G 56G 5% /dy/php/html/wp-content/uploads
# echo "172.16.1.221:/gv0/wp-content/uploads /dy/php/html/wp-content/uploads glusterfs defaults 0 0" >> /etc/fstab
# chown -R nginx.nginx /dy/php/html/
5 补充wp-conifg.php中配置wordpress连接地址
define('WP_HOME', 'http://172.16.1.213' );
define('WP_SITEURL', 'http://172.16.1.213' );
5.5 测试
连续访问网站的URL:http://172.16.1.213/
[root@lb7-01 ~]# tailf /usr/local/nginx/logs/php-access.log
6 LVS DR RS配置
在172.16.1.213、214节点上操作
6.1 脚本文件
# cat /root/lvs-dr-real.sh
#!/bin/bash
source /etc/profile
VIP1=172.16.1.200
NIC1="lo:0"
case $1 in
start)
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
ifconfig $NIC1 $VIP1 netmask 255.255.255.255 broadcast $VIP1 up
route add -host $VIP1 dev $NIC1
;;
stop)
echo 0 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 0 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 0 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 0 > /proc/sys/net/ipv4/conf/lo/arp_announce
ifconfig $NIC1 down
;;
status)
if ifconfig $NIC1 |grep $VIP1 &> /dev/null; then
echo "$NIC1 is configured."
else
echo "$NIC1 not configured."
fi
;;
*)
echo "Usage: $0 {start|stop|status}"
exit 1
esac
6.2 执行脚本文件并加入到开机自启动
# chmod +x /root/lvs-dr-real.sh
# /root/lvs-dr-real.sh start
# ip addr
# chmod +x /etc/rc.d/rc.local
# echo "/root/lvs-dr-real.sh start" >> /etc/rc.local
7 四层负载均衡
7.1 LB4-01
在172.16.1.211节点上操作
1 安装keepalived
# yum install keepalived -y
# cp /etc/keepalived/keepalived.conf{,.bak}
# yum install ipvsadm -y
# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived
# 全局配置
global_defs {
# 运行keepalived的一个标识,多个集群设置不同
router_id LVS_RR
}
# vrrp_instance 说明了VRRP的一些特征,比如主从、VRID等
vrrp_instance VI_1 {
# 指定实例初始状态,实际的MASTER和BACKUP是选举决定的
state MASTER
# 指定实例绑定的网卡
interface eth1
# 设置VRID标记,每个实例是唯一的(0..255)
virtual_router_id 52
# 设置优先级,优先级高的会被竞选为Master,Master要高于BACKUP至少50
priority 150
# 检查的时间间隔,默认1s
advert_int 1
# 设置认证
authentication {
# 认证方式使用PASS
auth_type PASS
# 认证的密码
auth_pass 1111
}
# 设置VIP
virtual_ipaddress {
# 可以设置多个,每行一个,用于切换时的地址绑定
172.16.1.200/24 dev eth1 label eth1:1
}
}
#########################################################
# 虚拟服务器virtual_server定义块,该部分是用来管理LVS的,
# 是实现keepalived和LVS相结合的模块,real_server是该模块
# 的子模块,可设置多个。
#########################################################
# VIP地址,要和vrrp_instance模块中的virtual_ipaddress地址一致
virtual_server 172.16.1.200 80 {
# 健康检查时间间隔
delay_loop 6
# lvs调度算法rr、wrr、lc、wlc、lblc、sh、dh
lb_algo rr
# 负载均衡转发规则NAT|DR|RUN
lb_kind DR
# 使用的协议
protocol TCP
# RS的真实IP地址
real_server 172.16.1.213 80 {
# 四层健康检查
TCP_CHECK {
connect_port 80 # 连接远程服务器的TCP端口
connect_timeout 3 # 连接远程服务器超时时间
nb_get_retry 3 # 最大重试次数
delay_before_retry 3 # 连续两个重试之间的延迟时间
}
}
# RS的真实IP地址
real_server 172.16.1.214 80 {
# 四层健康检查
TCP_CHECK {
connect_port 80 # 连接远程服务器的TCP端口
connect_timeout 3 # 连接远程服务器超时时间
nb_get_retry 3 # 最大重试次数
delay_before_retry 3 # 连续两个重试之间的延迟时间
}
}
}
# systemctl start keepalived.service
# systemctl status keepalived.service
# ip addr
# ipvsadm -L -n
7.2 LB4-02
在172.16.1.212节点上操作
1 安装keepalived
# yum install keepalived -y
# cp /etc/keepalived/keepalived.conf{,.bak}
# yum install ipvsadm -y
# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived
# 全局配置
global_defs {
# 运行keepalived的一个标识,多个集群设置不同
router_id LVS_RR
}
# vrrp_instance 说明了VRRP的一些特征,比如主从、VRID等
vrrp_instance VI_1 {
# 指定实例初始状态,实际的MASTER和BACKUP是选举决定的
state BACKUP
# 指定实例绑定的网卡
interface eth1
# 设置VRID标记,每个实例是唯一的(0..255)
virtual_router_id 52
# 设置优先级,优先级高的会被竞选为Master,Master要高于BACKUP至少50
priority 100
# 检查的时间间隔,默认1s
advert_int 1
# 设置认证
authentication {
# 认证方式使用PASS
auth_type PASS
# 认证的密码
auth_pass 1111
}
# 设置VIP
virtual_ipaddress {
# 可以设置多个,每行一个,用于切换时的地址绑定
172.16.1.200/24 dev eth1 label eth1:1
}
# 节点变为master时执行发送邮件的脚本
notify_master /etc/keepalived/send_mail.sh
}
#########################################################
# 虚拟服务器virtual_server定义块,该部分是用来管理LVS的,
# 是实现keepalived和LVS相结合的模块,real_server是该模块
# 的子模块,可设置多个。
#########################################################
# VIP地址,要和vrrp_instance模块中的virtual_ipaddress地址一致
virtual_server 172.16.1.200 80 {
# 健康检查时间间隔
delay_loop 6
# lvs调度算法rr、wrr、lc、wlc、lblc、sh、dh
lb_algo rr
# 负载均衡转发规则NAT|DR|RUN
lb_kind DR
# 使用的协议
protocol TCP
# RS的真实IP地址
real_server 172.16.1.213 80 {
# 四层健康检查
TCP_CHECK {
connect_port 80 # 连接远程服务器的TCP端口
connect_timeout 3 # 连接远程服务器超时时间
nb_get_retry 3 # 最大重试次数
delay_before_retry 3 # 连续两个重试之间的延迟时间
}
}
# RS的真实IP地址
real_server 172.16.1.214 80 {
# 四层健康检查
TCP_CHECK {
connect_port 80 # 连接远程服务器的TCP端口
connect_timeout 3 # 连接远程服务器超时时间
nb_get_retry 3 # 最大重试次数
delay_before_retry 3 # 连续两个重试之间的延迟时间
}
}
}
# chmod +x send_mail.sh
# systemctl start keepalived.service
# ip addr
# ipvsadm -L -n
7.3 访问测试
# http://172.16.1.200/
# 在172.16.1.211节点上查看lvs负载均衡调度信息
[root@lb4-01 ~]# ipvsadm -L -n
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 172.16.1.200:80 rr
-> 172.16.1.213:80 Route 1 0 1
-> 172.16.1.214:80 Route 1 2 1
注意:
本实验使用的php应用是wordpress,由于wordpress应用自带session共享,且自带固定的URL地址,使用vip登录时会跳转到RS,但是整体实验的架构逻辑是没有问题的。
8 补充
8.1 tomcat部署
在172.16.1.215、216节点上操作
1 配置JDK环境变量
# tar -xzf jdk-8u45-linux-x64.tar.gz
# mv jdk1.8.0_45/ /usr/local/jdk
# cat >>/etc/profile<< EOF
export JAVA_HOME=/usr/local/jdk
export CLASSPATH=\$JAVA_HOME/lib/tools.jar:\$JAVA_HOME/jre/lib/rt.jar
export PATH=\$JAVA_HOME/bin:\$PATH
EOF
# source /etc/profile
# java -version
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)
2 安装tomcat
# tar -xzf apache-tomcat-8.5.37.tar.gz
# mv apache-tomcat-8.5.37/ /usr/local/tomcat/
# rm -rf /usr/local/tomcat/webapps/*
# cat /usr/lib/systemd/system/tomcat.service
# [unit] 配置了服务的描述,规定了在network启动之后执行
# [service] 配置服务的pid,服务的启动,停止,重启
# [install] 配置了使用用户
[Unit]
Description=tomcat Server 8.5
#After=syslog.target network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
Environment="JAVA_HOME=/usr/local/jdk"
PIDFile=/usr/local/tomcat/tomcat.pid
ExecStart=/usr/local/tomcat/bin/startup.sh
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/usr/local/tomcat/bin/shutdown.sh
PrivateTmp=true
Restart=on-failure
[Install]
WantedBy=multi-user.target
# vim /usr/local/tomcat/bin/catalina.sh
# Copy CATALINA_BASE from CATALINA_HOME if not already set
[ -z "$CATALINA_BASE" ] && CATALINA_BASE="$CATALINA_HOME"
CATALINA_PID="$CATALINA_BASE/tomcat.pid"
# systemctl daemon-reload
# systemctl start tomcat.service
# systemctl enable tomcat.service
# df -hT
172.16.1.221:/gv0 fuse.glusterfs 58G 2.7G 56G 5% /usr/local/tomcat/webapps
3 安装服务
在172.16.1.215节点上操做
#/usr/local/tomcat/webapps/ROOT/
# systemctl restart tomcat.service
# 访问项目进行初始化
注意:
172.16.1.216节点上的动态tomcat服务也要重启一下,访问172.16.1.213
登录jpress时,无法通过验证码登录,这是因为session不共享的原因。由
于jpress不支持session共享,所以lb-7上使用ip_hash。
访问172.16.1.217、218节点静态文件出现403,需要授权
# chmod 777 /usr/local/tomcat/webapps/
4 Tomcat基于Redis实现Session共享
# 参考文档
https://github.com/cc-chen/tomcat8.5-redis-session-manager
8.2 php优化
1 开启PHP优化加速组件
# ls /usr/local/php/lib/php/extensions/no-debug-non-zts-20131226/
opcache.a opcache.so redis.so
# 在编译php的时候开启
[root@dy-web01 php-5.6.34]# ./configure --help | grep opcache
--enable-opcache Enable Zend OPcache support
# 编译php时没有开启,使用手动方式开启
# vim /usr/local/php/etc/php.ini
opcache.enable=1
opcache.memory_consumption=128
;extension=php_shmop.dll
zend_extension=opcache.so
# systemctl restart php-fpm.service
# http://172.16.1.213/phpinfo.php
2 php-fpm.conf优化
# vim /usr/local/php/etc/php-fpm.conf
8.3 tomcat优化
参考文档
https://blog.51cto.com/lizhenliang/1763866
# vim /usr/local/tomcat/conf/server.xml
<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="1000"
minSpareThreads="20"
maxSpareThreads="100"
acceptCount="900"
disableUploadTimeout="true"
connectionTimeout="20000"
URIEncoding="UTF-8"
enableLookups="false"
redirectPort="8443"
compression="on"
compressionMinSize="1024"
compressableMimeType="text/html,text/xml,text/css,text/javascript" />
# vim /usr/local/tomcat/bin/catalina.sh
#!/bin/sh
JAVA_OPTS="-server -Xms256m -Xmx1024m -XX:+UseConcMarkSweepGC -XX:-PrintGC -XX:-PrintGCDetails -XX:-PrintGCTimeStamps -Xloggc:../logs/gc.log"
# 一般2个GB
# ps -ef | grep tomcat
# jmap -heap 3694
8.4 nginx缓存
1 cat /usr/local/nginx/conf/nginx.conf
user nginx;
# worker进程的数量
worker_processes auto;
# 绑定Nginx的worker进程到指定的CPU内核
worker_cpu_affinity auto;
# error_log logs/error.log warn;
pid logs/nginx.pid;
# worker进程可以打开的最大句柄描述符个数
# 调整至1w以上,负荷较高建议2-3w以上
worker_rlimit_nofile 65535;
events {
use epoll;
# 每个worker进程的最大连接数
# worker_processes乘以worker_connections等于nginx总体最大连接数
worker_connections 10240;
}
http {
include mime.types;
default_type application/octet-stream;
# 统一使用utf-8字符集
charset utf-8;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" $upstream_addr';
# access_log logs/access.log main;
# Core module
sendfile on;
# 静态资源服务器建议打开
tcp_nopush on;
# 动态资源服务建议打开,需要打开keepalived
tcp_nodelay on;
keepalive_timeout 65;
# sendfile on;
# tcp_nopush on;
# tcp_nodelay on;
# keepalive_timeout 65;
fastcgi_connect_timeout 30000;
fastcgi_send_timeout 30000;
fastcgi_read_timeout 30000;
fastcgi_buffer_size 256k;
fastcgi_buffers 8 256k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
fastcgi_intercept_errors on;
##cache##
client_header_timeout 60s;
client_body_timeout 60s;
client_max_body_size 10m;
client_body_buffer_size 1m;
# 默认on,是否缓存后端服务器响应
proxy_buffering on;
# 默认60s,与后端服务器建立连接超时时间
proxy_connect_timeout 60s;
# 默认60s,读取后端服务器响应超时时间
proxy_read_timeout 300s;
# 默认60s,发送请求到后端服务器超时时间
proxy_send_timeout 300s;
# 缓存区大小
proxy_buffer_size 64k;
# 指定多少与多大缓存区来缓存后端服务器响应
proxy_buffers 4 128k;
# 忽略缓存cookie
proxy_ignore_headers Set-Cookie;
proxy_busy_buffers_size 128k;
proxy_temp_file_write_size 1m;
proxy_temp_path /home/temp_dir;
# 缓存目录 目录层级 缓存区名称和大小 移除多长时间未访问的缓存数据 最大占用磁盘空间
proxy_cache_path /home/cache levels=1:2 keys_zone=cache_one:200m inactive=1d max_size=30g;
# 添加请求头Host字段值为本机IP地址
proxy_set_header Host $host;
# 添加请求头X-Real-IP值为客户端IP
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Gzip module
gzip on;
gzip_disable "MSIE [1-6]\.";
gzip_http_version 1.1;
# gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
# gzip_http_version 1.1;
gzip_comp_level 9;
gzip_types text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php;
gzip_vary on;
# 上传文件大小限制
# client_max_body_size 8m;
# 隐藏nginx版本号
server_tokens off;
# 关闭目录浏览功能
autoindex off;
# Virtal Server
include conf.d/*.conf;
}
2 cat /usr/local/nginx/conf/conf.d/java.conf
upstream static.jp {
ip_hash;
server 172.16.1.217:80;
server 172.16.1.218:80;
}
upstream dynamic.jp {
ip_hash;
server 172.16.1.215:8080;
server 172.16.1.216:8080;
}
server {
listen 80;
server_name localhost;
access_log logs/jp-access.log main;
error_log logs/jp-error.log warn;
location / {
proxy_pass http://dynamic.jp;
}
location ~ \.(html|css|js|jpg|png|gif|ico|flv|swf)$ {
proxy_pass http://static.jp;
# 禁止所有的proxy_redirect指令
proxy_redirect off;
# 添加响应头,测试是否命中
add_header X-Cache $upstream_cache_status;
# 指定缓存区名称,和nginx.conf中配置的缓存区名要一致
proxy_cache cache_one;
# 为不同状态码设置缓存时间
proxy_cache_valid 200 302 1h;
proxy_cache_valid 301 1d;
proxy_cache_valid any 10m;
expires 30d;
# 定义缓存的key,根据md5值为缓存文件名
# proxy_cache_key $host$uri$is_args$args;
proxy_cache_key $host$request_uri;
}
}
3 访问图片,发现图片缓存被命中
# ls -ld /home/cache/ /home/temp_dir/
drwx------ 13 nginx root 105 Mar 8 00:35 /home/cache/
drwx------ 2 nginx root 6 Mar 8 00:35 /home/temp_dir/
# ls -l /home/cache/
# ls -l /home/temp_dir/
total 0
8.5 运维优化
1 运维思维
# 网站运行速度慢解决思路
(1) 单个用户访问不了/访问慢
用户电脑有问题,用户电脑DNA解析有问题,用户网络到网站入口链路有问题。
(2) 部分用户访问不了/访问慢
可能地区性网络链路问题,某个节点有异常,没有及时剔除。
(3) 所有用户访问不了/访问慢
机房网络有问题,网站入口流量带宽饱和,数据库有问题,负载大。
(4) 静态页面访问快,动态页面访问慢,根据用户反馈的现象分析,而不是马上解决问题。
2 磁盘IO调度算法选择
# cat /sys/block/sda/queue/scheduler
noop [deadline] cfq
cfq # 完全公平的调度算法
deadline # 适用于数据库
noop # io队列,用于SSD
3 少用swap分区使用
OOM KILL掉使用内存最大进程
# cat /proc/sys/vm/swappiness
0 # 默认是30
cat >> /etc/sysctl.conf << EOF
vm.swappiness = 0
EOF
4 增大打开文件描述符数量
ulimit -SHn 65535
cat >> /etc/security/limits.conf << EOF
* soft nofile 65535
* hard nofile 65535
EOF
5 内核参数优化
cat >> /etc/sysctl.conf << EOF
net.ipv4.tcp_tw_reuse = 1
net.ipv4.ip_local_port_range = 1024 65000
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_tw_buckets = 20480
net.ipv4.tcp_max_syn_backlog = 20480
net.core.netdev_max_backlog = 262144
net.ipv4.tcp_fin_timeout = 20
EOF
8.5 lvs模式
1 说明
2 NAT
3 DR和TUN
DR:RS抑制ARP请求
4 FULLNAT
5 lvs在360的应用