带你读《HikariCP数据库连接池实战》之一:阿里中间件实战,第一个案例-阿里云开发者社区

开发者社区> 华章出版社> 正文

带你读《HikariCP数据库连接池实战》之一:阿里中间件实战,第一个案例

简介: 本书不仅对市面上常见的连接池组件进行了全方位比较和分析,还以实战的角度深入介绍了高性能HikariCP连接池的使用、原理与维护。

HikariCP数据库连接池实战
点击查看第二章
点击查看第三章
image.png
朱政科 著
第1章

阿里中间件实战,第一个案例

在应用系统开发过程中,池化技术,如对象池、连接池、线程池等,通过复用对象以减少创建、释放连接的消耗来提升性能。由于TCP连接的创建开支十分昂贵,数据库所能承载的TCP并发连接数也有限制,针对这种场景,数据库连接池应运而生。数据库连接池的实现有很多,如c3p0、DBCP、Druid等,也包括本书将详细介绍的、号称性能最好的数据库连接池——HikariCP。
本章首先从一个有趣的实例说起。在此过程中,我将告诉你很多和连接相关的知识,并且让你对系统的调优过程产生一点共鸣,然后我才能按通常的方式向你展开原理介绍。这个例子是我在阿里巴巴多年间对一款中间件调优的真实经历,这款中间件经历过很多打磨,比如全链路压测、3年双十一大促、多种监控系统接入、数次整体结构重构改造、重大问题修复等。这款中间件是纯TCP的,再回首,我并不为当年所做的那些TCP性能优化感到自豪,相反,我认为一款池化的中间件如果能提炼出来,会更有价值,因为它更加有利于技术产品的快速落地及运维,进而更好地提升研发效能。
希望读者通过这个实例可以了解到在没有池化技术的情况下TCP调优是如何进行的,同时也能理解TCP调优的复杂性,体会到池化技术出现的必然性。数据库连接池同样是池化技术,大家也可以深入思考并想象一下数据库连接池中间件需要解决哪些问题。

1.1 物联网MQTT单机压测130万参数调优

2019年1月,我的工作之一就是为公司搭建一套独立于阿里云之外的自己的物联网MQTT集群。MQTT非常适合物联网场景,它可以保持设备与服务器的长连接,避免反复轮询,并支持推送。和数据库连接池一样,它同样运行于TCP协议之上,MQTT相比于HTTP具有协议开销低、容忍弱网络、低功耗、百万并发等优点。但是由于当前的阿里云MQTT不支持will、retain msg、QOS2,并且存在限流、断连等不稳定因素,自建MQTT集群就显得格外重要。
在调研了Eclipse Mosquitto后,我又在EMQ(Erlang/Enterprise/Elastic MQTT Broker)的官网上发现了下列描述:“EMQ消息服务器1.x版本MQTT连接压力测试到130万,在1台8核心、32G内存的CentOS服务器上。”经过梳理后我认为,它的服务端调优主要分为Linux操作系统参数调优和TCP协议栈网络参数调优两部分。
Linux操作系统参数调优如下:
1)系统全局允许分配的最大文件句柄数。
sysctl -w fs.file-max=2097152
sysctl -w fs.nr_open=2097152
echo 2097152 > /proc/sys/fs/nr_open
2)允许当前会话或进程打开文件句柄数。
ulimit -n 1048576
TCP协议栈网络参数调优如下:
1)并发连接backlog设置。
sysctl -w net.core.somaxconn=32768
sysctl -w net.ipv4.tcp_max_syn_backlog=16384
sysctl -w net.core.netdev_max_backlog=16384
2)TCP Socket 读写Buffer设置。
sysctl -w net.core.rmem_default=262144
sysctl -w net.core.wmem_default=262144
sysctl -w net.core.rmem_max=16777216
sysctl -w net.core.wmem_max=16777216
sysctl -w net.core.optmem_max=16777216
sysctl -w net.ipv4.tcp_mem='16777216 16777216 16777216'
sysctl -w net.ipv4.tcp_rmem='1024 4096 16777216'
sysctl -w net.ipv4.tcp_wmem='1024 4096 16777216'
3)TCP连接追踪设置。
sysctl -w net.nf_conntrack_max=1000000
sysctl -w net.netfilter.nf_conntrack_max=1000000
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_time_wait=30
4)TIME-WAITSocket最大数量、回收与重用设置。
net.ipv4.tcp_max_tw_buckets=1048576
注意: 不建议开启该设置,NAT模式下可能引起RST连接
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1
5)FIN-WAIT-2 Socket超时设置。
net.ipv4.tcp_fin_timeout = 15
TCP/IP参考模型可以分为应用层、传输层、网络层和链路层。TCP和UDP在传输层,应用层除了刚才我们介绍的MQTT,还有HTTP、FTP等。因为MQTT运行于TCP协议之上,所以它的调优也离不开TCP的参数调优,数据库连接池的出现也是为了解决应用与数据库之间TCP的性能问题。当前很多应用,比如服务端和算法服务的交互也离不开TCP的传输。所以了解TCP的调优方式可以夯实这个技术领域调优的基础,一通百通。

