Nginx
一、含义
Nginx(发音同engine x)是一个 Web服务器,也可以用作反向代理,负载平衡器和 HTTP缓存。
Nginx使用异步事件驱动的方法来处理请求。Nginx的模块化事件驱动架构可以在高负载下提供更可预测的性能。
Nginx是一款面向性能设计的HTTP服务器,相较于Apache、lighttpd具有占有内存少,稳定性高等优势。与旧版本(<=2.2)的Apache不同,Nginx不采用每客户机一线程的设计模型,而是充分使用异步逻辑从而削减了上下文调度开销,所以并发服务能力更强。整体采用模块化设计,有丰富的模块库和第三方模块库,配置灵活。 在Linux操作系统下,Nginx使用epoll事件模型,得益于此,Nginx在Linux操作系统下效率相当高。同时Nginx在OpenBSD或FreeBSD操作系统上采用类似于epoll的高效事件模型kqueue。
二、安装
在Ubuntu16.04下安装
sudo apt-get install nginx
三、虚拟主机
虚拟主机使用的是特殊的软硬件技术,把一台运行在因特网上的服务器主机分成多台"虚拟"的主机,每台虚拟主机是一个独立的网站,具有独立的域名,具有完整的Intemet服务器功能(WWW、FTP、Email等)。同一台主机上的虚拟主机之间是完全独立的,在网站访问者看来,每一台虚拟主机和一台独立的主机是完全一样。
总结:虚拟主机提供了在同一台服务器、同一个 Nginx 进程上运行多个网站的功能。
Nginx可以配置多种类型的虚拟主机
- 基于IP的虚拟主机
- 基于域名的虚拟主机
- 基于端口的虚拟主机
四、基于域名的虚拟主机
1.Nginx的配置文件
在 /etc/nginx/nginx.conf 目录下的配置文件的详细信息如下:
http { ...... ## # Virtual Host Configs ## include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; }
这表了在明默认情况下 nginx 会自动包含 /etc/nginx/conf.d/*.conf 和 /etc/nginx/sites-enabled/* 文件
2.启用站点和可用站点
默认情况下,在 /etc/nginx/sites-enabled 下有一个默认站点,这个站点也就是 nginx 安装之后的默认站点:
$ cd /etc/nginx/sites-enabled $ ls -l total 0 lrwxrwxrwx 1 root root 34 Oct 6 02:19 default -> /etc/nginx/sites-available/default
vim /etc/nginx/sites-available/default 可以看到如下内容:
server { listen 80 default_server; listen [::]:80 default_server;
root /var/www/html; index index.html index.htm index.nginx-debian.html;
server_name _; location / { try_files $uri $uri/ =404;
} }
在 /etc/nginx/sites-available/ 下建立站点的配置文件,这些站点就是所谓的"可用站点"。
然后在 link 到/etc/nginx/sites-enabled 下开启站点,这些开启的站点就是所谓"启用站点"。
通过建立链接来控制可用站点的启用。
五、实战
创建虚拟主机 basiccloud.net
目标: http://basiccloud.net 和 http://www.basiccloud.net 应该都指向同一个虚拟主机。
在 /etc/nginx/sites-available/ 下新建 basiccloud.net 文件,内容如下:
server { listen 80; server_name basiccloud.net www.basiccloud.net; root /var/www/basiccloud.net; index index.html; }
然后建立 /var/www/basiccloud.net 目录,准备好站点的html文件(项目代码)。
将 basiccloud.net 站点文件链接到 /etc/nginx/sites-enabled/ 目录:
sudo ln -s /etc/nginx/sites-available/basiccloud.net /etc/nginx/sites-enabled/basiccloud.net
配置完成之后,在重新转载前,先验证一下:
$ sudo nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
验证通过,再重新装载:
sudo nginx -s reload
创建虚拟主机 dolphin.basiccloud.net
目标: http://dolphin.basiccloud.net 应该指向另外一个虚拟主机。
在 /etc/nginx/sites-available/ 下新建 dolphin.basiccloud.net 文件,内容如下:
server { listen 80; server_name dolphin.basiccloud.net; root /var/www/dolphin.basiccloud.net; index index.html; }
然后建立 /var/www/dolphin.basiccloud.net 目录,准备好站点的html文件(项目代码)。
将 dolphin.basiccloud.net 站点文件链接到 /etc/nginx/sites-enabled/ 目录:
sudo ln -s /etc/nginx/sites-available/dolphin.basiccloud.net /etc/nginx/sites-enabled/dolphin.basiccloud.net
修改完成之后,使用命令检测配置修改结果并重新装载配置:
sudo nginx -t sudo nginx -s reload
六、实战二:域名免端口(反向代理)
在实际使用中,由于web服务器启动于不同进程,因此需要指定不同的端口,也就意味着必然有web应用要使用80之外的端口,这样在地址栏中就必须出现端口号,非常影响用户体验。
比较好的方式,通过使用不同的域名或者二级域名,然后通过nginx反向代理的方式转发请求给到实际负责处理的服务器。
下面是这种方式的典型使用场景的例子:
创建虚拟主机 git.basiccloud.net
目标:http://git.basiccloud.net 应该指向当前机器上运行于 8800 端口的 gitlab 服务器。
在 /etc/nginx/sites-available/ 下新建 git.basiccloud.net 文件,内容如下:
server { listen 80; server_name git.basiccloud.net; location /{ proxy_pass http://127.0.0.1:8800; } }
将 git.basiccloud.net 站点文件链接到 /etc/nginx/sites-enabled/ 目录:
sudo ln -s /etc/nginx/sites-available/git.basiccloud.net /etc/nginx/sites-enabled/git.basiccloud.net
修改完成之后,使用命令检测配置修改结果并重新装载配置:
sudo nginx -t sudo nginx -s reload
创建虚拟主机 maven.basiccloud.net
目标:http://maven.basiccloud.net 应该指向当前机器上运行于 8081 端口的 artifactory 服务器。
在 /etc/nginx/sites-available/ 下新建 maven.basiccloud.net 文件,内容如下:
server { listen 80; server_name maven.basiccloud.net; location /{ proxy_pass http://127.0.0.1:8081; } }
将 maven.basiccloud.net 站点文件链接到 /etc/nginx/sites-enabled/ 目录:
sudo ln -s /etc/nginx/sites-available/maven.basiccloud.net /etc/nginx/sites-enabled/maven.basiccloud.net
七、HTTP配置
默认情况下,nginx已经自动开启了对client连接的keep alive支持。一般场景可以直接使用,
但是对于一些比较特殊的场景,还是有必要调整个别参数。
需要修改nginx的配置文件(在nginx安装目录下的conf/nginx.conf):
http { keepalive_timeout 120s 120s; keepalive_requests 10000; }
keepalive_timeout指令
keepalive_timeout指令的语法:
Syntax: keepalive_timeout timeout [header_timeout]; Default: keepalive_timeout 75s; Context: http, server, location
第一个参数设置keep-alive客户端连接在服务器端保持开启的超时值。值为0会禁用keep-alive客户端连接。
可选的第二个参数在响应的header域中设置一个值“Keep-Alive: timeout=time”。
这两个参数可以不一样
注:默认75s一般情况下也够用,对于一些请求比较大的内部服务器通讯的场景,适当加大为120s或者300s。第二个参数通常可以不用设置。
keepalive_requests指令
keepalive_requests指令用于设置一个keep-alive连接上可以服务的请求的最大数量。当最大请求数量达到时,连接被关闭。默认是100。
这个参数的真实含义,是指一个keep alive建立之后,nginx就会为这个连接设置一个计 数器,记录这个keep alive的长连接上已经接收并处理的客户端请求的数量。如果达到这 个参数设置的最大值时,则nginx会强行关闭这个长连接,逼迫客户端不得不重新建立新 的长连接。 这个参数往往被大多数人忽略,因为大多数情况下当QPS(每秒请求数)不是很高时,默认 值100凑合够用。但是,对于一些QPS比较高(比如超过10000QPS,甚至达到 30000,50000甚至更高) 的场景,默认的100就显得太低。 简单计算一下,QPS=10000时,客户端每秒发送10000个请求(通常建立有多个长连 接),每个连接只能最多跑100次请求,意味着平均每秒钟就会有100个长连接因此被 nginx关闭。同样意味着为了保持QPS,客户端不得不每秒中重新新建100个连接。因 此,如果用netstat命令看客户端机器,就会发现有大量的TIME_WAIT的socket连接(即使 此时keep alive已经在client和nginx之间生效)。 因此对于QPS较高的场景,非常有必要加大这个参数,以避免出现大量连接被生成再抛 弃的情况,减少TIME_WAIT。
保持和server的长连接
为了让nginx和server(nginx称为upstream)之间保持长连接,典型设置如下:
http { upstream BACKEND { server 192.168.0.1:8080 weight=1 max_fails=2 fail_timeout=30s; server 192.168.0.2:8080 weight=1 max_fails=2 fail_timeout=30s; keepalive 300; // 这个很重要! } server { listen 8080 default_server; server_name ""; location / { proxy_pass http://BACKEND; proxy_set_header Host $Host; proxy_set_header x-forwarded-for $remote_addr; proxy_set_header X-Real-IP $remote_addr; add_header Cache-Control no-store; add_header Pragma no-cache; proxy_http_version 1.1; // 这两个最好也设置 proxy_set_header Connection ""; client_max_body_size 3072k; client_body_buffer_size 128k; } } }
location设置
location中有两个参数需要设置:
http { server { location / { proxy_http_version 1.1; // 这两个最好也设置 proxy_set_header Connection ""; } } }
HTTP协议中对长连接的支持是从1.1版本之后才有的,因此最好通过proxy_http_version指令设置为"1.1",而"Connection"header应该被清理。清理的意思,我的理解,是清理从client过来的httpheader,因为即使是client和nginx之间是短连接,nginx和upstream之间也是可以开启长连接的。这种情况下必须清理来自client请求中的"Connection" header。
# nginx uwsgi wsgi django关系: # 第一步:nginx 是对外的服务接口,外部浏览器通过url访问nginx # 第二步:nginx 接收到浏览器发送过来的http请求,将包进行解析,分析url, # 如果是静态文件请求就直接访问用户给nginx配置的静态文件目录,直接返回用户请求的静态文件, # 如果不是静态文件,而是一个动态的请求,那么nginx就将请求转发给uwsgi,uwsgi 接收到请求之后将包进行处理, # 处理成wsgi可以接受的格式,并发给wsgi,wsgi 根据请求调用应用程序的某个文件, # 某个文件的某个函数,最后处理完将返回值再次交给wsgi,wsgi将返回值进行打包, # 打包成uwsgi能够接收的格式,uwsgi接收wsgi 发送的请求,并转发给nginx,nginx最终将返回值返回给浏览器。 # 第三步:要知道第一级的nginx并不是必须的,uwsgi完全可以完成整个的和浏览器交互的流程,但是要考虑到某些情况 # 1 安全问题,程序不能直接被浏览器访问到,而是通过nginx,nginx只开放某个接口,uwsgi本身是内网接口,这样运维人员在nginx上加上安全性的限制,可以达到保护程序的作用。 # 2负载均衡问题,一个uwsgi很可能不够用,即使开了多个work也是不行,毕竟一台机器的cpu和内存都是有限的,有了nginx做代理,一个nginx可以代理多台uwsgi完成uwsgi的负载均衡。 # 3静态文件问题,用django或是uwsgi这种东西来负责静态文件的处理是很浪费的行为,而且他们本身对文件的处理也不如nginx好,所以整个静态文件的处理都直接由nginx完成,静态文件的访问完全不去经过uwsgi以及其后面的东西。
原文:Nginx的学习笔记