WEB服务与NGINX(25)- LNMP架构-WEB集群部署phpmyadmin



1 LNMP架构-WEB集群部署phpmyadmin

1.1 WEB集群架构需求分析

  • 扩展多台WEB服务器的需求:

    单台服务器能支撑的访问量一般是有限的,我们一般需要使用多台WEB服务器组成集群对外提供服务。因此配置多台WEB服务器可以增加架构的稳定性,可扩展性,并且提升用户的访问速度和承载更多的并发量。

  • WEB集群中负载均衡的作用:

    在使用WEB集群环境时,我们一般需要使用负载均衡设备放置在前端,对用户的流量按照一定的算法调度后WEB集群中,可以使用nginx的七层均衡功能,或者LVS的四层负载均衡。

  • 负载均衡的会话共享

    当用户登陆一个网站服务器,网站服务器会将用户的登陆信息存储下来,存储下来的内容叫 Session,以保证我们能够一直处于”登陆在线“状态。

    由于我们使用的是负载均衡轮询机制,会导致用户请求分散在不同的节点,从而造成会话无法保持。

    假设用户A通过负载均衡登陆了网站,此时会话信息存储在A节点,那么当它一刷新,负载均衡会将请求分发给B节点,那么B节点没有用户A的登陆信息,就会提示用户A登陆,当A用户点击登陆时又会将请求分发给C节点,从而造成用户A无法实现会话保持。

  • 如何实现会话保持

    • 粘性session:指Ngnix每次都将同一用户的所有请求转发至同一台服务器上,即Nginx的IP_hash调度算法,此种方式无法很好实现流量负载。
    • session复制:每次session发生变化,就广播给集群中的服务器,使所有的服务器上的 session相同。
    • session共享:缓存session至内存数据库中,使用redis或memcached实现,推荐使用。
    • session持久化:将session存储至数据库中,像操作数据一样操作session,类似于wordpress/wecenter的机制,将会话信息保存在数据库中,不清理数据库,则用户登录永不掉线。不适合大量用户登录的场景。
    • 基于用户端cookie的方式。

1.2 WEB集群架构环境

LNMP实验场景如下:

  • linux系统版本:CentOS 7.8 X86_64

  • 客户端:192.168.20.1

  • nginx负载均衡:主机名:nginx01,地址:192.168.20.20,nginx版本:1.20.1

  • WEB服务器01:主机名:nginx02,地址:192.168.20.22,nginx版本:1.20.1

  • WEB服务器02:主机名:nginx03,地址:192.168.20.23,nginx版本:1.20.1

  • php-fpm:和WEB服务器nginx共用一台主机,版本7.3.16

  • mysql服务器:主机名:mysql01,地址:192.168.20.50,版本:mariadb-10.5.2

  • redis服务器:主机名redis01,地址:192,168.20.61,版本:3.2.12

  • phpmyadmin:版本:4.9.5

    (使用phpmyadmin的原因时该软件将用户的登录信息保存在本地,不像wordpress一样,将用户的登录信息保存在数据库中,可以演示会话缓存的效果。)

image

1.3 部署mariadb

使用二进制方式部署mariadb,步骤参考前面小节,此处省略。

允许数据库的admin账号可以远程登录

[root@mysql01 ~]# mysql -uroot -p123456
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 130
Server version: 10.5.2-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> GRANT ALL PRIVILEGES ON *.* TO "root"@"192.168.20.%" IDENTIFIED BY "123456";
Query OK, 0 rows affected (0.023 sec)

MariaDB [(none)]> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.015 sec)

1.4 部署web服务器nginx

WEB01和WEB02的配置完全相同,此处以一台为例进行说明,编译安装nginx的方式见前面小节,此处省略。

#nginx的配置文件如下:
[root@nginx02 ~]# cat /etc/nginx/nginx.conf
user  nginx;
worker_processes  auto;