1.2 阿里中间件TCP四次挥手性能调优实战

重用数据库连接最主要的原因是可以减少应用程序与数据库之间创建或销毁TCP连接的开销,数据库连接池的概念应运而生。如果不使用连接池,TCP四次挥手过程中TIME_WAIT的性能调优是相对比较复杂的,实例如下所示。

1.2.1 亿级消息网关Rowan架构

Rowan是一个亿级企业消息网关中间件服务,如图1-1所示。它在业务上为B2B、Aliexpress、集团安全、共享事业部、淘宝等大部门提供邮件、短信、旺旺、站内信、钉钉等消息的持续发送能力,支持的业务包括会员注册、评价、仲裁、用户触达EDM、资金中心对账、交易、营销、物流追踪、卖家认证、CRM、风控合规、反欺诈、风险评测、处罚等。
技术上,Rowan由多个服务和中间件构成,具有模板管理、用户触达、消息管理、EDM无线引流、打点追踪等功能,每天产生的消息条数过千万,仅2016年“双十一大促”当天产生的消息,仅邮件类就超过6亿件。
以邮件模块为例,Rowan技术架构有过两个时期。第一个时期,业务方请求通过HSF(一种阿里内部类似Dubbo的RPC)请求调用Rowan,Rowan再透传调用阿里云邮SMTP服务。当业务洪峰抵达的时候,海外集群会经常出现超时的情况。这是因为,当时阿里云国内集群的系统设计能力比较强,基本上可以支撑国内的邮件发送;相对于国内有5个数据库集群,国外阿里云集群则稍显薄弱,仅有一个数据库集群。国内集群的系统设计能力是1亿次请求/天,日常2000多万次请求/天;海外日常1000多万次请求/天,峰值1500多万次请求/天。阿里云使用写磁盘的方式,若投递信息失败,重试5次,大致时间点是2分钟、5分钟、30分钟、1小时和2小时,若2小时后仍发送失败则丢弃信息。但是,只要是被阿里云SMTP拦截的,如返回给Rowan的connection reset、451、526等异常,不进入阿里云队列,这就会造成只有Rowan能打印出异常信息,而阿里云服务端则打印不出具体的异常信息,排查问题变得相当棘手。
image.png
由于国内外知名的邮件服务器,如亚马逊AWS、搜狐SENDCLOUD等都是支持抗堆积的,在无法推动阿里云从SMTP支持到HTTP的背景下,我进行了第二个时期的技术改造设计,如图1-2所示。
在这个架构中,所有的外部服务通过Rowan Service调用对应的服务,如“邮件”等。首先会根据Cache缓存中的模板信息组装成消息体,并存储在HBASE中进行发送状态的记载;其次请求的消息会直接丢到对应的中美MQ(阿里内部叫Metaq,对外开源叫RocketMQ)消息队列集群中,在线流式实时计算Jstorm会分别处理MQ中的邮件、短信、站内信、HTTP、旺旺、钉钉等消息,来进行消息的投递。
由于杭州的阿里云邮系统能力远远高于美国集群,所以美国集群若命中了国内邮箱,比如126、163、QQ等,会直接路由到国内阿里云网关进行发送。在图1-2中,Rowan服务是MQ的生产者,Jstorm是MQ的消费者,故流控和暂停功能放在了消费者这里。流控功能是基于阿里配置中心Diamond定制化开发的,Jstorm启动时直接从配置项读取MQ最大线程数和最小线程数。在Diamond中还可以配置海外集群的压力疏导功能,支持按照百分比将流量转移到国内。利用Diamond配置中心实时更新的特性,当Diamond修改时可以实时推送给对应机房以指定的流控线程数重启MQ消费者客户端。
image.png
阿里云可以配置发件账号的优先级,并暂停低优先级的账号。Rowan这套新架构在此基础上额外支持两个类似的扩展功能:自带无效地址,可以关掉对指定收件人的发送;模板禁用也可以直接关掉此类模板的发送。
这套架构采用疏导的策略,旨在将海外集群的压力转移到国内分担,从而大幅度提高系统的整体QPS。这套架构需要业务进行配合,通过采取统计国内外邮件账号的QPS指标、进行国内外发件账号的优先级排序、准备发送故障预案、精简合并系统通知邮件、均匀化编排大促营销邮件发送等一系列措施,来保障整体系统“双十一大促”的稳定性。这也是我在阿里巴巴公司工作期间学到的——技术驱动业务,团队合作,“贴着业务走,以结果为导向”是中间件团队的职责。

