当前位置: 首页 > 科技观察

高性能NginxHTTPS调优!加速HTTPS30%

时间:2023-03-19 15:59:57 科技观察

为什么要优化NginHTTPS延迟Nginx经常被用作最常见的服务器,经常被用作负载均衡器(LoadBalancer)、反向代理(ReverseProxy)和网关(Gateway)和很快。一个正确配置的Nginx服务器单机应该能够承受每秒大约50K到80K的请求,同时将CPU负载保持在可控范围内。但在很多情况下,负载并不是初级优化的重点。比如卡拉搜索,我们希望用户每次按键都能体验到即时搜索的感觉,即每次搜索请求都要在100ms-200ms内端到端的返回给用户。让用户搜索无“卡”、“加载”。因此,对我们来说,优化请求延迟是最重要的优化方向。在本文中,我们首先介绍Nginx中哪些TLS设置可能与请求延迟有关,以及如何调整它们以最大化加速。然后我们以优化Kara搜索Nginx服务器为例,分享如何调整NginxTLS/SSL设置,让初??次搜索的用户速度提升30%左右。我们将详细讨论我们在每个步骤中做了哪些优化,优化的动机和效果。希望能对其他遇到类似问题的同学有所帮助。TLS握手和延迟很多时候,开发者认为如果不是绝对关心性能,那么就没有必要去了解底层,优化更多的细节。这句话在很多情况下是合适的,因为在很多情况下,必须对复杂的底层逻辑进行包装,才能让上层应用开发的复杂度可控。例如,如果你只需要开发一个APP或网站,可能不需要关注汇编细节和编译器如何优化你的代码——毕竟苹果或安卓上的很多优化都是在底层完成的。那么,了解底层TLS与应用层的Nginx延迟优化有什么关系呢?答案是,在大多数情况下,优化网络延迟实际上是试图减少用户和服务器之间的数据传输次数,这称为往返次数。由于物理限制,光速从北京到云南大约需要20毫秒。如果一不小心让数据在北京和云南之间多次往返,那么延迟必然会增加。因此,如果你需要优化请求延迟,了解一点底层网络上下文是有帮助的,很多时候甚至是你能否轻松理解一个优化的关键。在本文中,我们不会深入讨论TCP或TLS机制的太多细节。感兴趣的可以参考《HighPerformanceBrowserNetworking》[4]一书,可以免费阅读。例如,下图显示了如果您的服务启用了HTTPS,在任何数据传输开始之前会发生什么。可以看到,在你的用户得到他需要的数据之前,底层数据包已经在用户和你的服务器之间来回了3次。假设每次往返需要28毫秒,则用户在接收数据之前已经等待了224毫秒。同时,这个28毫秒其实是一个非常乐观的假设。在国内电信、联通、移动等各种复杂的网络情况下,用户与服务器之间的延迟更是不可控。另一方面,通常一个网页需要几十个请求,而这些请求不一定都是并行的,所以用几十乘以224毫秒,页面可能会在几秒内打开。所以,原则上,如果可能的话,我们需要尽量减少用户和服务器之间的往返。在以下设置中,对于每个设置,我们将讨论为什么此设置可能有助于减少往返次数。Nginx中的TLS设置那么在Nginx的设置中,如何调整参数来降低延迟呢?开启HTTP/2HTTP/2标准是Google的SPDY的改进。与HTTP1.1相比,它提高了很多性能,尤其是在多个请求并行时可以显着减少。在现在的网络上,一个网页平均需要被请求几十次,而在HTTP1.1时代,浏览器可以做的是打开几个连接(通常是6个)进行并行请求,而在HTTP2中,一个连接可以发出并行请求。HTTP2原生支持多个并行请求,因此大大减少了顺序执行请求的往返,所以可以优先开启。如果你想亲眼看看HTTP1.1和HTTP2.0之间的速度差异,你可以试试:https://www.httpvshttps.com/。在我的网络测试中,HTTP/2比HTTP1.1快66%。在Nginx中启用HTTP2.0非常简单,只需在listen443ssl中添加一个http2标志即可;#改为listen443sslhttp2;如果您担心您的用户使用的是旧客户端,例如Python请求,HTTP2尚不支持,那么其实不用担心。如果用户的客户端不支持HTTP2,连接将自动降级为HTTP1.1,保持向后兼容性。因此,所有使用旧客户端的用户仍然不受影响,而新客户端则可以享受HTTP/2的新特性。如何确认你的网站或API是否启用了HTTP2打开Chrome中的开发者工具,点击Protocol,可以看到所有请求使用的协议。如果协议列的值为h2,则使用HTTP2。当然还有一种方式就是直接使用curl。如果返回的状态前面有HTTP/2,自然开启了HTTP/2。?~curl--http2-Ihttps://kalasearch.cnHTTP/2403server:Tenginecontent-type:application/xmlcontent-length:264date:Tue,22Dec202018:38:46GMTx-oss-request-id:5FE23D363ADDB93430197043x-oss-cdn-auth:successx-oss-server-time:0x-alicdn-da-ups-status:endOs,0,403通过:cache13.l2et2[148,0],cache10.l2ot7[291,0],cache4.us13[360,0]timing-allow-origin:*eagleid:2ff6169816086623266688093e调整密码优先级并尝试选择更新更快的密码以帮助减少延迟:#Manuallyenablecipherlistssl_prefer_server_cipherson;#preferalistofcipherstopreventoldandslowciphersssl_ciphers'AESGCM5DH:EDH6+2EDH';EnableOCSPStapling在国内,这可能是对使用Let'sEncrypt证书的服务或网站影响最大的延迟优化。如果未启用OCSPStapling,有时需要在用户连接到您的服务器时验证证书。而且因为一些不明原因(这个就不解释了)Let'sEncrypt的验证服务器不是很流畅,所以会造成几秒甚至十几秒的延迟。这个问题在iOS设备上尤为严重。解决这个问题有两种方法:如果你没有使用Let'sEncrypt,可以尝试更换为阿里云提供的免费DV证书。如果启用OCSPStapling,则可以省略证书验证步骤。省去一次往返,尤其是网络情况不可控的往返,可能会大大减少你的延迟。在Nginx中启用OCSPStapling也很简单,只需要设置:ssl_staplingon;ssl_stapling_verifyon;ssl_trusted_certificate/path/to/full_chain.pem;如何检测是否启用了OCSPStapling?可以通过如下命令opensls_client-connecttest.kalasearch.cn:443-servernamekalasearch.cn-status-tlsextdebug&1|grep-i"OCSPresponse"进行测试。如果结果为OCSResponse:OCSPResponseData:OCSPResponseStatus:successful(0x0)ResponseType:BasicOCSPResponse,说明已经启用。调整ssl_buffer_sizessl_buffer_size控制发送数据时的缓冲区大小,默认设置为16k。值越小,延迟越小,加头会使开销变大,反之,延迟越大,开销越小。因此,如果你的服务是RESTAPI或网站,降低这个值可以减少延迟和TTFB,但如果你的服务器用于传输大文件,则可以保持16k。如果是网站或者RESTAPI,推荐值为4k,但是这个值的最优值会因为数据不同而明显不同,所以请尝试2-16k之间的不同值。在Nginxssl_buffer_size4k中调整这个值也很容易;启用SSLSession缓存启用SSLSession缓存可以大大减少TLS的重复验证和TLS握手的往返。虽然session缓存会占用一定的内存,但是1M内存可以缓存4000个连接,可以说是非常非常划算了。同时,对于大多数网站和服务来说,达到4000个并发连接本身就需要非常非常庞大的用户群,所以才可以放心开启。#这里ssl_session_cache设置使用50M内存,4小时连接超时关闭时间ssl_session_timeout#EnableSSLcachetospeedupforreturnvisitorsssl_session_cacheshared:SSL:50m;#speedupfirsttime.1m~=4000connectionsssl_session_timeout4h;卡拉搜索如何降低30%的请求延迟,是国内Algolia帮助开发者快速搭建即时搜索功能(instantsearch),做国内最快最易用的search-as-a-service。开发者连接后,所有的搜索请求都可以通过KaraAPI直接返回给终端用户。为了让用户有即时的搜索体验,我们需要在每次按键后的极短时间内(通常为100ms到200ms)将结果返回给用户。因此每次搜索需要在引擎处理时间的50毫秒以内和端到端时间的200毫秒以内。我们用豆瓣电影的数据做了一个电影搜索的demo。如果您有兴趣,请体验即时搜索。尝试搜索“无间道”或“西游记”来体验速度和相关性:https://movies-demo.kalasearc...每个请求的延迟预算只有100到200毫秒,我们必须考虑每一步的延迟。简化一下,每个搜索请求需要经历的延迟有一个总延迟=用户请求到达服务器(T1)+逆向生成处理(NginxT2)+数据中心延迟(T3)+服务器处理(Kara引擎T4)+用户请求return(T3+T1)以上延迟中,T1只与用户与服务器的物理距离有关,而T3很小,可以忽略不计。所以我们能控制的大致只有T2和T4,分别是Nginx服务器的处理时间和Kara引擎的处理时间。Nginx在这里作为一个反向代理来处理一些安全、流量控制和TLS逻辑,而Kara的引擎是一个基于Lucene的反向引擎。我们首先考虑的第一种可能性:延迟是否来自Kara引擎?在下图所示的Grafana仪表盘中,我们看到除了不时出现一些慢查询外,95%的搜索服务器处理延迟都在20毫秒以内。与基准ElasticSearch引擎在相同数据集上的P95搜索延迟相比,约为200毫秒,排除了引擎速度慢的可能。在阿里云监控中,我们设置从全国各地向Kara服务器发送搜索请求。我们最终发现SSL的处理时间经常超过300毫秒,这意味着在T2这一步,Nginx已经用完了我们所有的请求时间预算,比如TLS握手。同时查看后发现,在苹果设备上的搜索速度极慢,尤其是第一次访问的设备。因此,我们粗略判断应该是因为我们使用的Let'sEncrypt证书。我们按照上面的步骤调整了Nginx的设置,总结了写这篇文章的步骤。调整NginxTLS设置后,SSL时间从平均140ms缩短到110ms左右(全国各省、联通、移动测试点),苹果设备首次访问慢的问题也消失了。调整后,全国测试的搜索延迟降低到150毫秒左右。总结调整Nginx中的TLS设置会对使用HTTPS的服务和网站的延迟产生巨大影响。本文总结了Nginx中TLS相关的设置,详细讨论了每个设置对延迟可能产生的影响,并给出了调整建议。