Nginx是触发器架构的页面伺服器,也可以用于逆向全权、用户端器和HTTP缓存。应用软件由米哈伊尔·赛索诺夫建立再于2004年首次公开发布。2011年成立撞名子公司以提供更多全力支持。2019年3月11日,Nginx子公司被F5 Networks以6.7万美元全面收购。
Nginx有以下的特点
由C撰写,挤占的资源和缓存低,操控性高。单民主化多处理器,当开启nginx伺服器,会聚合一个master民主化,master民主化会fork出数个worker民主化,由worker缓存处置应用程序的允诺。全力支持逆向全权,全力支持7层阻抗平衡(开拓阻抗平衡的益处)。高mammalian,nginx是触发器非堵塞型处置允诺,采用的epollandqueue商业模式处置静态文档速度慢度组件化,实用性简单。街道社区活耀,各种高效能组件子公司出品迅速。主要就实用性组件
NGINX组件使用四种主要就类别的实用性第一类。大部份都是用JSON表述的。插件Application第一类表述组件正在运行的插件的特征,比如词汇,过程命令行和文档系统上的位置。侦听器Listener第一类表述组件实用性,该实用性将传至的允诺通过已表述的IP门牌号和路由器或非到选定的插件。路由器第一类Router提供更多路由器机能。路由器机能主要就包括路由器到Unit插件,提供更多动态文档,全权到内部服务和伺服器横山的用户端。结语将建立对这些第一类的基础认知。
插件 Application
{ “applications”: { “my-app”: { “type”: “php”, “processes”: 2, “root”: “/var/www/app/”, “index”: “index.php”, “user”: “app_user”, “group”:“app_group” } } }布署在NGINX组件上的每一插件都由一个插件第一类表述。用JSON表述的插件第一类选定了插件的特性。五种插件类别都有其自己的须要和较旧属性。许多不同的插件特性控制着单位业务流程的管理工作和管制。 type特性是大部份插件中国共产党有的是惟一须要的业务流程管理工作特性。它表述了插件词汇,比如PHP,Python,Golang,Ruby或Perl。其他特性主要就包括插件民主化数管制;时间管制;用户,组和配置文件;和工作产品目录。
H55N Listener
{ “listeners”: { “*:8080”: { “pass”: “applications/my-app” } } }为了指示NGINX组件监听传至的允诺,必须表述一个H55N第一类。侦听器第一类表述组件将传至允诺或非到的插件。侦听器第一类是选定给表述IP和路由器的键的值。在此示例中,*用于IP门牌号,因此指示组件监听分配给伺服器的大部份IP门牌号。侦听器第一类具有两个特性:pass和tls(较旧)。 pass特性采用一个字符串值,该值选定将允诺或非到的插件,插件目标,路由器或上游。该示例将请求直接发送到名为my-app的插件。
路由器 Routes
{ “listeners”: { “*:8080”: { “pass”: “routes” } }, “routes”: [ { “match”: { “host”: “blog.example.com” }, “action”: { “pass”: “applications/blog” } }, { “action”: { “pass”: “applications/my-app” } } ] }路由器具有两个特性:match和action。这两个特性都有其自己的第一类类别,这些第一类类别具有许多可实用性的特性。
Match全力支持不同的选项:arguments, cookies, destination, headers, host, method, scheme, source, 和 uri。
Action全力支持pass, share, fallback, proxy, return, 和 location等。
全权 Proxy
{ “listeners”: { “*:8080”: { “pass”: “routes”} },“routes”: [ { “match”: { “uri”: “/wiki/*” }, “action”: { “proxy”: “http://172.17.0.1:80”} }, {“action”: { “pass”: “applications/my-app” } } ] }全权操作类别会将允诺中继到内部HTTP服务。此操作的机能是基本逆向全权的机能。可以使用Unix,IPv4和IPv6套接字门牌号作为目标。该机能将适合许多用例。要获得更多高级机能,可以使用NGINX逆向全权和用户端器伺服器。
动态文档
{ “listeners”: { “*:8080”: {“pass”: “routes” } }, “routes”: [ { “action”: { “share”: “/var/www/static/”, “fallback”: { “share”: “/var/app/static” } } } ] }share操作类别将提供更多本地产品目录中的动态内容。它可以与fallback操作结合使用,该fallback操作将告诉Unit如果找不到所允诺的文档或Unit权限不足以访问该文档,则如何指示该允诺。fallback操作可以将允诺路由器到pass,proxy或share操作。当回退将允诺或非到另一个share操作时,可以嵌套fallback操作。
上游服务 Upstreams
{ “listeners”: { “*:8080”: { “pass”: “upstreams/pool-0” } }, “upstreams”: { “pool-0”: { “servers”: { “10.0.0.2:8080”: { }, “10.0.1.2:8080”: { “weight”: 2.0 } } } } }组件实用性的上游upstreams特性表述了许多命名的上游upstreams第一类。每一上游upstreams第一类都表述一个伺服器servers第一类。伺服器servers第一类使用键来表述目标,并使用该值来选定较旧的权重。上游upstreams使用加权循环阻抗平衡算法。权重最大值为1000000,最小值为0(此类伺服器未收到任何允诺),默认值为1。
目标 Targets
{ “listeners”:{ “*:8080”:{ “pass”:“routes” } }, “routes”:[ { “match”:{ “host”:“admin.example.com” }, “action”:{ “pass”:“applications/my-app/admin” } }, { “action”:{ “pass”:“applications/my-app/website” } } ], “applications”:{ “my-app”:{ “type”:“php”, “targets”:{ “admin”:{ “index”:“admin.php”, “root”:“/var/www/admin”},“website”:{ “script”:“index.php”, “root”:“/var/www/” } } } } }路由器Routes和插件Applications实用性的结合。插件实用性具有一个目标targets特性,该特性表述了插件上下文的另一层。 PHP插件必须具有在插件级别或目标级别表述的root和script或index特性。在该示例中,管理目标targets的根产品目录与网站目标的根产品目录不同。 admin目标还允许调用产品目录结构中的大部份PHP文档,其中admin.php为索引。网站目标包含管理工作根产品目录;但是,它仅允许调用index.php脚本。一个插件最多可以实用性254个目标。只需将目标名称附加到插件名称空间,即可路由器到目标。
了解了主要就第一类实用性后,下面我们就看看Nginx提供更多的一些主要就的机能和相应的实用性第一类。
阻抗平衡
当今的互联网用户体验都要求操控性和正常运行时间。为此,运行同一系统的数个副本,并将阻抗分布在它们上。随着阻抗的增加,可以使系统的另一个副本联机。这种架构技术称为水平缩放。基于软件的基础架构因其灵活性而越来越受欢迎,从而开辟了无限的可能性。无论哪种用例,都需要一种与基础架构一样动态的用户端解决方案。 NGINX通过HTTP,TCP和UDP用户端方式满足了这一需求。
HTTP 商业模式
upstreambackend {server 10.10.12.45:80 weight=1; server app.example.com:80 weight=2; } server { location / { proxy_passhttp://backend; } }TCP商业模式
stream { upstream mysql_read { server read1.example.com:3306 weight=5; serverread2.example.com:3306; server 10.10.12.34:3306 backup; } server { listen 3306; proxy_passmysql_read; } }UDP 商业模式
stream { upstream ntp { server ntp1.example.com:123 weight=2; server ntp2.example.com:123; }server { listen 123 udp; proxy_pass ntp; } }阻抗平衡方法
Round robin 基于权重,按统计顺序分配流量Least connections 把流量分配到连接最少的上游服务上去Generic hash 通过管理工作员表述的基于文本,变量的哈希值来分配流量,常用于服务和允诺内容匹配的场景Random 基于权重,随机分配流量IP hash,仅对HTTP生效,使用IP门牌号的前三个字节聚合哈希值,并相应地分配流量被动健康检查
upstream backend { server backend1.example.com:1234 max_fails=3fail_timeout=3s; server backend2.example.com:1234 max_fails=3 fail_timeout=3s; }利用健康检查,确保流量只会路由器到健康的服务上去
慢开启
upstream { zone backend 64k; server server1.example.com slow_start=20s; serverserver2.example.com slow_start=15s; }慢开启给服务时间热身,在上述的例子中,服务1会等待20秒接受新的允诺,已给出足够的时间来初始化,准备缓存等。
TCP健康检查
stream { server { listen 3306; proxy_pass read_backend; health_check interval=10 passes=2 fails=3; } }在上述的例子中,如果上游伺服器无法响应NGINX发起的三个或更多TCP连接,则将被视为不正常。 NGINX每10秒执行一次检查。仅在通过两次运行状况检查后,伺服器才被视为运行状况良好。
流量管理工作
NGINX也被归类为Web流量控制器。可以使用NGINX根据许多属性智能的路由器流量和控制流。NGINX能够基于百分比拆分应用程序允诺,利用应用程序的地理位置和以速率,连接和带宽管制的形式控制流量的能力。
A/B测试
upstream backend { server 10.10.12.45:80 weight=1; server app.example.com:80 weight=2; } server { location / { proxy_passhttp://backend; } }当测试电子商务网站上转换率的不同类别的营销和前端机能时,这种类别的A / B测试很有用。插件通常使用一种称为canary release的布署类别。在这种类别的布署中,流量会缓慢切换到新版本。在推出新版本的代码时,在不同版本的插件之间拆分应用程序可能很有用,以管制发生错误时的爆炸半径。无论在两个不同的插件集之间拆分应用程序的原因是什么,NGINX都通过使用split_clients组件使此操作变得简单。
管制连接数目
http { limit_conn_zone $binary_remote_addr zone=limitbyaddr:10m; limit_conn_status 429; … server { … limit_conn limitbyaddr 40; … } }上述实用性管制到Server的连接数为40,返回429错误。
管制速率
http { limit_req_zone $binary_remote_addr zone=limitbyaddr:10m rate=1r/s; limit_req_status 429; … server { … limit_req zone=limitbyaddr burst=10 nodelay; … } }限速组件机能强大,可防止滥用快速允诺,同时仍为大部份人提供更多优质服务。管制允诺速率的原因有很多,其中之一就是安全性。您可以通过在登录页面上设置非常严格的管制来拒绝暴力攻击。您可以对大部份允诺设置合理的管制,从而禁用可能试图拒绝为您的插件提供更多服务或浪费资源的恶意用户的计划。
管制带宽
location /download/ { limit_rate_after 10m; limit_rate 1m; }通过管制特定连接的带宽,NGINX可以以选定的方式在大部份应用程序之间共享其上传带宽。这两个指令可以完成大部份操作:limit_rate_after和limit_rate。 limit_rate指令默认选定给定上下文的速率管制,以每秒字节数为单位。但是,可以为兆字节选定m或为千兆字节选定g。两个指令的默认值均为0。值0表示完全不管制下载速率。此组件允许以编程方式更改应用程序的速率管制。
大规模内容缓存
缓存通过存储将来要再次提供更多的允诺响应来加速内容服务。内容缓存减少了上游伺服器的阻抗,缓存了完整的响应,而不需要运行计算并再次查询同一允诺。缓存可提高效能并减少阻抗,这意味着可以用更少的资源更快地服务。在战略位置扩展和分发缓存伺服器可能会对用户体验产生巨大影响。最好将内容托管在消费者附近,以获得最佳操控性。可以将内容缓存在用户附近。这就是内容交付网络或CDN的商业模式。借助NGINX,可以在可以放置NGINX伺服器的任何地方缓存内容,从而有效地建立自己的CDN。借助NGINX缓存,还可以在上游发生故障时被动缓存并提供更多缓存的响应。
缓存区域
proxy_cache_path /var/nginx/cache keys_zone=CACHE:60m levels=1:2 inactive=3h max_size=20g; proxy_cache CACHE;使用proxy_cache_path表述缓存区域和响应的路径。
缓存忽略
proxy_cache_bypass $http_cache_bypass;如果HTTP允诺标头cache_bypass设置为任何非0的值,该实用性将告诉NGINX绕过缓存。
缓存操控性
location ~* \.(css|js)$ { expires 1y; add_header Cache-Control “public”; }此location块选定应用程序可以缓存CSS和JavaScript文档的内容。 expires指令指示应用程序一年后其缓存资源将不再有效。 add_header指令将HTTP响应标头Cache-Control添加到响应中,其值为public,这允许沿途的任何缓存伺服器缓存资源。如果我们选定专用,则仅允许应用程序缓存该值。
缓存操控性有很多因素,磁盘速度最为重要。 NGINX实用性中可以执行许多操作来帮助提高缓存操控性。一种选择是以这样一种方式设置响应的标题,即应用程序实际上缓存了响应,根本不向NGINX发出允诺,而只是从其自己的缓存中提供更多服务
认证
NGINX能够验证应用程序。使用NGINX对应用程序允诺进行身份验证可减轻工作量,并能够阻止未经批准的允诺到达应用伺服器。 NGINX开源可用的组件主要就包括基本身份验证和子允诺身份验证。
基本认证
聚合一个密码文档,如下例:
# comment name1:password1 name2:password2:comment name3:password3使用openssl对该文档加密
$ openssl passwd MyPassword1234使用auth_basic和auth_basic_user_file来实用性认证
location / { auth_basic “Private site”; auth_basic_user_file conf.d/passwd; }和第三方认证服务集成
location /private/ { auth_request /auth; auth_request_set $auth_status $upstream_status; } location = /auth { internal; proxy_pass http://auth-server; proxy_pass_request_body off; proxy_set_header Content-Length “”; proxy_set_header X-Original-URI $request_uri; }安全控制
安全性是分层完成的,安全模型必须有多层才能真正得到加强。NGINX提供更多不同的机能来全力支持安全能力。
基于IP门牌号的安全控制
location /admin/ { deny 10.0.0.1; allow 10.0.0.0/20; allow 2001:0db8::/32; deny all; }allow和deny指令在HTTP,Server和Location上下文中有效。顺序检查规则,直到找到与远程门牌号匹配的为止。
跨域资源共享
map $request_method $cors_method { OPTIONS 11; GET 1; POST 1; default 0; } server { … location / { if ($cors_method ~ 1) { add_header Access-Control-Allow-Methods GET,POST,OPTIONS; add_header Access-Control-Allow-Origin *.example.com; add_header Access-Control-Allow-Headers DNT, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type; } if ($cors_method = 11) { add_header Access-Control-Max-Age 1728000; add_header Content-Type text/plain; charset=UTF-8; add_header Content-Length 0; return 204; } } }此示例通过使用map将GET和POST方法分组在一起进行了精简。 OPTIONS允诺方法向应用程序返回有关此伺服器的CORS规则的预检允诺。 CORS允许使用OPTIONS,GET和POST方法。设置
Access-Control-Allow-Origin标头可以使从该伺服器提供更多的内容也可以在与该标头匹配的原始页面上使用。预检允诺可以在应用程序上缓存1,728,000秒或20天。当诸如JavaScript之类的资源所允诺的资源不是其自己的域时,它会构成跨域访问CORS。当允诺被视为跨源允诺时,浏览器必须遵守CORS规则。如果浏览器没有专门允许其使用的标头,则它将不使用该资源。为了使我们的资源可以被其他子域使用,我们必须设置CORS标头,这可以通过add_header指令完成。如果允诺是具有标准内容类别的GET,HEAD或POST,并且该允诺没有特殊的标头,则浏览器将发出允诺,并且仅检查源。其他允诺方法将使浏览器发出前允诺,以检查该资源将服从的伺服器条款。如果没有适当地设置这些标头,则浏览器在尝试利用该资源时将给出错误消息。
应用程序加密
http { # All directives used below are also valid in stream server { listen 8433 ssl; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; ssl_certificate /etc/nginx/ssl/example.pem; ssl_certificate_key /etc/nginx/ssl/example.key; ssl_certificate/etc/nginx/ssl/example.ecdsa.crt;ssl_certificate_key /etc/nginx/ssl/example.ecdsa.key; ssl_session_cacheshared:SSL:10m; ssl_session_timeout 10m; } }该例子实用性SSL来加密http服务。
控制特定资源的访问
location /resources { secure_link_secret mySecret; if ($secure_link = “”) { return 403; } rewrite ^ /secured/$secure_link; } location /secured/ { internal; root /var/www; }此实用性建立一个内部且面向公众的位置块。面向公众的位置块/ resources将返回403 Forbidden,除非允诺URI包含一个md5哈希字符串,可以使用提供更多给secure_link_secret指令的密码进行验证。除非已验证URI中的哈希,否则$ secure_link变量为空字符串。
用Secret保护资源是确保文档受到保护的好方法。该Secret与URI结合使用。然后,此字符串将被md5散列,并且该md5散列的十六进制摘要在URI中使用。哈希将放入链接中,并由NGINX评估。 NGINX知道哈希之后的URI中所允诺文档的路径。 NGINX还通过secure_link_secret指令提供更多了Secret信息。 NGINX能够快速验证md5哈希并将URI存储在$ secure_link变量中。如果无法验证哈希,则将变量设置为空字符串。请务必注意,传递给secure_link_secret的参数必须是动态字符串;它不能是变量。
通过过期时间控制资源
location /resources { root /var/www; secure_link $arg_md5,$arg_expires; secure_link_md5 “$secure_link_expires$uri$remote_addr mySecret”; if ($secure_link = “”) { return 403; } if ($secure_link = “0”) { return 410; } }secure_link指令采用两个参数,并以逗号分隔。第一个参数是保存md5哈希值的变量。本示例使用HTTP参数md5。第二个参数是一个变量,它以Unix纪元时间格式保存链接到期的时间。 secure_link_md5指令采用单个参数,该参数声明用于构造md5哈希值的字符串的格式。与其他实用性一样,如果哈希未通过验证,则$secure_link变量将设置为空字符串。但是,在这种用法下,如果哈希匹配但时间已到期,则$secure_link变量将设置为0。
HTTP重或非
server { listen 80 default_server; listen [::]:80 default_server; server_name _; return 301 https://$host$request_uri; }此实用性在路由器80上监听IPv4和IPv6和任何主机名的默认伺服器。 return语句将301永久重或非返回到同一主机上的HTTPS伺服器并允诺URI。
务必始终在适当的时候重或非到HTTPS。可能会发现不需要重或非大部份允诺,而仅重或非那些在应用程序和伺服器之间传递敏感信息的允诺。在这种情况下,可能只想将return语句放在特定的位置,比如/ login。
HTTP/2
HTTP / 2是对HTTP协议的主要就修订。这个版本中完成的许多工作都集中在传输层,比如在单个TCP连接上启用完整的允诺和响应多路复用。通过对HTTP头字段进行压缩获得了效率,并增加了对允诺优先级的全力支持。该协议的另一个重要补充是伺服器能够将消息推送到应用程序。
基本实用性
server { listen 443 ssl http2 default_server; ssl_certificate server.crt; ssl_certificate_key server.key; … }要打开HTTP / 2,只需要将http2参数添加到listen指令中
gRPC
server { listen 80 http2; location / { grpc_pass grpc://backend.local:50051; } }NGINX能够接收,全权,阻抗平衡,路由器和终止gRPC调用。使用gRPC组件,NGINX可以设置,更改或删除gRPC调用标头,设置允诺超时和设置上游SSL / TLS规范。当gRPC通过HTTP / 2协议进行通信时,可以将NGINX实用性为在同一端点上接受gRPC和非gRPC Web通信。
HTTP/2服务端推送
server { listen 443 ssl http2 default_server; ssl_certificate server.crt; ssl_certificate_key server.key; root /usr/share/nginx/html; location = /demo.html { http2_push /style.css; http2_push/image1.jpg; } }要使用HTTP / 2伺服器推送,必须实用性为HTTP / 2实用性伺服器。可以指示NGINX使用http2_push指令推送特定文档。该指令采用一个参数,即要推送到应用程序的文档的完整URI路径。
容器和微服务
容器在插件层提供更多了一个抽象层,从而将软件包的安装和相关性从布署转移到了构建过程。这很重要,因为工程师可以以统一方式运行和布署的代码组件,而不管环境如何。将容器提升为可运行组件可减少依赖环境和环境之间的实用性麻烦的风险。鉴于此,组织将其插件布署在容器平台上方面有很大的动力。在容器平台上运行插件时,通常要对尽可能多的堆栈进行容器化,主要就包括全权或用户端器。 NGINX可以轻松地进行容器化和布署。它们还主要就包括许多使交付容器化插件的机能。
官方镜像
$ docker run –name my-nginx -p 80:80 \ -v /path/to/content:/usr/share/nginx/html:ro -d nginxNGINX已通过Docker Hub提供更多了正式的Docker镜像。这个官方的Docker镜像可以使用自己喜欢的插件交付平台NGINX轻松地在Docker中快速开启和运行。能够使用一个命令在容器中开启NGINX并运行它!这些官方镜像的Dockerfile和源可在GitHub上获得。以通过构建自己的Dockerfile并在FROM命令中选定官方镜像来扩展官方镜像。
建立自己的Docker镜像
通过以下的Dockerfile可以建立自己的Nginx镜像。
FROM centos:7 # Install epel repo to get nginx and install nginx RUN yum -y install epel-release && \ yum -y install nginx # add local configuration files into the image ADD /nginx-conf /etc/nginx EXPOSE 80 443 CMD [“nginx”]产品目录
├── Dockerfile └── nginx-conf ├── conf.d│ └──default.conf ├── fastcgi.conf ├── fastcgi_params ├── koi-utf ├── koi-win ├── mime.types ├── nginx.conf ├── scgi_params ├── uwsgi_params └── win-utf使用配置文件
daemon off; env APP_DNS; include /usr/share/nginx/modules/*.conf; … http { perl_set $upstream_app sub { return $ENV{“APP_DNS”}; }; server { … location / { proxy_pass https://$upstream_app; } } }要使用perl_set,必须安装ngx_http_perl_module。可以通过动态或动态(从源代码构建)加载组件来实现。默认情况下,NGINX从其环境中删除大部份的是环境变量;需要使用env指令声明不想删除的任何变量。 perl_set指令采用两个参数:要设置的变量名称和呈现结果的perl字符串。
Kubernetes Ingress Controller
Kubernetes是容器编排和管理工作的领先平台。入口控制器Ingress Controller是将流量路由器到插件其余部分的边缘容器。 NGINX非常适合担任此角色,并使其易于实用性。 NGINX-Ingress项目通过DockerHub映像提供更多了NGINX开放源代码入口控制器。使用NGINX入口控制器启用Kubernetes集群可提供更多NGINX的大部份相同机能,但具有Kubernetes网络和DNS的附加机能来路由流量。
Nginx作为常见的Web服务被广泛地用于布署应用服务,了解和用好Nginx是软件架构师的必修课。