文档章节

程序员修神之路--提高网站的吞吐量

o
 osc_gu9d45li
发布于 2019/04/07 17:59
字数 2599
阅读 7
收藏 0

钉钉、微博极速扩容黑科技,点击观看阿里云弹性计算年度发布会!>>>

菜菜哥,有个事你还得帮我呀

呦西,YY妹子,最近天这么热了,你怎么还穿这么多?

苦笑一下.....前几天写了几个接口,领导让提高一下接口吞吐量

这是你技术提高的大好机会呀

可吞吐量是什么呀?怎么提高呢?

来,凑近一点,哥给你解释一番

吞吐量定义

百科

吞吐量是指对网络、设备、端口、虚电路或其他设施,单位时间内成功地传送数据的数量(以比特、字节、分组等测量)。


        以上的定义比较宽泛,定义到网站或者接口的吞吐量是这样的:吞吐量是指系统在单位时间内处理请求的数量。这里有一个注意点就是单位时间内,对于网站的吞吐量这个单位时间一般定义为1秒,也就是说网站在一秒之内能处理多少http(https/tcp)请求。与吞吐量对应的衡量网站性能的还有响应时间、并发数、QPS每秒查询率。


响应时间是一个系统最重要的指标之一,它的数值大小直接反应了系统的快慢。响应时间是指执行一个请求从开始到最后收到响应数据所花费的总体时间。


并发数是指系统同时能处理的请求数量,这个也是反应了系统的负载能力。

每秒查询率(QPS)是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准,在因特网上,作为域名系统服务器的机器的性能经常用每秒查询率来衡量。对应fetches/sec,即每秒的响应请求数,也即是最大吞吐能力。

        我们以高速收费站为例子也许更直观一些,吞吐量就是一天之内通过的车辆数,响应时间就是车速,并发数就是高速上同时奔跑的汽车数。由此可见其实以上几个指标是有内在联系的。比如:响应时间缩短,在一定程度上可以提高吞吐量。

其实以上几个指标主要反映了两个概念:

1. 系统在单位时间之内能做多少事情

2. 系统做一件事情需要的时间


提高吞吐量以下场景都是在假设程序不发生异常的情况下 服务器(进程)级别

        服务器级别增加网站吞吐量也是诸多措施中最容易并且是效果最好的,如果一个网站能通过增加少量的服务器来提高吞吐量,菜菜觉得是应该优先采用的。毕竟一台服务器的费用相比较一个程序员费用来说要低的多。但是有一个前提,就是你的服务器是系统的瓶颈,网站系统之后的其他系统并非瓶颈。如果你的系统的瓶颈在DB或者其他服务,盲目的增加服务器并不能解决你的问题。

        通过增加服务器来解决你的网站瓶颈,意味着你的网站需要做负载均衡,如果没有运维相关人员,你可能还得需要研究负载均衡的方案,比如LVS,Nginx,F5等。我曾经面试过很多入道不久的同学,就提高吞吐量问题,如果没有回答上用负载均衡方案的基本都pass了,不要说别的,这个方案就是一个基础,就好比学习一个语言,你连最基本的语法都不会,我凭什么让你通过。有喷的同学可以留言哦


其实现在很多静态文件采用CDN,本质上也可以认为是增加服务器的策略


线程级别

        当一个请求到达服务器并且正确的被服务器接收之后,最终执行这个请求的载体是一个线程。当一个线程被cpu载入执行其指令的时候,在同步的状态下,当前线程会阻塞在那里等待cpu结果,如果cpu执行的是比较慢的IO操作,线程会一直被阻塞闲置很长时间,这里的很长是对比cpu的速度而言,如果你想有一个直观的速度对比,可以去查看菜菜以前的文章:

高并发下为什么更喜欢进程内缓存

        当一个新的请求到来的时候,如果没有新的线程去领取这个任务并执行,要么会发生异常,要么创建新的线程。线程是一种很稀缺的资源,不可能无限制的创建。这种情况下我们就要把线程这种资源充分利用起来,不要让线程停下来。这也是程序推荐采用异步的原因,试想,一个线程不停的在工作,遇到比较慢的IO不会去等待结果,而是接着处理下一个请求,当IO的结果返回来得到通知的时候,线程再去取IO结果,岂不是能在相同时间内处理更多的请求。


程序异步化(非阻塞)会明显提高系统的吞吐量,但是响应时间可能会稍微变大


        还有一点,尽量减少线程上下文在cpu的切换,因为线程上线文切换的成本也是比较大的,在线程切换的时候,cpu需要把当前线程的上下文信息记录下来用以下次调用的时候使用,然后把新线程的上下文信息载入然后执行。这个过程相对于cpu的执行速度而言,要慢很多。

        不要拿Golang反驳以上观点,golang的协程虽然是用户级别比线程更小的载体,但是最终和Cpu进行交互的还是线程。


  Cpu级别

        在讲cpu级别之前,如果有一定的网络模型的基础,也许会好一些。这里大体阐述一下,现代操作系统都采用虚拟寻址的方式,它的寻址空间(虚拟存储空间)为4G(2的32次方)。操作系统将虚拟空间分为两类:内核空间和用户空间。内核空间独立于用户空间,有访问受保护的内存空间、IO设备的权限(所有的用户空间共享)。用户空间就是我们的应用程序运行的空间,其实用户空间并没有操作各种IO设备的权限,像我们平时读取一个文件,本质上是委托内核空间去执行读取指令的,内核空间读取到数据之后再把数据复制到程序运行的空间,最后应用程序再把数据返回调用方。


        通过上图大体可以看出,内核会为每个I/O设备维护一个buffer(同一个文件描述符读和写的buffer不同),应用程序发出一个IO操作的指令其实通过了内核空间和用户空间两个部分,并且发生了数据的复制操作。这个过程其实主要包含两个步骤:

