0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

介绍 Nginx的基本概念,性能,SSL 安装

Linux爱好者 2018-02-08 09:12 次阅读

大家好,分享即关爱,我们很乐意和你分享一些新的知识,我们准备了一个 Nginx 的教程,分为三个系列,如果你对 Nginx 有所耳闻,或者想增进 Nginx 方面的经验和理解,那么恭喜你来对地方了。

我们会告诉你 Nginx 如何工作及其背后的理念,还有如何优化以加快应用的性能,如何安装启动和保持运行。

这个教程有三个部分:

基本概念 —— 这部分需要去了解 Nginx 的一些指令和使用场景,继承模型,以及 Nginx 如何选择 server 块,location 的顺序。

性能 —— 介绍改善 Nginx 速度的方法和技巧,我们会在这里谈及 gzip 压缩,缓存,buffer 和超时。

SSL 安装 —— 如何配置服务器使用 HTTPS

创建这个系列,我们希望,一是作为参考书,可以通过快速查找到相关问题(比如 gzip 压缩,SSL 等)的解决方式,也可以直接通读全文。为了获得更好的学习效果,我们建议你在本机安装 Nginx 并且尝试进行实践。

tcp_nodelay,tcp_nopush和sendfile

tcp_nodelay

在 TCP 发展早期,工程师需要面对流量冲突和堵塞的问题,其中涌现了大批的解决方案,其中之一是由 JohnNagle 提出的算法

Nagle 的算法旨在防止通讯被大量的小包淹没。该理论不涉及全尺寸 tcp 包(最大报文长度,简称 MSS)的处理。只针对比 MSS 小的包,只有当接收方成功地将以前的包(ACK)的所有确认发送回来时,这些包才会被发送。在等待期间,发送方可以缓冲更多的数据之后再发送。

ifpackage.size>=MSS.size

send(package)

elsifacks.all_received?

send(package)

else

#acumulatedata

end

与此同时,诞生了另一个理论,延时 ACK

在 TCP 通讯中,在发送数据后,需要接收回应包(ACK)来确认数据被成功传达。

延时 ACK 旨在解决线路被大量的 ACK 包拥堵的状况。为了减少 ACK 包的数量,接收者等待需要回传的数据加上 ACK 包回传给发送方,如果没有数据需要回传,必须在至少每 2 个 MSS,或每 200 至 500 毫秒内发送 ACK(以防我们不再收到包)。

ifpackages.any?

send

elsiflast_ack_send_more_than_2MSS_ago?||200_ms_timer.finished?

send

else

#wait

end

正如你可能在一开始就注意到的那样 —— 这可能会导致在持久连接上的一些暂时的死锁。让我们重现它!

假设:

初始拥塞窗口等于 2。拥塞窗口是另一个 TCP 机制的一部分,称为慢启动。细节现在并不重要,只要记住它限制了一次可以发送多少个包。在第一次往返中,我们可以发送 2 个 MSS 包。在第二次发送中:4 个 MSS 包,第三次发送中:8 个MSS,依此类推。

4 个已缓存的等待发送的数据包:A, B, C, D

A, B, C是 MSS 包

D 是一个小包

场景:

由于是初始的拥塞窗口,发送端被允许传送两个包:A 和 B

接收端在成功获得这两个包之后,发送一个 ACK

发件端发送 C 包。然而,Nagle 却阻止它发送 D 包(包长度太小,等待 C 的ACK)

在接收端,延迟 ACK 使他无法发送 ACK(每隔 2 个包或每隔 200 毫秒发送一次)

在 200ms 之后,接收器发送 C 包的 ACK

发送端收到 ACK 并发送 D 包

介绍 Nginx的基本概念,性能,SSL 安装

在这个数据交换过程中,由于 Nagel 和延迟 ACK 之间的死锁,引入了 200ms 的延迟。

Nagle 算法是当时真正的救世主,而且目前仍然具有极大的价值。但在大多数情况下,我们不会在我们的网站上使用它,因此可以通过添加 TCP_NODELAY 标志来安全地关闭它。

tcp_nodelay on; # sets TCP_NODELAY flag, used on keep-alive connections

享受这200ms提速吧!

sendfile

正常来说,当要发送一个文件时需要下面的步骤:

malloc(3) – 分配一个本地缓冲区,储存对象数据。

read(2) – 检索和复制对象到本地缓冲区。

write(2) – 从本地缓冲区复制对象到 socket 缓冲区。