1.2.2 人脸识别服务:异曲同工的架构

提到疏导的架构和QPS的提升,让我想起了2019年我设计的大幅度提升QPS的技术方案。
如图1-3所示,FaceServer是基于Java的人脸识别服务,通过调用Python的算法服务,为业务服务提供人脸识别的Dubbo API接口。算法服务包括多个原子服务,如人脸、质量、属性、活体、特征等。据统计,FaceServer服务调用算法人脸识别服务,平均每天有40~50次超时异常,最多的时候有100次。技术团队因此对算法服务器单机进行了压测,单机10个线程,平均响应时间在2.878秒左右(FaceServer认为3秒即超时),最长响应时间为13.814秒,QPS为1。
image.png
FaceServer在物联网时代,就类似于淘宝网等网站的会员登录,是互联网的门面,QPS为1显然不能满足商业化需求。很多做研发的资深人士可能会想,是否可以采用堆机器的方式来提高QPS呢?这是不可行的,因为算法服务器非常特别,不同于普通的服务器,它是昂贵的GPU密集型服务器:一台阿里云GPU服务器单机每月要6000元,一年7.2万元,按照图1-3采购两台,一年总计14.4万元。也就是说,目前单机只有1QPS,两台机器2QPS,要支持200QPS,如果堆机器,一年就需要花1400多万元。为了使QPS达到200,一年需要多支出1400多万元的开销,这绝对不是中小型创业公司能够承担的,在降成本的大型BAT,想必也是不能接受的。
目前的算法服务器是单点,另一台算法GPU服务器由于历史原因一直没有启用,所以第1步改造我决定先高效利用好两台已有的算法GPU服务器。在进行了将单机部署提升为集群部署、算法服务内部的串行改并行、耗时原子服务多开进程等工作后,FaceServer的维护者表示再也没有出现过线上的超时异常的情况,此时的架构如图1-4所示。经团队压测后,单机的QPS也从1提升到了7,由于线上正在使用人脸识别服务,整体集群QPS没有进行压测,估计应该是1+1>2的效果(集群14QPS)。
image.png
基于百度人脸识别算法,为企业认证的用户免费提供每月15QPS的服务,据此推测,百度应该也有一些性能优化的技巧来高效利用GPU服务器,因此目前这样的架构还可以继续提高QPS。于是,我又和算法团队进行了进一步的沟通,有收获的是,据算法团队反馈,算法服务器内部单独处理一张人脸图片和批量处理其实是一样的。算法团队表示,在单模型情况下,当前人脸特征模型单机进程如果使用批处理至少可以将QPS提高到35,而这恰恰就是可以大幅提升QPS的切入点。根据算法团队批处理的需求,我想到了一个请求合并的架构。
如图1-5所示就是第2版优化架构。这是一种请求合并的处理架构,也是中间件性能提升中较为常见的方案。对于业务服务来说,依然是通过Dubbo同步调用FaceServer服务,而FaceServer则是将每次请求丢到一个队列中去,当这个队列请求收集到一定数量(比如算法服务的35QPS)时则进行提交或者每秒进行提交,这种同步转异步的方式可以充分利用算法GPU服务器的资源,从而大幅提升QPS。在图1-5的架构中,我采用了Guava而不是Redis,原因是Redis进行人脸图片的读写会有网络开销,采用Guava会在更大程度上提升响应时间。另外,关于图1-5重试的部分我也使用了GuavaRetry,充分利用了Guava的缓存和重试工具特性。
这种Dubbo同步转异步、请求合并的方案,其实和Rowan的抗堆积、流控与暂停有着异曲同工之妙,都是在有限资源(人力、物力)的基础上充分合理利用已有资源,从而达到更为极致的QPS。
image.png

