正向代理或反向代理是取决于是接收服务还是提供服务。比如说,一个人想要上网,可以借助浏览器实现与互联网交互,人与浏览器是一起的,这个是正向代理;一个人想要点餐,跟服务员说,服务员再跟厨师说,服务员是跟厨师一起的,这个是反向代理
我们使用nginx一般做的是反向代理,即请求的服务经过nginx,再由nginx进行分发
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
因为nginx善于做静态文件代理,而不擅长做动态相关代理,我们可以借助uwsgi做动态代理。另外,proxy_pass是基于七层协议请求转发的,而uwsgi_pass是基于四层协议转发,故效率更高
安装uwsgi
pip install uwsgi在配置文件的location配置段里加上
include uwsgi_params; uwsgi_pass 代理地址;下面配合Django举例
新建/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; } }如果是七层代理转发,location使用的应该是 proxy_pass, 然后直接启动Django服务器
python3 manage.py runserver 0.0.0.0:8001如果是四层代理转发,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如果一个网站的访问量比较大,一个服务可能会忙不过来,可以选择多开几个,实现负载平衡
我们编辑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指定该集合
加权轮询
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/; } }在/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.pidNginx默认提供了两个日志文件 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;其实日志格式就是引用了一些内置变量,大概有
变量说明$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"';我们编辑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;