这涉及到两个上下文切换(读,写),并使相同对象的第二个副本成为不必要的。正如你所看到的,这不是最佳的方式。值得庆幸的是还有另一个系统调用,提升了发送文件(的效率),它被称为:sendfile(2)(想不到吧!居然是这名字)。这个调用在文件 cache 中检索一个对象,并传递指针(不需要复制整个对象),直接传递到 socket 描述符,Netflix 表示,使用 sendfile(2) 将网络吞吐量从 6Gbps 提高到了 30Gbps。

然而,sendfile(2) 有一些注意事项:

不可用于 UNIX sockets(例如:当通过你的上游服务器发送静态文件时)

能否执行不同的操作,取决于操作系统

在 nginx 中打开它

sendfile on;

tcp_nopush

tcp_nopush 与 tcp_nodelay 相反。不是为了尽可能快地推送数据包,它的目标是一次性优化数据的发送量。

在发送给客户端之前,它将强制等待包达到最大长度(MSS)。而且这个指令只有在 sendfile 开启时才起作用。

sendfileon;

tcp_nopushon;

看起来 tcp_nopush 和 tcp_nodelay 是互斥的。但是,如果所有 3 个指令都开启了,nginx 会:

确保数据包在发送给客户之前是已满的

对于最后一个数据包,tcp_nopush 将被删除 —— 允许 TCP 立即发送,没有 200ms 的延迟

我应该使用多少进程?

工作进程

worker_process 指令会指定:应该运行多少个 worker。默认情况下,此值设置为 1。最安全的设置是通过传递 auto 选项来使用核心数量。

但由于 Nginx 的架构,其处理请求的速度非常快 – 我们可能一次不会使用超过 2-4 个进程(除非你正在托管 Facebook 或在 nginx 内部执行一些 CPU 密集型的任务)。

worker_process auto;

worker 连接

与 worker_process直接绑定的指令是 worker_connections。它指定一个工作进程可以一次打开多少个连接。这个数目包括所有连接(例如与代理服务器的连接),而不仅仅是与客户端的连接。此外,值得记住的是,一个客户端可以打开多个连接,同时获取其他资源。

worker_connections 1024;

打开文件数目限制

在基于 Unix 系统中的“一切都是文件”。这意味着文档、目录、管道甚至套接字都是文件。系统对一个进程可以打开多少文件有一个限制。要查看该限制:

ulimit-Sn#softlimit

ulimit-Hn#hardlimit

这个系统限制必须根据 worker_connections 进行调整。任何传入的连接都会打开至少一个文件(通常是两个连接套接字以及后端连接套接字或磁盘上的静态文件)。所以这个值等于 worker_connections*2 是安全的。幸运的是,Nginx 提供了一个配置选项来增加这个系统的值。要使用这个配置,请添加具有适当数目的 worker_rlimit_nofile 指令并重新加载 nginx。

worker_rlimit_nofile 2048;

配置

worker_processauto;

worker_rlimit_nofile2048;#Changesthelimitonthemaximumnumberofopenfiles(RLIMIT_NOFILE)forworkerprocesses.

worker_connections1024;#Setsthemaximumnumberofsimultaneousconnectionsthatcanbeopenedbyaworkerprocess.

最大连接数

如上所述,我们可以计算一次可以处理多少个并发连接:

最大连接数=

worker_processes*worker_connections

(keep_alive_timeout+avg_response_time)*2

keep_alive_timeout (后续有更多介绍) + avg_response_time 告诉我们:单个连接持续了多久。我们也除以 2,通常情况下,你将有一个客户端打开 2 个连接的情况:一个在 nginx 和客户端之间,另一个在 nginx 和上游服务器之间。

Gzip

启用 gzip 可以显著降低响应的(报文)大小,因此,客户端(网页)会显得更快些。

压缩级别

Gzip 有不同的压缩级别,1 到 9 级。递增这个级别将会减少文件的大小,但也会增加资源消耗。作为标准我们将这个数字(级别)保持在 3 – 5 级,就像上面说的那样,它将会得到较小的节省,同时也会得到更大的 CPU 使用率。

这有个通过 gzip 的不同的压缩级别压缩文件的例子,0 代表未压缩文件。

curl -I -H 'Accept-Encoding: gzip,deflate' https://netguru.co/