1.2.3 “双十一大促”全链路压测发现TCP问题

聊完架构,我们继续回到Rowan和TCP的话题。
Rowan邮件功能使用的是SMTP协议,SMTP在七层协议中属于应用层协议,属TCP/IP协议簇,它帮助每台计算机在发送或中转信件时找到下一个目的地。Rowan对接阿里云云邮网关,阿里云云邮再对接Hotmail、Gmail、Yahoo等邮件服务商。在我日常运维的过程中,会偶发性地出现“Could not connect to SMTP host”的异常提示,尤其是在业务方进行EDM(Email Direct Marketing)邮件大规模营销时会频繁发生。
备战“双十一”过程中,我对Rowan进行了全链路技术改造和压测,在进行线上压测邮件服务过程中发现美国集群(US代表美国,HZ代表杭州)在达到1万QPS压力时,Rowan服务端大量产生60多万次的SMTP连接不上阿里云网关的异常,如图1-6所示。
image.png
阿里的中间件存在百花齐放、百家争鸣的情况,也可以说是野蛮生长、重复造轮子、适者生存。当时还有一款同样的功能的中间件叫作EVE,这是一款从阿里巴巴B2B时代就存在的历史悠久的中间件,而Rowan则是一款年轻的中间件。和EVE不同的是,Rowan并不是通过堆机器和增加系统复杂度来换取高吞吐量的,其只使用了中美(各4台)共计8台Server服务器,Rowan引入Apache的Jstorm技术,SMTP的邮件发送逻辑放在了Jstorm中,引入Jstorm就是想用最少的机器做极致的事。在Jstorm的日志中,我们又拿到了更加详细的异常信息。
Caused by: javax.mail.MessagingException: Could not connect to SMTP host: smtp-usa.ocm.aliyun.com, port: 25; nested exception is: java.net.NoRouteToHostException: Cannot assign requested address at com.sun.mail.smtp.AliyunSMTPTransport.openServer(AliyunSMTPTransport.java:1764) at com.sun.mail.smtp.AliyunSMTPTransport.protocolConnect(AliyunSMTPTransport.java:587) Caused by: java.net.NoRouteToHostException: Cannot assign requested address at java.net.PlainSocketImpl.socketConnect(Native Method) at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
然而登录阿里云的服务器查看系统指标,以及检查阿里云云邮系统的神农监控、盘古等指标都没有问题。查看Jstorm服务器套接字socket使用概况,可以根据上述异常SMTP 25端口使用netstat -tn |grep :25 |wc -l 命令,或者使用ss –s(Socket Statistics缩写)命令。如图1-7和图1-8所示是连续两次截图记录,可以看出timewait非常多。
image.png
image.png
种种迹象表明,问题发生在Client端而不是Server端,这是一起典型的TCP调优案例。

1.2.4 Linux内核网络参数调优

首先我们调整一下Linux内核参数来提高服务器并发处理能力。一般来说,这种方式可以不用升级服务器硬件就能最大程度提高服务器性能,是一种节省成本的做法。内核参数修改了以下4个配置:

  • ulimit –n。该文件表示系统里打开文件描述符的最大值,查看之后发现是1024,这个值偏小,我们将其调大一些。
  • somaxconnSocket。cat /proc/sys/net/core/somaxconn,该文件表示等待队列的长度,默认是128,我们将其调到1000。
  • netdev_max_backlog。cat /proc/sys/net/core/netdev_max_backlog,该文件表示在每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目,我们将其调到1000。
  • tcp_max_syn_backlog。cat /proc/sys/net/ipv4/tcp_max_syn_backlog,该文件表示SYN队列的长度,默认为1024,加大队列长度为8192,以容纳更多等待中的网络连接。