events {
    worker_connections  10240;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

log_format access_json '{ "@timestamp": "$time_iso8601", '  
'"remote_addr": "$proxy_add_x_forwarded_for", '  
'"referer": "$http_referer", '  
'"request": "$request", '  
'"status": $status, '  
'"bytes":$body_bytes_sent, '  
'"agent": "$http_user_agent", '  
'"x_forwarded": "$http_x_forwarded_for", '  
'"upstr_addr": "$upstream_addr",'  
'"upstr_host": "$upstream_http_host",'  
'"upstreamtime": "$upstream_response_time" }'; 

    server_tokens off;
    fastcgi_cache_path /data/nginx/fastcgi_cache levels=1:1:1 keys_zone=fastcgi_cache:250m inactive=10m max_size=1g;
    sendfile        on;
    keepalive_timeout  65;

include /etc/nginx/conf.d/*.conf;
}        
[root@nginx02 ~]# cat /etc/nginx/conf.d/xuzhichao.conf 
server {
	listen 80 default_server;
	server_name www.xuzhichao.com;
	access_log /var/log/nginx/access_xuzhichao.log access_json;
	charset utf-8,gbk;	
	
	#防盗链
	valid_referers none blocked server_names *.b.com  b.*  ~\.baidu\.  ~\.google\.;
	
	if ( $invalid_referer ) {
		return 403;	
	}

	client_max_body_size 10m;

	#浏览器图标
	location = /favicon.ico {
		root /data/nginx/xuzhichao;
	}

	location / {
		root /data/nginx/xuzhichao;
		index index.html index.php;
	}

	location ~ \.php$ {
		root /data/nginx/xuzhichao;

		#fastcgi反向代理
		fastcgi_pass 127.0.0.1:9000;
		fastcgi_index index.php;
		fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
		fastcgi_param HTTPS on;
		fastcgi_hide_header X-Powered-By;
		include fastcgi_params;
		
		#fastcgi缓存	
		fastcgi_cache fastcgi_cache;
		fastcgi_cache_key $request_uri;
		fastcgi_cache_methods GET HEAD;
		fastcgi_cache_valid 200 301 302 30m;
		fastcgi_cache_valid any 5m;
		fastcgi_cache_min_uses 1;
		fastcgi_keep_conn on;
	}

	location ~ ^/(ping|pm_status)$ {
		access_log off;
		allow 192.168.20.0/24;
		deny all;
		fastcgi_pass 127.0.0.1:9000;
		fastcgi_param SCRIPT_FILENAME $fastcgi_script_name;
		include fastcgi_params;
	}

	location = /nginx_status {
		access_log off;
		allow 192.168.20.0/24;
		deny all;
		stub_status;
	}
}

#检测语法,重启nginx
[root@nginx02 xuzhichao]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@nginx02 xuzhichao]# systemctl reload nginx.service

#下载favicon.ico文件:
[root@nginx02 ~]# cd /data/nginx/xuzhichao/
[root@nginx02 xuzhichao]# wget https://www.baidu.com/favicon.ico

1.5 部署redis

#1.安装redis并启动服务
[root@redis01 ~]# yum install redis

#2.修改redis的配置文件:
[root@redis01 ~]# sed -i '/^bind/c bind 127.0.0.1 172.16.1.51' /etc/redis.conf

#3.启动redis服务
[root@redis01 ~]# systemctl start redis

[root@redis01 ~]# ss -ntlp
State      Recv-Q Send-Q  Local Address:Port                 Peer Address:Port              
LISTEN     0      128     192.168.20.61:6379                            *:*                   users:(("redis-server",pid=1939,fd=6))
LISTEN     0      128         127.0.0.1:6379                            *:*                   users:(("redis-server",pid=1939,fd=4))

1.6 部署php-fpm

WEB01和WEB02的php-fpm的配置完全相同,此处以一台为例进行说明,编译安装php-fpm的方式见前面小节,此处省略。

1.6.1 php安装扩展模块redis

php的redis模块下载路径http://pecl.php.net/package-stats.php

#1.安装php-pecl-redis
[root@nginx02 ~]# yum install php-pecl-redis

#2.解压缩redis扩展包
[root@nginx02 ~]# cp redis-4.2.0.tgz /usr/local/src/
[root@nginx02 ~]# cd /usr/local/src/
[root@nginx02 src]# tar xf redis-4.2.0.tgz 
[root@nginx02 src]# cd redis-4.2.0/

#3.生成配置文件:
[root@nginx02 redis-4.2.0]# ll | wc -l
29
[root@nginx02 redis-4.2.0]# /app/php/bin/phpize 
Configuring for:
PHP Api Version:         20180731
Zend Module Api No:      20180731
Zend Extension Api No:   320180731
[root@nginx02 redis-4.2.0]# ll | wc -l
44

#4.编译安装:
[root@nginx02 redis-4.2.0]# ./configure --with-php-config=/app/php/bin/php-config
[root@nginx02 redis-4.2.0]# make
[root@nginx02 redis-4.2.0]# make install

#5.验证redis模块:
[root@nginx02 redis-4.2.0]# ll /app/php/lib/php/extensions/no-debug-non-zts-20180731/
total 8384
-rwxr-xr-x 1 root root 4231620 Jun 30 20:10 opcache.a
-rwxr-xr-x 1 root root 2284480 Jun 30 20:10 opcache.so
-rwxr-xr-x 1 root root 2064064 Jul  1 23:55 redis.so

#6.编辑php.ini配置文件,扩展redis.so模块
[root@nginx02 redis-4.2.0]# vim /app/php/etc/php.ini
;;;;;;;;;;;;;;;;;;;;;;
; Dynamic Extensions ;
;;;;;;;;;;;;;;;;;;;;;;
......
extension=/app/php/lib/php/extensions/no-debug-non-zts-20180731/redis.so
......

#7.重启php-fpm
[root@nginx02 redis-4.2.0]# pkill  php-fpm
[root@nginx02 redis-4.2.0]# /app/php/sbin/php-fpm -t
[02-Jul-2021 00:00:27] NOTICE: configuration file /app/php/etc/php-fpm.conf test is successful
[root@nginx02 redis-4.2.0]# /app/php/sbin/php-fpm -c /app/php/etc/php.ini

#7.准备php测试页:
[root@nginx02 nginx]# vim /data/nginx/xuzhichao/test.php
<?php
	phpinfo();
?>

验证加载redis模块是否成功:

http://www.xuzhichao.com/test.php

image

1.6.2 php相关配置文件修改

#1.将php的会话保存由原来保存到文件改为保存到redis服务器中。
[root@nginx02 ~]# vim /app/php/etc/php.ini
;session.save_handler = files
session.save_handler = redis
session.save_path = "tcp://192.168.20.61:6379"
;session.save_path = "tcp://192.168.20.61:6379?auth=PASSWORD" <==如果redis存在密码,使用该方式连接。
    
#2.重启php-fpm
[root@nginx02 ~]# pkill php-fpm
[root@nginx02 ~]# /app/php/sbin/php-fpm -c /app/php/etc/php.ini

1.7 部署负载均衡nginx

负载均衡申请HTTPS证书步骤见前面小节,此处省略。

负载均衡nginx的配置文件如下:

[root@nginx01 ~]# cat /etc/nginx/conf.d/xuzhichao.conf 
upstream webserver {
	server 192.168.20.22 weight=1 fail_timeout=5s max_fails=3;
	server 192.168.20.23 weight=1 fail_timeout=5s max_fails=3;
#	server 192.168.20.21 fail_timeout=5s max_fails=3 backup;
}

server {
	listen 443 ssl;
	listen 80;
	server_name www.xuzhichao.com;
	access_log /var/log/nginx/access_xuzhichao.log access_json;

	ssl_certificate /etc/nginx/certs/xuzhichao.crt;
	ssl_certificate_key /etc/nginx/certs/xuzhichao.key;
	ssl_session_cache shared:ssl_cache:30m;
	ssl_session_timeout 10m;

	valid_referers none blocked server_names *.b.com  b.*  ~\.baidu\.  ~\.google\.;

	if ( $invalid_referer ) {
		return 403;	
	}
	
    location / {
		root /data/nginx/html/xuzhichao;
		index index.html index.php;
		
		if ( $scheme = http ) {
			rewrite /(.*) https://www.xuzhichao.com/$1 permanent;
		}
	}

	location /phpmyadmin {
		
		if ($scheme = "http") {
			rewrite ^/phpmyadmin/(.*)$ https://www.xuzhichao.com/phpmyadmin/$1;
		} 
		
		proxy_pass http://webserver;

		proxy_set_header host $http_host;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

		proxy_connect_timeout 30;
		proxy_send_timeout 60;
		proxy_read_timeout 60;
        
        proxy_buffering on;
        proxy_buffer_size 64k;
        proxy_buffers 4 64k;
	}
}

#检查语法并重启nginx
[root@nginx01 ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@nginx01 ~]# systemctl reload nginx.service

1.8 部署phpmyadmin

在nginx02和nginx03主机上部署应用程序phpmyadmin,两台主机配置完全相同,以nginx02的配置为例进行说明:

#1.进入nginx工作目录,加压phpmyadmin程序,创建软连接。
[root@nginx02 ~]# cd /data/nginx/xuzhichao/
[root@nginx02 xuzhichao]# tar xf phpMyAdmin-4.9.5-all-languages.tar.gz
[root@nginx02 xuzhichao]# ln -sv phpMyAdmin-4.9.5-all-languages phpmyadmin

#2.修改配置文件,设置数据库主机地址:
[root@nginx02 xuzhichao]# cd phpmyadmin/
[root@nginx02 phpmyadmin]# cp config.sample.inc.php config.inc.php 
[root@nginx02 phpmyadmin]# vim config.inc.php
$cfg['Servers'][$i]['host'] = '192.168.20.50'; 

客户端访问https://www.xuzhichao.com/phpmyadmin/

页面如下:用户名,密码需要填写连接数据库的用户名密码,此处为root/123456.

image

输入用户名密码后,点击“执行”:

注意:当没有配置php-fpm的会话缓存到redis时,因为负载均衡使用的是轮询机制,每次输完用户名点击登录时会切换到另一台WEB节点,导致无法登录成功,会有如下报错:

其实时因为WEB集群缓存没有共享的原因导致。

image

按照以上步骤配置完redis缓存后,可以正常登录phpmyadmin,而且刷新页面,重新调度到另一台WEB节点时,因为会话时存储在redis服务器上,因此用户也不会掉线。

显示调度到了192.168.20.22这台主机上:

image

刷新页面后会调度到192.168.20.23这台主机上,用户没有掉线:

image

查看redis的缓存信息:

[root@redis01 ~]# redis-cli
127.0.0.1:6379> KEYS *
(empty list or set)
127.0.0.1:6379> KEYS *
127.0.0.1:6379> KEYS *
1) "PHPREDIS_SESSION:6pb9dumnsg3frtdmtiioiscub2"
2) "PHPREDIS_SESSION:dnqeflotersiohcppik3gu0noj"  <==redis为客户端分配的cookie值,若删除后客户端session失效,需要重新登录。

客户端上显示的cookie信息,刷新页面不会改变,且与redis服务器中保存的cookie值一致:

image

posted @ 2021-07-04 22:29  向往自由的独行者  阅读(280)  评论(0)    收藏  举报