❯du-sh./*

64K./0_gzip

16K./1_gzip

12K./2_gzip

12K./3_gzip

12K./4_gzip

12K./5_gzip

12K./6_gzip

12K./7_gzip

12K./8_gzip

12K./9_gzip

❯ls-al

-rw-r--r--1matDobekstaff617113Nov08:460_gzip

-rw-r--r--1matDobekstaff123313Nov08:481_gzip

-rw-r--r--1matDobekstaff121233Nov08:482_gzip

-rw-r--r--1matDobekstaff120033Nov08:483_gzip

-rw-r--r--1matDobekstaff112643Nov08:494_gzip

-rw-r--r--1matDobekstaff111113Nov08:505_gzip

-rw-r--r--1matDobekstaff110973Nov08:506_gzip

-rw-r--r--1matDobekstaff110803Nov08:507_gzip

-rw-r--r--1matDobekstaff110713Nov08:518_gzip

-rw-r--r--1matDobekstaff110053Nov08:519_gzip

gzip_http_version 1.1;

这条指令告诉 nginx 仅在 HTTP 1.1 以上的版本才能使用 gzip。我们在这里不涉及 HTTP 1.0,至于 HTTP 1.0 版本,它是不可能既使用 keep-alive 和 gzip 的。因此你必须做出决定:使用 HTTP 1.0 的客户端要么错过 gzip,要么错过 keep-alive。

配置

gzipon;#enablegzip

gzip_http_version1.1;#turnongzipforhttp1.1andabove

gzip_disable"msie6";#IE6hadissueswithgzip

gzip_comp_level5;#inccompresionlevel,andCPUusage

gzip_min_length100;#minimalweighttogzipfile

gzip_proxiedany;#enablegzipforproxiedrequests(e.g.CDN)

gzip_buffers168k;#compressionbuffers(ifweexceedthisvalue,diskwillbeusedinsteadofRAM)

gzip_varyon;#addheaderVaryAccept-Encoding(moreonthatinCachingsection)

#definefileswhichshouldbecompressed

gzip_typestext/plain;

gzip_typestext/css;

gzip_typesapplication/javascript;

gzip_typesapplication/json;

gzip_typesapplication/vnd.ms-fontobject;

gzip_typesapplication/x-font-ttf;

gzip_typesfont/opentype;

gzip_typesimage/svg+xml;

gzip_typesimage/x-icon;

缓存

缓存是另一回事,它能提升用户的请求速度。

管理缓存可以仅由 2 个 header 控制:

在 HTTP/1.1 中用Cache-Control管理缓存

Pragma 对于 HTTP/1.0 客户端的向后兼容性

缓存本身可以分为两类:公共缓存和私有缓存。公共缓存是被多个用户共同使用的。专用缓存专用于单个用户。我们可以很容易地区分,应该使用哪种缓存:

add_headerCache-Controlpublic;

add_headerPragmapublic;

对于标准资源,我们想保存1个月:

location~*\.(jpg|jpeg|png|gif|ico|css|js)${

expires1M;

add_headerCache-Controlpublic;

add_headerPragmapublic;

}

上面的配置似乎足够了。然而,使用公共缓存时有一个注意事项。

让我们看看如果将我们的资源存储在公共缓存(如 CDN)中,URI 将是唯一的标识符。在这种情况下,我们认为 gzip 是开启的。

有2个浏览器:

旧的,不支持 gzip

新的,支持 gzip

旧的浏览器给 CDN 发送了一个 netguru.co/style 请求。但是 CDN 也没有这个资源,它将会给我们的服务器发送请求,并且返回未经压缩的响应。CDN 在哈希里存储文件(为以后使用):

{

...

netguru.co/styles.css=>FILE("/sites/netguru/style.css")

...

}

然后将其返回给客户端。

现在,新的浏览器发送相同的请求到 CDN,请求 netguru.co/style.css,获取 gzip 打包的资源。由于 CDN 仅通过 URI 标识资源,它将为新浏览器返回一样的未压缩资源。新的浏览器将尝试提取未打包的文件,但是将获得无用的东西。

如果我们能够告诉公共缓存是怎样进行 URI 和编码的资源识别,我们就可以避免这个问题。

{

...

(netguru.co/styles.css,gzip)=>FILE("/sites/netguru/style.css.gzip")

(netguru.co/styles.css,text/css)=>FILE("/sites/netguru/style.css")

...

}

这正是 Vary Accept-Encoding: 完成的。它告诉公共缓存,可以通过 URI 和 Accept-Encoding header 区分资源。

所以我们的最终配置如下:

location~*\.(jpg|jpeg|png|gif|ico|css|js)${

expires1M;

add_headerCache-Controlpublic;

add_headerPragmapublic;

add_headerVaryAccept-Encoding;

}

超时

client_body_timeout 和 client_header_timeout 定义了 nginx 在抛出 408(请求超时)错误之前应该等待客户端传输主体或头信息的时间。

send_timeout 设置向客户端发送响应的超时时间。超时仅在两次连续的写入操作之间被设置,而不是用于整个响应的传输过程。如果客户端在给定时间内没有收到任何内容,则连接将被关闭。

设置这些值时要小心,因为等待时间过长会使你容易受到攻击者的攻击,并且等待时间太短的话会切断与速度较慢的客户端的连接。

#Configuretimeouts

client_body_timeout12;

client_header_timeout12;

send_timeout10;

Buffers

client_body_buffer_size

设置读取客户端请求正文的缓冲区大小。如果请求主体大于缓冲区,则整个主体或仅其部分被写入临时文件。对 client_body_buffer_size 而言,设置 16k 大小在大多数情况下是足够的。

这是又一个可以产生巨大影响的设置,必须谨慎使用。太小了,则 nginx 会不断地使用 I/O 把剩余的部分写入文件。太大了,则当攻击者可以打开所有连接但你无法在系统上分配足够缓冲来处理这些连接时,你可能容易受到 DOS 攻击。

client_header_buffer_size 和 large_client_header_buffers

如果 header 不能跟 client_header_buffer_size 匹配上,就会使用 large_client_header_buffers。如果请求也不适合 large_client_header_buffers,将给客户端返回一个错误提示。对于大多数的请求来说,1KB 的缓存是足够的。但是,如果一个包含大量记录的请求,1KB 是不够的。

如果请求行的长度超限,将给客户端返回一个 414(请求的 URI 太长)错误提示。如果请求的 header 长度超限,将抛出一个 400(错误请求)的错误代码

client_max_body_size

设置客户端请求主体的最大允许范围,在请求头字段中指定“内容长度”。如果您希望允许用户上传文件,调整此配置以满足您的需要。

配置

client_body_buffer_size16K;

client_header_buffer_size1k;

large_client_header_buffers21k;

client_max_body_size8m;

Keep-Alive

HTTP 所依赖的 TCP 协议需要执行三次握手来启动连接。这意味着在服务器可发送数据(例如图像)之前,需要在客户机和服务器之间进行三次完整的往返。

假设你从 Warsaw 请求的 /image.jpg,并连接到在柏林最近的服务器:

Open connection

TCP Handshake:

Warsaw->------------------ synchronize packet(SYN) ----------------->- Berlin

Warsaw-<--------- synchronise-acknowledgement packet(SYN-ACK) ------<- Berlin

Warsaw->------------------- acknowledgement(ACK) ------------------->- Berlin

Data transfer:

Warsaw->---------------------- /image.jpg --------------------------->- Berlin

Warsaw-<--------------------- (image data) --------------------------<- Berlin

Close connection

对于另一次请求,你将不得不再次执行整个初始化。如果你在短时间内发送多次请求,这可能会快速累积起来。这样的话 keep-alive 使用起来就方便了。在成功响应之后,它保持连接空闲给定的时间段(例如 10 秒)。如果在这段时间内有另一个请求,现有的连接将被重用,空闲时间将被刷新。

Nginx 提供了几个指令来调整 keepalive 设置。这些可以分为两类:

在客户端和 nginx 之间 keep-alive

keepalive_disablemsie6;#disableselectedbrowsers.

#Thenumberofrequestsaclientcanmakeoverasinglekeepaliveconnection.Thedefaultis100,butamuchhighervaluecanbeespeciallyusefulfortestingwithaload‑generationtool,whichgenerallysendsalargenumberofrequestsfromasingleclient.

keepalive_requests100000;

#Howlonganidlekeepaliveconnectionremainsopen.

keepalive_timeout60;

在 nginx 和上游服务器之间 keep-alive

upstreambackend{

#Thenumberofidlekeepaliveconnectionstoanupstreamserverthatremainopenforeachworkerprocess

keepalive16;

}

server{

location/http/{

proxy_passhttp://http_backend;

proxy_http_version1.1;

proxy_set_headerConnection"";

}

}

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Linux
    +关注

    关注

    87

    文章

    11224

    浏览量

    208903
  • SSL
    SSL
    +关注

    关注

    0

    文章

    125

    浏览量

    25720
  • nginx
    +关注

    关注

    0

    文章

    143

    浏览量

    12161

原文标题:Nginx 教程(2):性能

文章出处:【微信号:LinuxHub,微信公众号:Linux爱好者】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    NanoPi NEO - 可靠的Nginx 网络服务器

    服务器部署,并删除匿名用户和测试数据库。#mysql_secure_installation根据提示进行选择:3. 安装nginx如果你之前已经安装了Apache2,则需要先移除apache2
    发表于 06-20 15:43

    天线分集技术的基本概念介绍

    基本概念往往有助于理解多变的无线电通信链接品质,一旦理解了这些基本概念,其中许多问题可以通过一种低成本、易实现的被称作天线分集(antenna diversity)的技术来实现。
    发表于 07-02 06:04

    linux的ssl配置方法

    我用的是wdcp,在wdcp的双引擎模式(apache+nginx)下,利用nginx来给网站制作ssl
    发表于 07-17 07:21

    RAM技术的基本概念

    目前的铁路和电力及航空航天等多个行业已纷纷推行系统可靠性分析RAM技术,研发最佳的设备运行维护方案,从而消除设备隐患,避免设备事故发生,降低装置非计划停工次数和设备运行维护费用,促进装置安全长周期运行,具有重要的现实意义。本文主要概括介绍RAM技术的基本概念
    发表于 12-16 07:04

    阻抗控制相关的基本概念

    阻抗控制部分包括两部分内容:基本概念及阻抗匹配。本篇主要介绍阻抗控制相关的一些基本概念
    发表于 02-25 08:11

    USB基本概念及从机编程方法介绍

    慕课苏州大学.嵌入式开发及应用.第四章.较复杂通信模块.USB基本概念及从机编程方法0 目录4 较复杂通信模块4.4 USB基本概念及从机编程方法4.4.1 课堂重点4.4.2 测试与作业5 下一
    发表于 11-08 09:14

    Uart协议(即串口)的基本概念及相关知识介绍

    一一介绍,今天要来了解的是Uart协议,即我们通常所说的串口通信。一、Uart协议(即串口)的基本概念UART全称为Universal Asynchronous Receiver
    发表于 01-17 08:55

    主要学习下nginx安装配置

    处理。因为有了中间件,使得大型网站在规划有了更好的层次性,维护上更加方便。也可以实现负载均衡、安全防护等。Nginx是一个开源高性能、可靠的HTTP中间件、代理服务,在目前企业中得到了很大的利用。今天
    发表于 10-19 14:12

    基于RF射频知识基本概念及DTD无线产品介绍

    基于RF射频知识基本概念及DTD无线产品介绍
    发表于 10-25 08:38 8次下载
    基于RF射频知识<b class='flag-5'>基本概念</b>及DTD无线产品<b class='flag-5'>介绍</b>

    详细介绍时序基本概念Timing arc

    时序分析基本概念介绍——Timing Arc
    的头像 发表于 01-02 09:29 2.4w次阅读
    详细<b class='flag-5'>介绍</b>时序<b class='flag-5'>基本概念</b>Timing arc

    眼图基本概念介绍.ppt

    眼图基本概念介绍.ppt
    发表于 11-08 15:05 3次下载

    搭建Keepalived+Lvs+Nginx高可用集群负载均衡

      一、Nginx安装 二、配置反向代理 三、配置负载均衡 四、upstream指令参数 五、配置ssl证书提供https访问 六、配置ha nginx 七、LVS(Linux Vir
    的头像 发表于 06-25 15:39 2816次阅读
    搭建Keepalived+Lvs+<b class='flag-5'>Nginx</b>高可用集群负载均衡

    介绍时序分析的基本概念lookup table

    今天要介绍的时序分析基本概念是lookup table。中文全称时序查找表。
    的头像 发表于 07-03 14:30 1435次阅读
    <b class='flag-5'>介绍</b>时序分析的<b class='flag-5'>基本概念</b>lookup table

    时序分析Slew/Transition基本概念介绍

    今天要介绍的时序分析基本概念是Slew,信号转换时间,也被称为transition time。
    的头像 发表于 07-05 14:50 3025次阅读
    时序分析Slew/Transition<b class='flag-5'>基本概念</b><b class='flag-5'>介绍</b>

    时序分析基本概念介绍—Timing Arc

    今天我们要介绍的时序基本概念是Timing arc,中文名时序弧。这是timing计算最基本的组成元素,在昨天的lib库介绍中,大部分时序信息都以Timing arc呈现。
    的头像 发表于 07-06 15:00 3311次阅读
    时序分析<b class='flag-5'>基本概念</b><b class='flag-5'>介绍</b>—Timing Arc