修改完毕,重新进行线上压测,然而发现问题没有解决,QPS也没有得到提升。
小窍门
本节主要是对/proc/sys/net/进行优化,该目录下的配置文件主要用来控制内核和网络层之间的交互行为,一些技巧补充如下所示。
1)/proc/sys/net/core/message_burst文件表示写新的警告消息所需的时间(以0.1秒为单位),在这个时间内系统接收到的其他警告消息都会被丢弃。这用于防止某些企图用消息“淹没”系统的人所使用的拒绝服务(Denial of Service)攻击。缺省:50(5秒)。
2)/proc/sys/net/core/message_cost文件表示写每个警告消息相关的成本值。该值越大,越有可能忽略警告消息。缺省:5。
3)/proc/sys/net/core/netdev_max_backlog文件表示当每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目。缺省:300。
4)/proc/sys/net/core/optmem_max文件表示每个套接字所允许的最大缓冲区的大小。缺省:10240。
5)/proc/sys/net/core/rmem_default文件指定了接收套接字缓冲区大小的缺省值(以字节为单位)。缺省:110592。
6)/proc/sys/net/core/rmem_max文件指定了接收套接字缓冲区大小的最大值(以字节为单位)。缺省:131071。
7)/proc/sys/net/core/wmem_default文件指定了发送套接字缓冲区大小的缺省值(以字节为单位)。缺省:110592。
8)/proc/sys/net/core/wmem_max文件指定了发送套接字缓冲区大小的最大值(以字节为单位)。缺省:131071。

1.2.5 Linux TCP参数调优

TIME_WAIT是TCP中一个很重要的状态,在大并发的短连接下,会产生很多TIME_WAIT,这会消耗很多的系统资源;端口的数量只有65535,占用一个就会少一个,进而严重影响新连接。所以需要调优TCP参数,从而让系统更快地释放TIME_WAIT的连接。TCP的传输连接有连接建立、数据传送和连接释放3个阶段,多年前与阿里巴巴的叶军博士在一次闲聊中得知,作为阿里巴巴面试官的他经常会考察应聘者TCP的3次握手和4次挥手这个知识点。
对于TIME_WAIT,我们主要进行如下修改:
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1
这两个参数默认是关闭的,而且不建议开启,因为在NAT模式下可能引起连接RST。这两个参数的作用是主动断开连接,这由于违反了TCP协议(RFC 1122),在其官方文档中也强调:“It should not be changed without advice/request of technical”(在没有专业的建议或请求的情况下不要修改设置)。
TCP主要内核参数的说明如下所示:

  • net.ipv4.tcp_syncookies = 1表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击。默认为0,表示关闭。
  • net.ipv4.tcp_tw_reuse = 1表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接。默认为0,表示关闭。
  • net.ipv4.tcp_tw_recycle = 1表示开启TCP连接中TIME-WAIT sockets的快速回收。默认为0,表示关闭。
  • net.ipv4.tcp_fin_timeout修改系统默认的TIMEOUT时间。

我们可以再继续进行并发连接 backlog调优,并对可用端口调优范围、TCP Socket 读写 Buffer、TIME-WAIT Socket 最大数量、FIN-WAIT-2 Socket 超时设置等进行优化。特别说明一下,tcp_max_tw_buckets用于控制并发时,TIME_WAIT的数量默认值是180 000,如果超过该值,系统会清除多余部分,并警告“time wait bucket table overflow”。这些参数的调优不但能够提升服务器的负载,还可以在一定程度上防御DDoS等攻击。
在参数调优之后,又上了一道双保险,重新修改了com.sun.mail.smtp源码的SO_REUSEADDR,通过serverSocket.setReuseAddress(true)让其在服务器绑定端口前生效,目的是让端口释放后立即就可以被再次使用。
但是发布到线上进行压测以后,却依然没有效果。

1.2.6 一行代码大幅提升QPS

