加入收藏 | 设为首页 | 会员中心 | 我要投稿 核心网 (https://www.hxwgxz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 电商 > 正文

Web服务端性能提升实践

发布时间:2021-01-20 21:08:01 所属栏目:电商 来源:网络整理
导读:《Web服务端性能提升实践》要点: 本文介绍了Web服务端性能提升实践,希望对您有用。如果有疑问,可以联系我们。 随着互联网的不断发展,日常生活中越来越多的需求通过网络来实现,从衣食住行到金融教育,从口袋到身份,人们无时无刻不依赖着网络,而且越来越多的
副标题[/!--empirenews.page--]

《Web服务端性能提升实践》要点:
本文介绍了Web服务端性能提升实践,希望对您有用。如果有疑问,可以联系我们。

随着互联网的不断发展,日常生活中越来越多的需求通过网络来实现,从衣食住行到金融教育,从口袋到身份,人们无时无刻不依赖着网络,而且越来越多的人通过网络来完成自己的需求.

作为直接面对来自客户请求的Web服务端,无疑要同时承受更多的请求,并为用户提供更好的体验.这个时候Web端的性能常常会成为业务发展的瓶颈,提升性能刻不容缓.本文作者在开发过程中总结了一些提升Web服务端性能的经验,与大家分享.

问题分析

对于Web服务端性能,首先我们分析一下相关指标.从用户角度讲,用户调用Web服务时,请求返回时间越短,用户体验越好.从服务端角度讲,同一时间能承载用户请求量越大,服务端性能就越强.综合两方面,我们总结性能优化的两个方向:

1. 增加服务端所能支撑并发请求的最大数量;

2. 提高每个请求处理速度.

明确了优化方向,首先介绍一种服务端通常的架构模式,即来自浏览器或者App的Web一个请求,在服务端经过哪几层结构被处理并返回的.

架构模式:IP负载均衡->缓存服务器->反向代理->应用服务器->数据库

如图1所示,为了说明方便,我们来举个实际的例子: LVS(Keepalived)->Squid->nginx->Go->MySQL

:服务端架构

图1:服务端架构

我们对请求在每层做分发处理,这样可以使下一级结构有多个分支同时工作,来提高总体的最大并发数.

结合架构,我们来分析通常有哪些问题在拖了性能的后腿,以及找出对应的解决方法.

正常情况下,IP负载均衡,缓存服务器和nginx代理这几层主要是集群稳定性问题.容易出现性能瓶颈的地方往往是应用服务器层和数据库层,我们下面来列举几个例子:

1. 阻塞的影响

(1)问题:

大部分Web请求都是阻塞性质的,当一个请求被处理时,进程就会被挂起(占用CPU)直至请求完成.在大多数情况下,Web请求完成的足够快,所以这个问题并不被关注.然而,对于那些响应时间来完成的请求(像返回数据量大的请求或外部API),这意味着应用程序被锁定直至处理结束,这期间,其他的请求不会被处理,很明显,这些无效的等待时间浪费掉了,并且占用系统资源,严重的影响了我们可以负担的并发请求的数量.

(2)解决办法:

Web服务端在等待上一个请求处理的过程中,我们可以让I/O循环打开以便处理其他应用请求,直到处理完成时启动一个请求并给予反馈,而不再是等待请求完成的过程中挂起进程.这样,我们可以节省一些没有必要的等待时间,用这些时间去处理更多的请求,这样我们就可以大大增加请求的吞吐量,也就是在宏观上提高了我们可处理的并发请求数.

(3)例子

这里我们用Python的一款Web框架Tornado来具体说明改变阻塞方式提高并发性能.

场景:我们构建一个向远端(某个十分稳定的网站)发送HTTP请求的简单Web应用.这期间,网络传输稳定,我们不考虑网络来带的影响.

在这个例子中,我们使用Siege(一款压力测试软件)对服务端在10秒内执行大约10个并发请求.

如图2所示,我们可以很容易看出,这里的问题是无论每个请求自身返回多么快,服务器对远端的访问请求往返都会产生足够大的滞后,因为进程直到请求完成并且数据被处理前都一直处于强制挂起状态.当一两个请求时这还不是一个问题,但达到100个(甚至10个)用户时,这意味着整体变慢.如图,不到10秒时间10个相似用户的平均响应时间达到了1.99秒,共计29次.这个例子只展示了非常简单的逻辑.如果你要添加其他业务逻辑或数据库的调用的话,结果会更糟糕.增加更多的用户请求时,同时可被处理的请求就会增长缓慢,甚至有些请求会发生超时或失败.

阻塞式响应

图2:阻塞式响应

下面我们用Tornado执行非阻塞的HTTP请求.

如图3所示,我们从每秒3.20个事务提升到了12.59,在相同的时间内总共提供了118次请求.这真是一个非常大的改善!正如你所想象的,随着用户请求增多和测试时间增长时,它将能够提供更多连接,并且不会遇到上面版本遭受的变慢的问题.从而稳定的提高了可负载的并发请求数.

非阻塞式响应

图3:非阻塞式响应

2. 计算效率对响应时间和并发数的影响

先来介绍一下基础知识:一个应用程序是运行在机器上的一个进程;进程是一个运行在自己内存地址空间里的独立执行体.一个进程由一个或多个操作系统线程组成,这些线程其实是共享同一个内存地址空间的一起工作的执行体.

(1)问题

传统计算方式单线程运行,效率低,计算能力弱.

(2)解决办法

一种解决办法就是完全避免使用线程.例如,可以使用多个进程将重担交给操作系统来处理.但是,有个劣势就是,我们必须处理所有进程间通信,通常这比共享内存的并发模型有更多的开销.

另一种办法是用多线程工作,不过,公认的,使用多线程的应用难以做到准确,同步不同的线程,对数据加锁,这样同时就只有一个线程可以变更数据.不过过去的软件开发经验告诉我们这会带来更高的复杂度,更容易使代码出错以及更低的性能.

其中最主要的问题是内存中的数据共享,它们会被多线程以无法预知的方式进行操作,导致一些无法重现或者随机的结果(称作“竞态”).所以这个经典的方法明显不再适合现代多核/多处理器编程:thread-per-connection 模型不够有效.在诸多比较合适的范式中,有个被称作 Communicating Sequential Processes(顺序通信处理)(CSP,C. Hoare 发明的)还有一个叫做 message-passing-model(消息传递)(已经运用在了其他语言中,比如 Erlang).

我们这里使用办法是利用并行的架构来处理任务,一个并发程序可以在一个处理器或者内核上使用多个线程来执行任务,但是只有同一个程序在某个时间点同时运行在多核或者多处理器上才是真正的并行.

并行是一种通过使用多处理器以提高速度的能力.所以并发程序可以是并行的,也可以不是.

并行模式可以同时使用多线程、多核、多处理器,甚至多计算机,这无疑可以调动更多资源,从而压缩响应时间,提升运算效率,极大地增强了服务端的性能.

(3)例子

这里用Go语言中的Goroutine来具体说明.

(编辑:核心网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读