Nginx简介
Nginx是异步框架的网页服务器,十分轻量级的HTTP服务器,也可以用作反向代理、负载平衡器和HTTP缓存。目前国内知名的公司都在使用,比如新浪、腾讯、豆瓣、163等。该软件由俄罗斯人伊戈尔·赛索耶夫创建并于2004年首次公开发布。2011年成立同名公司以提供支持。2019年3月11日,Nginx公司被F5 Networks以6.7亿美元收购。
Nginx是免费的开源软件,根据类BSD许可证的条款发布。一大部分Web服务器使用Nginx,通常作为负载均衡器。Nginx有着非常好的性能(比Apache快将近67%),因为它是以事件驱动的方式编写的。Nginx采用C进行编写,不论是系统资源开销还是CPU使用效率都很多。
Nginx特点
Nginx使用异步事件驱动的方法来处理请求。Nginx的模块化事件驱动架构可以在高负载下提供更可预测的性能。是一个安装非常的简单、配置文件非常简洁、Bug非常少的服务。Nginx 启动特别容易,并且几乎可以做到7*24不间断运行,即使运行数个月也不需要重新启动。还能够在不间断服务的情况下进行软件版本的升级。
高性能HTTP服务器
Nginx是一款面向性能设计的HTTP服务器,相较于Apache、lighttpd具有占有内存少,稳定性高等优势。与旧版本(≤ 2.2)的Apache不同,Nginx不采用每客户机一线程的设计模型,而是充分使用异步逻辑从而削减了上下文调度开销,所以并发服务能力更强。整体采用模块化设计,有丰富的模块库和第三方模块库,配置灵活。
在Linux操作系统下,Nginx使用epoll事件模型,所以Nginx在Linux操作系统下效率相当高。
作用:处理静态文件,索引文件以及自动索引;打开文件描述符缓冲.无缓存的反向代理加速,简单的负载均衡和容错.FastCGI,简单的负载均衡和容错.支持 SSL 和 TLSSNI.
可大量并行处理
有报告表明能够支持五万个并行连接,而在实际运作中,可支持二~四万个并行连接。
内存池
为了避免出现内存碎片,减少向操作系统申请内存的次数、降低各个模块的开发复杂度,Nginx 设计了简单的内存池,它的作用主要是把多次向系统申请内存的操作整合成一次,这大大减少了 CPU 资源的消耗,同时减少了内存碎片。
代理服务器
作为邮件代理服务:Nginx 同时也是一个非常优秀的邮件代理服务(最早开发这个产品的目的之一也是作为邮件代理服务器),Last.fm 描述了成功并且美妙地使用经验。
模块化设计结构
整体采用模块化设计是Nginx的一个重大特点,甚至http服务器核心功能也是一个模块。
和Apache相比
Nginx 的编写有一个明确目标就是超越 Apache Web 服务器的性能。Nginx 提供开箱即用的静态文件,使用的内存比 Apache 少得多,每秒可以处理大约四倍于 Apache 的请求。 在低并发下性能与 Apache 相当(有时候还低于),但是在高并发下 Nginx 能保持低资源低消耗高性能。Nginx 的优点还包括:高度模块化的设计,模块编写简单,以及配置文件简洁。
Nginx架构
Nginx的架构大致流程如下:
- Nginx启动后会产生一个主进程,主进程执行一系列的工作后会产生一个或者多个工作进程;
- 在客户端请求动态站点的过程中,Nginx服务器还涉及和后端服务器的通信。Nginx将接收到的Web请求通过代理转发到后端服务器,由后端服务器进行数据处理和组织;
- Nginx之所以降低网络压力,采用缓存机制,是为了提高对请求的响应效率,将历史应答数据缓存到本地。保障对缓存文件的快速访问;
Nginx 里有一个 master 进程和多个 worker 进程。master 进程并不处理网络请求,主要负责调度工作进程:加载配置、启动工作进程及非停升级。worker 进程负责处理网络请求与响应。
master进程主要用来管理worker进程,具体包括如下4个主要功能:
- 接收来自外界的信号。
- 向各worker进程发送信号。
- 监控woker进程的运行状态。
- 当woker进程退出后(异常情况下),会自动重新启动新的woker进程。
woker进程主要用来处理基本的网络事件:
- 多个worker进程之间是对等且相互独立的,他们同等竞争来自客户端的请求。
- 一个请求,只可能在一个worker进程中处理,一个worker进程,不可能处理其它进程的请求。
- worker进程的个数是可以设置的,一般我们会设置与机器cpu核数一致。同时,nginx为了更好地利用多核特性,具有cpu绑定选项,我们可以将某一个进程绑定在某一个核上,这样就不会因为进程的切换带来cache的失效。
Nginx能用来做什么?
下面咱们从配置中来一一解释
一、静态HTTP服务器
Nginx是一个HTTP服务器,可以将服务器上的静态文件(如HTML、图片)通过HTTP协议展现给客户端。
二、反向代理服务器
客户端本来可以直接通过HTTP协议访问某网站应用服务器,网站管理员可以在中间加上一个Nginx,客户端请求Nginx,Nginx请求应用服务器,然后将结果返回给客户端,此时Nginx就是反向代理服务器。
三、负载均衡
当网站访问量非常大。因为网站越来越慢,一台服务器已经不够用了。于是将同一个应用部署在多台服务器上,将大量用户的请求分配给多台机器处理。同时带来的好处是,其中一台服务器万一挂了,只要还有其他服务器正常运行,就不会影响用户使用。
Nginx可以通过反向代理来实现负载均衡。
- upstream minio-server {
- ip_hash; # 根据客户端IP地址Hash值将请求分配给固定的一个服务器处理
- server 10.95.130.144:9000 weight=25 max_fails=2 fail_timeout=30s; # 应用服务器1
- server 10.95.130.145:9000 weight=25 max_fails=2 fail_timeout=30s; # 应用服务器2
- server 10.95.130.146:9000 weight=25 max_fails=2 fail_timeout=30s; # 应用服务器3
- server 10.95.130.147:9000 weight=25 max_fails=2 fail_timeout=30s; # 应用服务器4
- } # weight默认为1,该服务器处理1/4请求
- server {
- listen 80;
- server_name localhost;
- charset utf-8;
- default_type text/html;
- location / {
- proxy_set_header Host $http_host;
- proxy_set_header X-Forwarded-For $remote_addr;
- client_body_buffer_size 10M;
- client_max_body_size 10G;
- proxy_buffers 1024 4k;
- proxy_read_timeout 300;
- proxy_next_upstream error timeout http_404;
- root /usr/share/nginx/html; # 静态文件路径
- proxy_pass http://minio-server; # 负载均衡
- # proxy_pass http://192.168.20.1:8080; # 应用服务器地址,反向代理
- }
- }
四、虚拟主机
有的网站访问量大,需要负载均衡。然而并不是所有网站都如此出色,有的网站,由于访问量太小,需要节省成本,将多个网站部署在同一台服务器上。
例如将www.abc.com和www.def.com两个网站部署在同一台服务器上,两个域名解析到同一个IP地址,但是用户通过两个域名却可以打开两个完全不同的网站,互相不影响,就像访问两个服务器一样,所以叫两个虚拟主机。
在服务器8080和8081分别开了一个应用,客户端通过不同的域名访问,根据server_name可以反向代理到对应的应用服务器。虚拟主机的原理是通过HTTP请求头中的Host是否匹配server_name来实现的。另外,server_name配置还可以过滤有人恶意将某些域名指向你的主机服务器。
- server {
- listen 80 default_server;
- server_name _;
- return444; # 过滤其他域名的请求,返回444状态码
- }
- server {
- listen 80;
- server_name www.abc.com; # www.abc.com域名
- location / {
- proxy_pass http://localhost:8080; # 对应端口号8080
- }
- }
- server {
- listen 80;
- server_name www.def.com; # www.def.com域名
- location / {
- proxy_pass http://localhost:8081; # 对应端口号8081
- }
- }
nginx+uwsgi+django是我们常用的django部署方式。nginx作为最前端的服务器,他负责接收所有的客户端请求,对于请求的静态文件,由nginx服务器自己完成,因为它具有很好处理静态文件的能力,性能进行过优化,支持高并发量;uWSGI服务器作为支持服务器,是用来服务nginx的,nginx将请求的动态文件交给uWSGI进行处理。uWSGI实现了uwsgi、wsgi和http协议,uwsgi协议是uWSGI自定义的协议,定义的是框架(django)和服务器对接的接口。
nginx.conf 配置结构
main全局块:配置影响nginx全局的指令。一般有运行nginx服务器的用户组,nginx进程pid存放路径,日志存放路径,配置文件引入,允许生成worker process数等。
events块:配置影响nginx服务器或与用户的网络连接。有每个进程的最大连接数,选取哪种事件驱动模型处理连接请求,是否允许同时接受多个网路连接,开启多个网络连接序列化等。
http块:可以嵌套多个server,配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置。如文件引入,mime-type定义,日志自定义,是否使用sendfile传输文件,连接超时时间,单连接请求数等。
server块:配置虚拟主机的相关参数,一个http中可以有多个server。
location块:配置请求的路由,以及各种页面的处理情况。
不同模块指令关系:server继承main;location继承server;upstream既不会继承指令也不会被继承,它有自己的特殊指令,不需要在其他地方的应用。
- #全局块
- events { #events块
- }
- http #http块
- {
- #http全局块
- server #server块
- {
- #server全局块
- location [PATTERN] #location块
- {
- }
- location [PATTERN]
- {
- }
- }
- server
- {
- }
- #http全局块
- }
Nginx.conf详细配置
上面nginx的配置初入门的可能还不太明白什么意思,下面提供给大家详细的配置信息。
- #配置用户或者组,默认为nobody nobody。
- #user administrator administrators;
- #允许生成的进程数,默认为1
- #worker_processes 2;
- #指定nginx进程运行文件存放地址
- #pid /nginx/pid/nginx.pid;
- #制定错误日志路径,级别。这个设置可以放入全局块,http块,server块,级别依次为:debug|info|notice|warn|error|crit|alert|emerg
- error_log log/error.log debug;
- #工作模式及连接数上限
- events {
- #设置网路连接序列化,防止惊群现象发生,默认为on
- accept_mutex on;
- #设置一个进程是否同时接受多个网络连接,默认为off
- multi_accept on;
- #事件驱动模型,select|poll|kqueue|epoll|resig|/dev/poll|eventport
- #use epoll;
- #单个work进程允许的最大连接数,默认为512
- worker_connections 1024;
- }
- #http服务器
- http {
- #文件扩展名与文件类型映射表。设定mime类型(邮件支持类型),类型由mime.types文件定义
- #include /usr/local/etc/nginx/conf/mime.types;
- include mime.types;
- #默认文件类型,默认为text/plain
- default_type application/octet-stream;
- #取消服务访问日志
- #access_log off;
- #自定义日志格式
- log_format myFormat '$remote_addr–$remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $http_x_forwarded_for';
- #设置访问日志路径和格式。"log/"该路径为nginx日志的相对路径,mac下是/usr/local/var/log/。combined为日志格式的默认值
- access_log log/access.log myFormat;
- rewrite_log on;
- #允许sendfile方式传输文件,默认为off,可以在http块,server块,location块。(sendfile系统调用不需要将数据拷贝或者映射到应用程序地址空间中去)
- sendfile on;
- #每个进程每次调用传输数量不能大于设定的值,默认为0,即不设上限。
- sendfile_max_chunk 100k;
- #连接超时时间,默认为75s,可以在http,server,location块。
- keepalive_timeout 65;
- #gzip压缩开关
- #gzip on;
- tcp_nodelay on;
- #设定实际的服务器列表
- upstream mysvr1 {
- server 127.0.0.1:7878;
- server 192.168.10.121:3333 backup; #热备(其它所有的非backup机器down或者忙的时候,请求backup机器))
- }
- upstream mysvr2 #weigth参数表示权值,权值越高被分配到的几率越大
- server 192.168.1.11:80 weight=5;
- server 192.168.1.12:80 weight=1;
- server 192.168.1.13:80 weight=6;
- }
- upstream https-svr {
- #每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题
- ip_hash;
- server 192.168.1.11:90;
- server 192.168.1.12:90;
- }
- #error_page 404 https://www.baidu.com; #错误页
- #HTTP服务器
- # 静态资源一般放在nginx所在主机
- server {
- listen 80; #监听HTTP端口
- server_name 127.0.0.1; #监听地址
- keepalive_requests 120; #单连接请求上限次数
- set $doc_root_dir "/Users/doing/IdeaProjects/edu-front-2.0"; #设置server里全局变量
- #index index.html; #定义首页索引文件的名称
- location ~*^.+$ { #请求的url过滤,正则匹配,~为区分大小写,~*为不区分大小写。
- root $doc_root_dir; #静态资源根目录
- proxy_pass http://mysvr1; #请求转向“mysvr1”定义的服务器列表
- #deny 127.0.0.1; #拒绝的ip
- #allow 172.18.5.54; #允许的ip
- }
- }
- #http
- server {
- listen 80;
- server_name www.helloworld.com; #监听基于域名的虚拟主机。可有多个,可以使用正则表达式和通配符
- charset utf-8; #编码格式
- set $static_root_dir "/Users/doing/static";
- location /app1 { #反向代理的路径(和upstream绑定),location后面设置映射的路径
- proxy_pass http://zp_server1;
- }
- location /app2 {
- proxy_pass http://zp_server2;
- }
- location ~ ^/(images|javascript|js|css|flash|media|static)/ { #静态文件,nginx自己处理
- root $static_root_dir;
- expires 30d; #静态资源过时间30天
- }
- location ~ /\.ht { #禁止访问 .htxxx 文件
- deny all;
- }
- location = /do_not_delete.html { #直接简单粗暴的返回状态码及内容文本
- return 200 "hello.";
- }
- # 指定某些路径使用https访问(使用正则表达式匹配路径+重写uri路径)
- location ~* /http* { #路径匹配规则:如localhost/http、localhost/httpsss等等
- #rewrite只能对域名后边的除去传递的参数外的字符串起作用,例如www.c.com/proxy/html/api/msg?method=1¶=2只能对/proxy/html/api/msg重写。
- #rewrite 规则 定向路径 重写类型;
- #rewrite后面的参数是一个简单的正则。$1代表正则中的第一个()。
- #$host是nginx内置全局变量,代表请求的主机名
- #重写规则permanent表示返回301永久重定向
- rewrite ^/(.*)$ https://$host/$1 permanent;
- }
- #错误处理页面(可选择性配置)
- #error_page 404 /404.html;
- #error_page 500 502 503 504 /50x.html;
- #以下是一些反向代理的配置(可选择性配置)
- #proxy_redirect off;
- #proxy_set_header Host $host; #proxy_set_header用于设置发送到后端服务器的request的请求头
- #proxy_set_header X-Real-IP $remote_addr;
- #proxy_set_header X-Forwarded-For $remote_addr; #后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
- #proxy_connect_timeout 90; #nginx跟后端服务器连接超时时间(代理连接超时)
- #proxy_send_timeout 90; #后端服务器数据回传时间(代理发送超时)
- #proxy_read_timeout 90; #连接成功后,后端服务器响应时间(代理接收超时)
- #proxy_buffer_size 4k; #设置代理服务器(nginx)保存用户头信息的缓冲区大小
- #proxy_buffers 4 32k; #proxy_buffers缓冲区,网页平均在32k以下的话,这样设置
- #proxy_busy_buffers_size 64k; #高负荷下缓冲大小(proxy_buffers*2)
- #proxy_temp_file_write_size 64k; #设定缓存文件夹大小,大于这个值,将从upstream服务器传
- #client_max_body_size 10m; #允许客户端请求的最大单文件字节数
- #client_body_buffer_size 128k; #缓冲区代理缓冲用户端请求的最大字节数
- }
- #https
- #(1)HTTPS的固定端口号是443,不同于HTTP的80端口;
- #(2)SSL标准需要引入安全证书,所以在 nginx.conf 中你需要指定证书和它对应的 key
- server {
- listen 443;
- server_name www.hellohttps1.com www.hellohttps2.com;
- set $geek_web_root "/Users/doing/IdeaProjects/backend-geek-web";
- ssl_certificate /usr/local/etc/nginx/ssl-key/ssl.crt; #ssl证书文件位置(常见证书文件格式为:crt/pem)
- ssl_certificate_key /usr/local/etc/nginx/ssl-key/ssl.key; #ssl证书key位置
- location /passport {
- send_timeout 90;
- proxy_connect_timeout 50;
- proxy_send_timeout 90;
- proxy_read_timeout 90;
- proxy_pass http://https-svr;
- }
- location ~ ^/(res|lib)/ {
- root $geek_web_root;
- expires 7d;
- #add_header用于为后端服务器返回的response添加请求头,这里通过add_header实现CROS跨域请求服务器
- add_header Access-Control-Allow-Origin *;
- }
- #ssl配置参数(选择性配置)
- ssl_session_cache shared:SSL:1m;
- ssl_session_timeout 5m;
- }
- #配置访问控制:每个IP一秒钟只处理一个请求,超出的请求会被delayed
- #语法:limit_req_zone $session_variable zone=name:size rate=rate (为session会话状态分配一个大小为size的内存存储区,限制了每秒(分、小时)只接受rate个IP的频率)
- limit_req_zone $binary_remote_addr zone=req_one:10m rate=1r/s nodelay;
- location /pay {
- proxy_set_header Host $http_host;
- proxy_set_header X-Real_IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- #访问控制:limit_req zone=name [burst=number] [nodelay];
- limit_req zone=req_one burst=5; #burst=5表示超出的请求(被delayed)如果超过5个,那些请求会被终止(默认返回503)
- proxy_pass http://mysvr1;
- }
- #可以把子配置文件放到/usr/local/etc/nginx/servers/路径下,通过include引入
- include /usr/local/etc/nginx/servers/*.conf;
- }
Nginx内置全局变量
- $args :这个变量等于请求行中的参数,同$query_string
- $content_length : 请求头中的Content-length字段。
- $content_type : 请求头中的Content-Type字段。
- $document_root : 当前请求在root指令中指定的值。
- $host : 请求主机头字段,否则为服务器名称。
- $http_user_agent : 客户端agent信息
- $http_cookie : 客户端cookie信息
- $limit_rate : 这个变量可以限制连接速率。
- $request_method : 客户端请求的动作,通常为GET或POST。
- $remote_addr : 客户端的IP地址。
- $remote_port : 客户端的端口。
- $remote_user : 已经经过Auth Basic Module验证的用户名。
- $request_filename : 当前请求的文件路径,由root或alias指令与URI请求生成。
- $scheme : HTTP方法(如http,https)。
- $server_protocol : 请求使用的协议,通常是HTTP/1.0或HTTP/1.1。
- $server_addr : 服务器地址,在完成一次系统调用后可以确定这个值。
- $server_name : 服务器名称。
- $server_port : 请求到达服务器的端口号。
- $request_uri : 包含请求参数的原始URI,不包含主机名,如:”/foo/bar.php?arg=baz”。
- $uri : 不带请求参数的当前URI,$uri不包含主机名,如”/foo/bar.html”。
- $document_uri : 与$uri相同。
- nginx中$host、$http_host和$proxy_host区别
Nginx负载均衡策略
负载均衡顾名思义,是一种策略,用于防止一台服务器过载,而其他服务器闲置情况发生的策略。通过该策略可以使得提供相同服务的服务器负载基本相同。说得直白一点,就是当客户端发起一个请求之后,负载均衡会通过预先设定好的策略将该请求转发给上游的一台服务器进行处理。
负载均衡是一个很成熟的技术,其中对后端服务器进行轮询(默认);通过客户端请求IP进行hash;对后端服务器指定权重等,是较为常见的负载均衡策略。
对服务盲目地采用负载均衡策略,是不太合理的。负载均衡默认情况下是轮询策略,这在一些场景下并不高效。两种常见的负载均衡hash策略,以及对应的使用场景。
1、ip_hash(通过客户端请求ip进行hash,再通过hash值选择后端server):
当你服务端的一个特定url路径会被同一个用户连续访问时,如果负载均衡策略还是轮询的话,那该用户的多次访问会被打到各台服务器上,这显然并不高效(会建立多次http链接等问题)。
甚至考虑一种极端情况,用户需要分片上传文件到服务器下,然后再由服务器将分片合并,这时如果用户的请求到达了不同的服务器,那么分片将存储于不同的服务器目录中,导致无法将分片合并。所以,此类场景可以考虑采用nginx提供的ip_hash策略。既能满足每个用户请求到同一台服务器,又能满足不同用户之间负载均衡。
- upstream backend_test{
- ip_hash;
- server 192.168.128.1:8080 ;
- server 192.168.128.2:8080 ;
- server 192.168.128.3:8080 down;
- server 192.168.128.4:8080 down;
- }
- server {
- listen 8081;
- server_name test123.csdn.net;
- root /home/system/test123.csdn.net/test;
- location ^~ /upload {
- proxy_pass http://backend_test;
- }
2、url_hash(通过请求url进行hash,再通过hash值选择后端server):
一般来讲,要用到url_hash,是要配合缓存命中来使用。
举一个我遇到的实例:有一个服务器集群A,需要对外提供文件下载,由于文件上传量巨大,没法存储到服务器磁盘中,所以用到了第三方云存储来做文件存储。服务器集群A收到客户端请求之后,需要从云存储中下载文件然后返回,为了省去不必要的网络带宽和下载耗时,在服务器集群A上做了一层临时缓存(缓存一个月)。
由于是服务器集群,所以同一个资源多次请求,可能会到达不同的服务器上,导致不必要的多次下载,缓存命中率不高,以及一些资源时间的浪费。在此类场景下,为了使得缓存命中率提高,很适合使用url_hash策略,同一个url(也就是同一个资源请求)会到达同一台机器,一旦缓存住了资源,再此收到请求,就可以从缓存中读取,既减少了带宽,也减少的下载时间。
- upstream aastream {
- hash $request_uri;
- server 192.168.244.1:8080;
- server 192.168.244.2:8080;
- server 192.168.244.3:8080;
- server 192.168.244.4:8080;
- }
- server {
- listen 8081 default;
- server_name test123.csdn.net;
- charset utf-8;
- location /get {
- proxy_pass http://aastream;
- }
- }
Nginx启动命令
- ./nginx -s quit:此方式停止步骤是待nginx进程处理任务完毕进行停止。
- ./nginx -s stop:此方式相当于先查出nginx进程id再使用kill命令强制杀掉进程。
查询nginx进程
- ps aux|grep nginx
重启 nginx
1.先停止再启动(推荐): 对 nginx 进行重启相当于先停止再启动,即先执行停止命令再执行启动命令。如下:
- ./nginx -s quit
- ./nginx
2.重新加载配置文件: 当 nginx的配置文件 nginx.conf 修改后,要想让配置生效需要重启 nginx,使用-s reload 不用先停止 nginx再启动 nginx 即可将配置信息在 nginx 中生效,如下:
- ./nginx -s reload
切记每次配置nginx.conf后都要执行一下Nginx语法检测, /nginx/sbin/nginx.cong -t 然后再重启
Nginx的安装
Nginx的安装我就不详细给大家给大家介绍了,动动自己的小手自行查找吧。