经过了反复的调优以后,真正解决问题的其实只有一行代码“TCP option SO_LINGER”。在1.2.5节中的socket.setReuseAddress(true)代码后增加一行代码“socket.setSoLinger(true,0)”,重新进行线上压测,压测过程中启用setSoLinger,启用前后的数据结果如图1-9~图1-11所示。
image.png
image.png
image.png
从图1-9可以发现,启用l_linger前连接很难超过700,timewait状态的很多;启用socket.setSoLinger(true,0)后连接数到1045,timewait状态没有了(见图1-11)。正是因为放弃了TCP中的4次挥手,所以客户端(Rowan整体系统)会给服务端(阿里云邮集群)发出很多TCP中的RST。叶军博士曾告诉我说,关闭4次挥手这个案例他以前调优时也做过类似处理,有需要的场景可以将4次挥手改成3次挥手,不过要经过专业的大规模测试,一旦TCP层面的Buffer数据丢掉,还是会存在一些隐患的。SO_LINGER虽然可以让服务器性能提升很多,但是在《UNIX网络编程》卷1中提到过,TIME_WAIT的作用是在主动关闭端口后,保证数据让对端收到,Richard.Steven的原话是:“TIME_WAIT是我们的朋友。”如果服务存在大量或者多个通信,而且之间还有一些时序关系,那么我们就不能使用这种让用户丢弃一部分数据的方式,否则可能因为最后阶段丢失一些服务器的返回命令而造成程序的错误。
那SO_LINGER是什么呢?它是一个可以通过API设置的socket选项,仅适用于TCP和SCTP。它主要由on和linger两个属性决定,其数据结构如下所示:
struct linger {

int l_onoff; /* 0 = off, nozero = on */开关,零或者非零
int l_linger; /* linger time */优雅关闭最长时间

};
如表1-1所示,socket.setSoLinger(true,0)对应的是立即返回,即“强制关闭失效”的情况。
image.png
如图1-12所示,这种情况并不是4次挥手,TCP不会进入TIME_WAIT状态。在send buffer中的数据都发送完之前,close就返回,client向SERVER发送一个RST信息。
image.png
为了避免由于使用socket.setSoLinger(true,0)可能导致的应用数据包丢失问题,在如
图1-13所示的javamail官方文档中,SMTP启用了quitwait参数,可以保证应用层消息被完整地发完并收到服务端的发送响应。
image.png
所以,关闭Socket连接部分的代码调整为,如果quiteWait为true,则需要接收响应。修改完后,当天13:00以后进行了多次压测,在Rowan服务端中“Could not connect to SMTP host”这个异常再也没有出现,如图1-14所示。
image.png
同一时间,阿里云神农监控显示收到邮件的QPS比之前的压测要略大,曲线上升波动更快,完全符合预期,如图1-15所示。
image.png
至此,整体TCP调优结束。
思考SMTP也支持一个连接多封邮件,发完rset命令后,再重新认证发送就可以了,TCP方面并不是与阿里云服务器建立的连接,而是与阿里云的LVS建立的TCP连接。
阿里云使用的还是SMTP的协议,其实我们可以看一下业界的邮件服务,如AWS、SENDCLOUD等,不仅仅支持SMTP,也同样支持HTTP等。其实真正解决问题的方法是将连接方式改进为长连接,或者实现client的连接复用(连接池的理念)。所以推动阿里云从SMTP改为HTTP也是一个方向。

1.3 技术驱动业务,结果为导向

