• 03-Nginx代理负载均衡


    一、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"
  • 相关阅读:
    Python 压缩图片至指定大小
    nginx 服务器自签https协议 (Let’s Encrypt)
    Django 批量创建app
    常见的设计模式(python )———适配器模式
    带你完全理解Python中的metaclass,type,class之间的恩怨情仇...
    常见的设计模式(python)———单例模式(转载)
    常见的设计模式(python)———工厂模式
    常见的设计模型(python)——建造者模型
    Django-restframework 概述及目录
    Java多线程开发
  • 原文地址:https://www.cnblogs.com/kongxiangqun/p/13812238.html
Copyright © 2020-2023  润新知