一次业务接口性能评估的总结
本篇文章是我在项目中对一个业务接口做性能评估时,对一些问题的思考和相关知识点系统性回顾拾遗的一个总结。
业务背景
我们项目中的一个文件上传接口,主要业务功能是接收第三方渠道端上传的base64编码影像文件和相关业务数据,用户的业务属性数据入库,影像文件的base64编码数据通过调下游服务(中台服务)最终上传至影像平台。外部一直以来对该接口上传的影像文件都有1MB的大小限制,但近期发现,由于存在该限制,阻拦了很多用户的请求,为避免客损,需要放宽文件大小的规则限制至5MB,那么是否会对该服务的可用性产生影响?在不影响存量业务和服务可用性的情况下,该接口能够支持多少的并发数和多大的文件大小限制?
对接口现状的思考
为什么使用base64传输
在此之前要先弄清一个问题,为什么要通过接口来传输影像的base64,而不是通过文件服务器或文件流的方式传输?
文件服务器传输需要异步定时从文件服务器拉取影像,无法做到实时同步响应。且将影像文件通过base64编码传输可以作为application/json类型接口请求体的一个业务字段随其他业务字段一起传输,更加方便灵活,虽然增加了一定的接口报文的数据容量,但是在一些业务的便利性上,还是普遍采用的。
报文长度是否有限制
base64编码后的数据容量大约是原数据容量的1.3倍,post接口是否能容纳这么长的报文长度呢?这里衍生两个问题:
http网络传输本身是否会对报文大小有所限制?
http协议本身对Post请求的json报文大小几乎是没有限制的,非分块传输编码所支持的报文长度受限于请求头中的content_length所能表达的最大长度,这它支持的长度远远超过日常应用场景,所以几乎不用考虑协议本身对报文大小的限制。而更多的应该从网络带宽、服务器内存、请求经过的中间节点(如nginx或tomcat服务器)等相关报文大小配置等方面考虑。接口接收到请求反序列化时,将该base64编码数据赋值给字符串字段的时候是否会因超长导致赋值失败,这就涉及到java中String类型能够支持的数据长度最大是多少?
- 编译期:在Java中,我们要探讨String的最大长度需区分是字面量和运行时传参两种情况,如果是字面量,那么字段大小受限于JVM虚拟机在编译期生成字节码文件时常量池中CONSTANT_Utf8_info常量表的length所能表示的最大长度(u2类型=2字节)为2^16-1=65535=64KB的大小;
- 运行期:而若是运行时动态传值,由于String类型的底层为char数组实现,而char数组的长度是用int类型表示,所以String能接受的最大长度为int类型的最大值即
2^32-1约为4GB,除此之外,由于需要在堆中分配空间,还需考虑堆的空间限制。
探究接口和系统瓶颈
在搞清楚了以上问题后,可以明确,当前场景下,不会受上述先决条件的限制。那么就可以开始对该业务请求进行分析和评估。
整个过程分为以下几步:
- 预估能支撑的并发量和QPS
- 压测
- 性能监控
- 定位耗时和代码优化
- 通过限流和隔离保证系统容错
后续分几篇文章做系统性总结。