上述内容都是高并发时对于TCP的调优,但是抗堆积也是消息网关的一个很核心的特性,如亚马逊AMAZON SES和SENDCLOUD等都是抗堆积的。
邮件的拥堵会造成一连串的问题,如:多个阿里事业部之间邮件紧耦合,每到大促线上互相影响,业务发展严重受限,询盘导致系统雪崩,实时性高的会员注册邮件被整体通道堵死,投递量越大投递成功率越低,投递量用户反馈邮件延迟越多等问题。我清晰地记得,当年的故障报告有记载,因为邮件拥堵导致的P0级故障直接造成了资金损失。
对于流量洪峰,我们可以吸取古人的智慧。早在4000多年前,我国的黄河流域洪水为患,鲧采取“水来土挡”的策略治水,最终失败。大禹确立了一条与他父亲鲧的“堵”相反的方针,叫作“疏”,即“治水须顺水性,水性就下,导之入海。高处就凿通,低处就疏导”的治水思想。
当遇到国际化业务场景如“双十一”时,在美国的服务器系统设计能力远不如杭州服务器的情况下,我们可以采用多种手段进行“疏导”。
“疏”:可以采用拆分事业部、营销和通知账号的手段让每个发件账号独立走流程,消息设置优先级(最高优先级不落盘,直接向网关通过绿色通道发送,避免延迟,如提高注册邮件的实时性),支持整体和局部的流控暂停及停发消息等手段。
“导”:为了防止对于阿里云盘古的冲击,Rowan自身做好抗堆积建设;支持灰度引流,解决阿里云美国系统设计能力弱而杭州系统设计能力强的问题;大促邮件发送参与业务方评估,合理调度纷发;做好充分的预案等。由于中美有13个小时的时差,“双十一大促”也可以制定合理的规划,通过“打时间差”的形式处理好中美“双十一大促”的消息投递问题。
邮件领域还有一个经典的黑名单的问题,全球最大的反垃圾邮件组织spamhaus会将发往mail.ru,microsoft(Hotmail、Outlook、Live)等地址的邮件设为接收方拒收。如果营销邮件无法保证接收地址的有效性等,便会很容易被spamhaus封禁,spamhaus也往往不同意解封,一般只能通过邮件和spamhaus沟通。大促预热期对于EDM(Email Direct Marketing)营销GMV(Gross Merchandise Volume,网站成交总额)影响很大,尤其是外国人有着看电子邮件的习惯。正是因为邮件黑名单的问题,我在2016年曾经汇总过一部分数据,发现营销邮件的到达率从95%降到了70%左右,EDM相关GMV 就跟着下降了30%以上。
针对黑名单问题,优先寻求商务解封。除了商务解封之外,产品设计上需要建设邮件的黑白名单体系,对存量和增量用户进行确认,发送邮件列表的黑白名单,先从Hotmail等会被屏蔽的用户开始,在发送邮件的列表中进行过滤;如果是在邮件列表中的注册新会员用户,则进行邮箱验证,只验证是否可以发邮件,不影响下单等流程。另外,阿里云需要实现更换机房IP的策略,通过IP更换跳过spamhaus的监测,比如大促前保留备用营销网段随时准备动态切换。质量较低的任务也可以先暂停,当然这些任务暂停并不会影响我们向优质客户(如下过单的用户)发送的EDM邮件,所以对业务上的影响是可控的。具体的业务指标可以在这些低质量任务暂停后观察一下网站的流量指标,会发现基本不会有什么明显的影响。
在完成了上述工作以后,2016年“双十一大促”不光技术上提升到万级QPS,在业务上也取得了可喜的结果:1.6亿存量用户验证在大促前落地;“双十一”当天2亿营销邮件投递到用户邮箱;大促前3亿营销邮件投放成功;大促期间和2016年上半年比较,在整体的发送量提升的同时,打开率和行动率有10%~15%的提升。

1.4 本章小结

春秋战国时期,有位神医被尊为“医祖”,他就是扁鹊。一次,魏文王问扁鹊:“你们家兄弟三人,都精于医术,到底哪一位最好呢?”扁鹊答:“长兄最好,中兄次之,我最差。”文王又问:“那么为什么你最出名呢?”扁鹊答:“长兄治病,是治病于病情发作之前,由于一般人不知道他事先能铲除病因,所以他的名气无法传出去;中兄治病,是治病于病情初起时,一般人以为他只能治轻微的小病,所以他的名气只及本乡里;而我是治病于病情严重之时,一般人都看到我在经脉上穿针管放血,在皮肤上敷药等大手术,所以以为我的医术高明,名气因此响遍全国。”
本章介绍的例子,我没有高明地做好事前控制、事中控制,而是陷入在事后对严重问题不断地“穿针放血、敷药刮骨”等大手术般的操作中,希望能够让你对于“连接是怎样调优的”产生一点感觉。
通过本章实例,大家可以看到,TCP尤其是TIME_WAIT的调优其实是相对比较复杂的,且是一项耗时耗力的工作。此外,就算做了内核级别的调优,随着容器化Docker和K8S的普及,如果新扩容的机器没有带上这些调优过的配置又会让开发人员重蹈覆辙。
正是由于TCP的复杂性,无池化的数据库程序在高并发的场景下也必然会面临类似的这样或那样的问题。而数据库连接池的出现,将复杂的问题简单化,大大方便了程序员的开发运维工作,进而提升研发效能。接下来,让我们了解一些数据库连接池的背景、原理和理论。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:

华章出版社

官方博客
官网链接