一、nginx代理
1、什么是代理
正向代理:作用在浏览器和客户端。是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端必须要进行一些特别的设置才能使用正向代理。
正向代理类似一个跳板机,代理访问外部资源。
正向代理的好处:(1)能够隐藏用户的信息(前提是代理服务器隐藏用户信息,高匿代理),因为服务器只知道正向代理的信息,不知道用户的信息。(2)访问被墙的网站。(3)可以做缓存,加速访问资源。(4)对客户端访问授权,上网进行认证。
反向代理:作用在服务器。例如nginx,是给服务器进行分流导航。
反向代理的好处:1. 保证内网(服务器真实的网络)的安全,可以使用反向代理提供WAF功能,阻止web攻击。2.负载均衡,通过反向代理服务器来优化网站的负载,分流功能。
总体图:
2、反向代理支持模式
http 用户请求 响应 JAVA
smtp
websocket 用户可以请求, 服务端响应 服务端可以推送数据
uwsgi Python
fastcgi PHP
https
3、代理配置语法
proxy_pass
proxy_pass http://127.0.0.1:8080;
代理节点的配置 ******* 主机 10.0.0.100 *******
[root@proxy ~]# systemctl disable firewalld [root@proxy ~]# systemctl stop firewalld [root@proxy ~]# setenforce 0 #安装epel ginx [root@proxy ~]# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo [root@proxy ~]# yum install vim wget unzip nginx -y # 清理nginx.conf 无用的配置 # 将nginx加入开机自启 启动nginx [root@proxy ~]# systemctl start nginx [root@proxy ~]# systemctl enable nginx # 编写proxy配置文件 [root@proxy ~]# vim /etc/nginx/conf.d/proxy_proxy.workedu.com.conf server { listen 80; server_name proxy.workedu.com; location / { proxy_pass http://10.0.0.201; # 后端是什么端口根本不重要 proxy_set_header Host $http_host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_http_version 1.1; } } # 检查语法,重载服务 [root@proxy ~]# nginx -t [root@proxy ~]# systemctl restart nginx
用户请求代理
抓包分析: 提炼了几个参数:
proxy_set_header Host $http_host; # 将用户请求的域名携带到后端
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 将用户的真实IP地址,携带到后端,后端有对应的变量解析结果
proxy_http_version 1.1; # 代理请求后端默认走http1.0, 可以调整为http1.1 长连接
web节点的配置 ******* 10.0.0.201 *******
[root@node2 conf.d]# cat proxy.workedu.com.conf server { listen 80; server_name proxy.workedu.com; root /code/proxy; location / { index index.html; } } [root@node2 conf.d]# mkdir /code/proxy -p [root@node2 conf.d]# echo "node2...." >> /code/proxy/index.html [root@node2 conf.d]# nginx -t [root@node2 conf.d]# systemctl reload nginx
二、负载均衡
代理并没有解决代理多个web节点,代理延伸出来的一个负载均衡可以实现代理多个web节点
1、什么是负载均衡
负载均衡Load Balance,指的是将工作任务进行平衡,分摊到多个操作单元上运行。
2、为什么需要使用负载均衡
当我们的web服务器直接面向用户,往往要承载大量并发请求,单台服务器难以负荷,我使用多台web服务器组成集群,前端使用Nginx负载均衡,将请求分散的打到我们的后台服务器集群中,实现负载的分发。从而提升整体性能,以及系统的容灾能力。
2.1、负载均衡能实现的应用场景一:四层负载均衡
所谓四层负载均衡指的是OSI七层模型中的传输层,四层仅需要对客户端的请求进行TCP/IP协议的包转发就可以实现负载均衡.四层负载均衡的性能极好、因为只需要底层进行转发处理,而不需要进行一些复杂的逻辑。
2.2、负载均衡能实现的应用场景二:七层负载均衡
七层负载均衡它是在应用层,那么它可以完成很多方面的协议请求,比如我们说Http应用负载均衡,它可以实现http头信息的改写、安全应用规则控制、URI匹配规则控制、及rewrite等功能,所以在应用层里面可以做的内容就更多了。
2.3、四层负载均衡与七层负载均衡区别
四层负载均衡数据包在底层就进行了开发,而七层负载均衡数据包则是在最顶层进行分发,由此可以看出,七层负载均衡效率没有四层负载均衡效率高。
七层负载均衡更贴近于服务,如http协议就是七层协议,我们可以用Nginx可以作URI路径规则匹配、head改写、Rewrite、会话保持等,这些是四层负载均衡无法实现的。
3、Nginx负载均衡配置场景
nginx要实现负载均衡需要用到proxy_pass和upstream两个模块
nginx负载均衡与Nginx反向代理不同地方在于,nginx代理仅代理一台服务器,而Nginx负载均衡则是将客户端请求通过proxy_pass代理至一组upstream资源池
upstream 定义虚拟资源池 ( 将应用服务器逻辑定义为资源池 )
proxy_pass 代理
Syntax: upstream name { ... } Default : - Context: http # upstream例 upstream backend { server backend1.example.com weight=5; server backend2.example.com:8000; server unix:/tmp/backend3; server backup1.example.com:8000 backup; } server { location / { proxy_pass http://backend; } }
三、多台应用服务器节点的配置
node1: 10.0.0.200 node2: 10.0.0.201 域名: proxy.workedu.com
node1 nginx配置
vim /etc/nginx/conf.d/proxy.workedu.com.conf
server { listen 80; server_name proxy.workedu.com; root /code/proxy; location / { index index.html; } }
mkdir /code/proxy -p echo "node1...." > /code/proxy/index.html systemctl reload nginx
node2 nginxx配置:
vim /etc/nginx/conf.d/proxy.workedu.com.conf
server { listen 80; server_name proxy.workedu.com; root /code/proxy; location / { index index.html; } }
mkdir /code/proxy -p echo "node2...." > /code/proxy/index.html systemctl reload nginx
1、通过nginx负载均衡进行轮训调度
proxy: 10.0.0.100 域名: proxy.workedu.com
vim /etc/nginx/conf.d/proxy_proxy.workedu.com.conf
upstream node { server 10.0.0.200:80; server 10.0.0.201:80; } server { listen 80; server_name proxy.workedu.com; location / { proxy_pass http://node; proxy_set_header Host $http_host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_http_version 1.1; } }
nginx -t
systemctl reload nginx
2、调度算法
1、轮询: 默认 2、加权轮询: upstream node { server 10.0.0.200:80 weight=5; server 10.0.0.201:80 weight=1; } 静态的,固定200分发5次, 201分发1次,没有办法做到动态 3、ip_hash: 固定将请求调度至某一个节点. ( session会话保存 ) upstream node { ip_hash; server 10.0.0.200:80; server 10.0.0.201:80; }
轮训存在的问题:
""" nginx轮训到node1存储session id返回cookie存储在浏览器 浏览器携带cookie第二次访问nginx轮训到node2发现没有session与cookie对应 再返回一个cookie值存储在浏览器 导致用户永远都登录不上 """
为了解决这个问题,有了ip_hash的调度算法(解决session会话保持)
问题:
# 如果来源的都是同一个IP地址,则会造成某一个节点非常的繁忙,而其他的节点没有流量,造成负载不均衡的现象.
解决:
""" 用户访问时,nginx分发到节点,节点先去Redis查找有没有对应的session_id,没有将cookie写入浏览器, 浏览器下次访问携带cookie,另一节点也先去Redis中查找,发现有与cookie对应的session_id,登录成功 """
四、nginx_proxy + web应用节点(多台) + Redis会话保持
1、搭建好应用节点 ( 所有节点保持一致 )
wget https://files.phpmyadmin.net/phpMyAdmin/5.0.3/phpMyAdmin-5.0.3-all-languages.zip
2、准备phpmyadmin的Nginx配置文件
server { listen 80; server_name phpmyadmin.workedu.com; root /code/phpmyadmin; location / { index index.php; } location ~ .php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } }
systemctl reload nginx
unzip phpMyAdmin-5.0.3-all-languages.zip
mv phpMyAdmin-5.0.3-all-languages /code/phpmyadmin
3、配置phpmyadmin连接数据库地址
cp /code/phpmyadmin/config.sample.inc.php /code/phpmyadmin/config.inc.php
vim /code/phpmyadmin/config.inc.php /* Server parameters */ $cfg['Servers'][$i]['host'] = '10.0.0.202';
4、授权session存储本地目录为进程的用户身份
chown -R nginx.nginx /var/lib/php/session
5、部署node2节点的phpmyadmin, 需要将代码和nginx配置拷贝一份
scp -rp root@10.0.0.200:/code/phpmyadmin /code/ chown -R nginx.nginx /code/phpmyadmin/ scp root@10.0.0.200:/etc/nginx/conf.d/phpadmin.workedu.com.conf /etc/nginx/conf.d/ chown -R nginx.nginx /var/lib/php/session/
nginx -t
systemctl reload nginx
6、为应用节点,接入负载均衡
vim /etc/nginx/conf.d/proxy_phpadmin.workedu.com.conf
upstream php { server 10.0.0.200:80; server 10.0.0.201:80; } server { listen 80; server_name phpmyadmin.workedu.com; location / { proxy_pass http://php; proxy_set_header Host $http_host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
7、检查轮询是否会造成无法登陆情况, 配置IP_hash测试是否能正常登陆(可试可不试)
轮询一定会造成无法登陆成功. 可以采用ip_hash的方式解决. upstream php { ip_hash; server 10.0.0.200:80; server 10.0.0.201:80; }
8、采用Redis共享的方式来解决会话无法登陆的问题, 需要先将负载均衡恢复至轮询模式,然后在继续.
1、安装Redis 10.0.0.202
yum install redis -y vim /etc/redis.conf # 添加本机的内网IP地址 ( 不要写错了 )
bind 127.0.0.1 10.0.0.202
systemctl enable redis systemctl start redis netstat -lntp | grep redis # tcp 0 0 10.0.0.202:6379 0.0.0.0:* LISTEN 10699/redis-server # tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 10699/redis-server
2、通过其他的节点测试是否能正常访问Redis
yum install redis -y
redis-cli -h 10.0.0.202
3、配置应用节点接入Redis, [ 应用程序php必须有redis的模块,否则无法正常连接 ] 两个节点配置一样,都需要操作
# 将应用程序解析器连接至 Redis # vim /etc/php.ini [Session] ;session.save_handler = files #注释掉 session.save_handler = redis session.save_path = "tcp://10.0.0.202:6379?weight=1&timeout=2.5" # 注释如下两行内容 [root@oldboy-pythonedu ~]# vim /etc/php-fpm.d/www.conf ;php_value[session.save_handler] = files ;php_value[session.save_path] = /var/lib/php/session # 重启php-fpm [root@oldboy-pythonedu ~]# systemctl restart php-fpm
测试是否能正常登陆,然后检查浏览器中的session是否与redis中存储的session一致.
[root@node-mysql ~]# redis-cli 127.0.0.1:6379> keys * 1) "python_key" 2) "PHPREDIS_SESSION:f0ad1e364f79a85bd93b46883403f6ec"