【Linux】nginx代理与反向代理、负载平衡、日志

    科技2024-10-02  22

    1.代理与反向代理

    正向代理或反向代理是取决于是接收服务还是提供服务。比如说,一个人想要上网,可以借助浏览器实现与互联网交互,人与浏览器是一起的,这个是正向代理;一个人想要点餐,跟服务员说,服务员再跟厨师说,服务员是跟厨师一起的,这个是反向代理

    我们使用nginx一般做的是反向代理,即请求的服务经过nginx,再由nginx进行分发

    2 proxy_pass

    proxy_pass 指令设置代理服务器的地址和被映射的URI,地址可以是主机名或IP加端口号

    location /html/ { proxy_pass http://proxy.com; proxy_pass http://proxy.com/; }

    以上两种情况,就是最后有没有加上/的区别 当访问http://www.mysite.com/html/test.html时,两种情况代理是不一样的 分别是http://proxy.com/html/test.html和http://proxy.com/test.html

    3.uwsgi

    因为nginx善于做静态文件代理,而不擅长做动态相关代理,我们可以借助uwsgi做动态代理。另外,proxy_pass是基于七层协议请求转发的,而uwsgi_pass是基于四层协议转发,故效率更高

    安装uwsgi

    pip install uwsgi

    在配置文件的location配置段里加上

    include uwsgi_params; uwsgi_pass 代理地址;

    下面配合Django举例

    3.1 新建conf文件

    新建/etc/nginx/conf.d/8000.conf编辑如下

    server { listen 8000; # 把匹配到的所有的请求,转发 location / { # 七层协议请求转发 # proxy_pass定义出请求转发的目标服务器(被反向代理的服务器) # proxy_pass http://127.0.0.1:8001; # 四层协议转发 include uwsgi_params; uwsgi_pass 127.0.0.1:8001; } }
    3.2 重启服务
    nginx -t # 检查配置文件是否正确 systemctl restart nginx # 重启nginx服务
    3.3 七层代理转发

    如果是七层代理转发,location使用的应该是 proxy_pass, 然后直接启动Django服务器

    python3 manage.py runserver 0.0.0.0:8001
    3.3 四层代理转发

    如果是四层代理转发,location使用的应该是uwsgi_pass,并且需要配置django项目的wsgi.py

    wsgi.py(这里是指定settings配置文件,若无需要可采用默认)

    import os from django.core.wsgi import get_wsgi_application # 指定我们的配置文件 os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'meiduo_mall.settings.dev') application = get_wsgi_application()

    在wsgi.py同级目录创建uwsgi.ini文件,配置如下

    [uwsgi] # 使用Nginx连接时使用,Django程序所在服务器地址 socket=127.0.0.1:8001 # 直接做web服务器使用,Django程序所在服务器地址 # http=127.0.0.1:8001 # 项目目录 # chdir=项目路径/meiduo_project/meiduo_mall chdir=/data/meiduo_mall # 项目中wsgi.py文件的目录,相对于项目目录 wsgi-file=meiduo_mall/wsgi.py # 进程数 processes=1 # 线程数 threads=2 # uwsgi服务器的角色 master=True # 存放进程编号的文件 pidfile=uwsgi.pid # 日志文件 daemonize=uwsgi.log # 指定依赖的虚拟环境 # 方式一:使用python用户的虚拟环境 # virtualenv=/home/python/.virtualenvs/django_env # 方式二:使用root用户的虚拟环境; # 前提把python用户虚拟环境拷贝到root用户虚拟环境目录下, 命令如下: # cp -r /home/python/.virtualenvs/django_env /root/.virtualenvs/ # 然后就可以指定root下的django_env虚拟环境了 virtualenv=/root/.virtualenvs/django_env
    3.4 启动和关闭uwsgi
    uwsgi --ini uwsgi.ini # 启动uwsgi uwsgi --stop uwsgi.pid # 关闭uwsgi

    4.负载平衡

    如果一个网站的访问量比较大,一个服务可能会忙不过来,可以选择多开几个,实现负载平衡

    4.1 基本配置

    我们编辑conf文件

    upstream backend { server 127.0.0.1:8001; server 127.0.0.1:8002; } # 新增8000反向代理服务器 server { listen 8000; # 把匹配到的所有的请求,转发 location / { # 七层协议请求转发 # proxy_pass定义出请求转发的目标服务器(被反向代理的服务器) # proxy_pass http://127.0.0.1:8001; # 四层协议转发 include uwsgi_params; uwsgi_pass backend; } }

    以上代码主要增加了upstream,这是一个地址的集合列表,可以把实现负载的多个服务写到里面,然后在proxy_pass指定该集合

    4.2 均衡策略
    策略说明轮询默认的策略,按请求顺序逐一分配到不同的服务器加权轮询根据权重控制每个服务器被访问的概率ip哈希根据客户端的ip绑定服务器,下次再访问还是分配之前绑定的服务器uri哈希根据访问的URL的哈希结果分配请求其他还有很多均衡策略,还有些是商业类型的

    加权轮询

    upstream meiduo_backend { # 指定权重(整数) server 192.168.8.14:10086 weight=20; server 192.168.8.14:10087 weight=80; } server { listen 80; location / { proxy_pass http://meiduo_backend/; } }

    ip哈希

    upstream meiduo_backend { ip_hash; # 指定ip还行 server 127.0.0.1:10086; server 127.0.0.1:10087; } server { listen 80; location / { proxy_pass http://meiduo_backend/; } }

    uri哈希

    upstream meiduo_backend { hash $request_uri; # 指定uri哈希 server 127.0.0.1:10086; server 127.0.0.1:10087; } server { listen 80; location / { proxy_pass http://meiduo_backend/; } }
    4.3 负载平衡举例

    在/etc/nginx/conf.d目录下分别新建8000.conf,作为nginx的分配服务器

    8000.conf

    upstream backend.meiduo.site { server 127.0.0.1:8001; # 如果有多个服务器可以都写在这里 # server 127.0.0.1:8002; } server { listen 8000; location / { # 使用4层负载(传输层) include uwsgi_params; uwsgi_pass backend.meiduo.site; } }

    写完之后重启nginx

    nginx -t systemctl restart nginx

    修改Django项目的uwsgi.ini文件

    [uwsgi] # 使用Nginx连接时使用,Django程序所在服务器地址 socket=127.0.0.1:8001 # 直接做web服务器使用,Django程序所在服务器地址 # http=127.0.0.1:8001 # 项目目录 # chdir=项目路径/meiduo_project/meiduo_mall chdir=/data/meiduo_mall # 项目中wsgi.py文件的目录,相对于项目目录 wsgi-file=meiduo_mall/wsgi.py # 进程数 processes=1 # 线程数 threads=2 # uwsgi服务器的角色 master=True # 存放进程编号的文件 pidfile=uwsgi.pid # 日志文件 daemonize=uwsgi.log # 指定依赖的虚拟环境 # 方式一:使用python用户的虚拟环境 # virtualenv=/home/python/.virtualenvs/django_env # 方式二:使用root用户的虚拟环境; # 前提把python用户虚拟环境拷贝到root用户虚拟环境目录下, 命令如下: # cp -r /home/python/.virtualenvs/django_env /root/.virtualenvs/ # 然后就可以指定root下的django_env虚拟环境了 virtualenv=/root/.virtualenvs/django_env

    修改Django的wsgi.py文件

    import os from django.core.wsgi import get_wsgi_application os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'meiduo_mall.settings.dev') application = get_wsgi_application()

    使用uwsgi运行django

    # 运行 uwsgi --ini uwsgi.ini # 停止 uwsgi --stop uwsgi.pid

    5.日志

    Nginx默认提供了两个日志文件 access.log和error.log,通过access.log可以得到用户请求的相关信息;通过error.log可以获取某个web服务故障或其性能瓶颈等信息。这两个文件的保存路径可以在nginx.conf配置文件中查看

    cat /etc/nginx/nginx.conf -n

    可以在40、41行看到记录日志的配置

    40 access_log /var/log/nginx/access.log; 41 error_log /var/log/nginx/error.log;
    5.1 日志格式

    其实日志格式就是引用了一些内置变量,大概有

    变量说明$remote_addr前一台主机的ip(并不一定是真实客户端ip)$remote_user远程客户端的用户名(一般是“-”)$time_local时间和时区$request请求的url和请求方法$status响应码,200、400等$body_bytes_sent响应的内容字节数$http_referer访问链接来源$http_user_agent代理(一般是浏览器)$uri不带请求参数、不包含主机名的uri$http_x_forwarded_for记录客户端IP或前序代理服务器的IP$http_x_real_ip记录真实客户端的IP

    默认的配置文件上没用指定日志格式,即采用默认的combined格式,如下

    log_format combined '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent"';
    5.2 自定义日志

    我们编辑nginx.conf文件,当然也可以在其他conf配置文件指定日志。步骤是先声明日志格式,然后再使用该格式即可

    # 自定义一个名为proxy_format的日志格式 log_format proxy_format '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent "$http_referer"' '"$http_user_agent" "$http_x_forwarded_for" "$http_x_real_ip"'; # 指定日志文件的格式为proxy_format access_log /var/log/nginx/access.log proxy_format;
    Processed: 0.008, SQL: 8