1. 用户进程发出操作指令并等待数据

2. 内核把数据返回给用户进程(buffer的复制操作)

        根据这两个操作的不同表现,所以IO模型有了同步阻塞,同步非阻塞,异步阻塞,异步非阻塞的概念,但是这里并非此文的重点,所以不在展开详细介绍。

        利用cpu提高系统吞吐量主要目标是提高单位时间内cpu运行的指令数,避免cpu做一些无用功:

cpu负责把buffer的数据copy到应用程序空间,应用程序再把数据返回给调用方,假如这个过程发生的是一次Socket操作,应用程序在得到IO返回数据之后,还需要网卡把数据返回给client端,这个过程又需要把刚刚得到的buffer数据再次通过内核发送至网卡,通过网络传送出去。由此可见cpu把buffer数据copy到应用程序空间这个过程完全没有必要,在内核空间完全可以把buffer数据直接传输至网卡,这也是零拷贝技术要解决的问题。具体的零拷贝技术在这里不再展开。


不要让任何设备停下来,不要让任何设备做无用功


通过增加cpu的个数来增加吞吐量 网络传输级别

        至于网络传输级别,由于协议大部分是Tcp/ip,所以在协议传输方面优化的手段比较少,但是应用程序级别协议可以选择压缩率更好的,比如采用grpc会比单纯的http协议要好很多,http2 要比http 1.1要好很多。另外一方面网卡尽量加大传输速率,比如千兆网卡要比百兆网卡速度更快。由于网络传输比较偏底层,所以人工干预的切入点会少很多。


最后总结

        大部分程序员都是工作在应用层,针对应用级别代码能提高吞吐量的建议:

1

加大应用的进程数,增加并发数,特别在进程数是瓶颈的情况下

2

优化线程调用,尽量池化。

3

应用的代码异步化,特别是异步非阻塞式编程对于提高吞吐量效果特别明显

4

充分利用多核cpu优势,实现并行编程。

5

减少每个调用的响应时间,缩短调用链。例如通过加索引的方式来减少访问一次数据库的时间


写在最后

希望大家有所收获 --菜菜


恭喜 安浅   QI 两位喜提上周抽奖Golang书籍。

互联网之路,菜菜与君一同成长

长按识别二维码关注


你点的每个推荐,我都认真当成了喜欢
o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。
程序员修神之路--高并发下如何缩短响应时间

菜菜哥,请你看电影呀,但是得帮我一个忙 好呀,看什么? 哥斯拉2:怪兽之王 看过了~ X战警:黑凤凰 看过了 追龙2和黑衣人呢? 都看过了,你说帮什么忙吧 我一个网站响应特别慢,你帮我优化一...

osc_tr9tcucx
2019/06/19
2
0
程序员修神之路--高并发下如何缩短响应时间

本文分享自微信公众号 - 后端技术学堂(lemon10240)。 如有侵权,请联系 support@oschina.cn 删除。 本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。...

柠檬橙1024
04/23
0
0
程序员过关斩将--小小的分页引发的加班血案

菜菜哥,我又来了 晚上请我喝咖啡吗? 那你得先帮我解决一个问题 说来听听 昨天加班很晚排查一个分页引起的问题,到现在还没解决,心情有点抑郁,需要安慰 说来听听 我们新做的商城首页是一个...

osc_es532h90
04/16
2
0
程序员过关斩将--为什么不推荐业务中使用存储过程?

菜菜哥,我新接手了一个项目,看的我头疼呀 业务有这么复杂呀? 不是的,这个老项目完全是用存储过程写的,每个存储过程都好几百行 这样呀,是够头疼的~ 有没有办法帮我了解业务一下? 碰到这...

osc_nd4uekgu
2019/06/13
2
0
程序员修神之路--做好分库分表其实很难之二(继续送书)

菜菜哥,上次听你给我讲了分库的情况后,我明白了很多,能再给我讲讲分表吗 有收获就好,分表其实有很多情况和分库类似 还有不一样的情况吗? 有呀,本来数据库和表是不同层面的东西,肯定有...

osc_cw9m1qtk
04/16
6
0

没有更多内容

加载失败,请刷新页面

加载更多

未捕获ReferenceError:未定义$? - Uncaught ReferenceError: $ is not defined?

问题: How come this code throws an 此代码如何引发 Uncaught ReferenceError: $ is not defined 未捕获的ReferenceError:未定义$ when it was OK before? 以前什么时候可以? $(document......

javail
15分钟前
12
0
263. Ugly Number

题目: 263. Ugly Number 题目地址:https://leetcode.com/problems/ugly-number/ Write a program to check whether a given number is an ugly number. Ugly numbers are positive numbers......

JiaMing
37分钟前
46
0
HCIA_ARP01

ARP(地址解析协议) eNSP 常用路由器:AR2220 常用交换机:S5700、S3700 常用终端:PC、MCS(主播服务器) 设备连线:Copper(以太网用到的双绞线)、Serial(串口线,2SA接口)、Auto(自动连...

创业789
40分钟前
13
0
如何在Rails 4中使用问题 - How to use concerns in Rails 4

问题: The default Rails 4 project generator now creates the directory "concerns" under controllers and models. 默认的Rails 4项目生成器现在在控制器和模型下创建目录“Concer”。 ......

fyin1314
45分钟前
19
0
【LeetCode】 57 括号生成

题目: 解题思路: https://leetcode-cn.com/problems/generate-parentheses/solution/hui-su-suan-fa-by-liweiwei1419/ 代码: import java.util.ArrayList;import java.util.List;publ......

JaneRoad
昨天
8
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部