聲明
本文由Donny譯自 3scale.com 的 《How to load test & tune performance on your API》
本文基于Mark在APIStrat/APIDays 柏林站的演講,視頻可以在YouTube上看霞掺,如果你可以翻墻的話承桥。
這是如何對(duì)API進(jìn)行負(fù)載測(cè)試與調(diào)優(yōu)的第2部分。在第1部分中根悼,我們聊了配置測(cè)試環(huán)境,聊了要測(cè)量的指標(biāo)以及測(cè)量這些指標(biāo)的不同方法蜀撑。我們還了解了使用哪些測(cè)試工具挤巡,以獲得有關(guān)我們的API執(zhí)行情況的真實(shí)數(shù)據(jù)。
我們現(xiàn)在將研究如何將API安全地暴露給公眾酷麦,同時(shí)確保其性能不受影響矿卑。
如何為你的API添加訪問(wèn)控制層
我們已經(jīng)有了高性能的API了,但如果萬(wàn)一有人以超過(guò)16000次請(qǐng)求/秒的速度向服務(wù)器發(fā)送請(qǐng)求怎么辦沃饶?你如何能防止API用戶向你的API發(fā)出爆炸性請(qǐng)求母廷?如果沒(méi)處理好轻黑,將會(huì)影響其他用戶對(duì)API的使用。
解決方法有很多琴昆,最簡(jiǎn)單的就是在你的API服務(wù)器建立限速系統(tǒng)氓鄙。我們認(rèn)為應(yīng)該盡可能地降低系統(tǒng)之間的耦合度,所以最好在你的系統(tǒng)中有一個(gè)單獨(dú)的層业舍,這個(gè)單獨(dú)的層專門負(fù)責(zé)處理限速抖拦。
這時(shí)候API網(wǎng)關(guān)就可以派上用場(chǎng)了。API網(wǎng)關(guān)是解決管理API訪問(wèn)問(wèn)題的通用架構(gòu)解決方案舷暮。它除了用來(lái)做訪問(wèn)控制态罪,還可以充當(dāng)協(xié)調(diào)與開(kāi)放內(nèi)部API不同接口的整合層。
在本文案例中下面,我們將使用我們自己的API網(wǎng)關(guān)复颈,它與3scale平臺(tái)一起使API提供商能夠以安全的方式向外界開(kāi)放他們的API。它可以很方便地對(duì)API接口進(jìn)行身份驗(yàn)證與設(shè)置限速沥割。
有幾種方法可以將您的API與3scale集成耗啦,我們這里選擇基于Nginx的高性能代理部署API網(wǎng)關(guān)。我們將會(huì)在我們的API服務(wù)器之前部署3scale API網(wǎng)關(guān)驯遇。使用代理的原因不僅僅是性能問(wèn)題:由于它部署在我們的API之前芹彬,那些沒(méi)經(jīng)身份驗(yàn)證的或高于我們?cè)试S限制的流量請(qǐng)求在到達(dá)API服務(wù)器之前將會(huì)被代理拒絕掉。這讓我們可以更專注考慮我們的API服務(wù)器叉庐,這樣我們的API服務(wù)器就可以按我們預(yù)定的流量負(fù)載來(lái)設(shè)計(jì)舒帮,不用擔(dān)心超過(guò)這個(gè)流量會(huì)有什么意外發(fā)生,其他的事就交給API網(wǎng)關(guān)處理陡叠。當(dāng)然玩郊,萬(wàn)一我們的API服務(wù)器負(fù)荷處理量增加或者是用戶數(shù)量意外增長(zhǎng)時(shí),我們也能在3scale的管理平臺(tái)上調(diào)整限制設(shè)置枉阵。
作為工程師译红,在架構(gòu)中增加擴(kuò)展層要謹(jǐn)慎。所以我們這里的目標(biāo)是確保這個(gè)擴(kuò)展性不會(huì)對(duì)我們的API性能造成影響兴溜。
我們會(huì)在與我們的API服務(wù)器使用相同類型配置的AWS實(shí)例上部署網(wǎng)關(guān)侦厚,一個(gè)帶有2個(gè)虛擬核的c4.large。設(shè)置網(wǎng)關(guān)很簡(jiǎn)單拙徽,我們可以借用AWS服務(wù)市場(chǎng)上我們的AMI映像刨沦。
在3scale平臺(tái)上配置好API后,我們會(huì)拿到定制的Nginx配置文件膘怕,我們用它來(lái)啟動(dòng)API網(wǎng)關(guān)想诅。第一步將使用默認(rèn)配置運(yùn)行我們之前做的相同測(cè)試,請(qǐng)求地址要小修改一下,現(xiàn)在多包含了一個(gè)帶有API 密鑰的參數(shù)来破。
GET http://our-api-gateway.com/question?user_key=ABCD123
以10000次請(qǐng)求/秒速度運(yùn)行和以前相同的測(cè)試缤底,我們會(huì)命中幾個(gè)錯(cuò)誤瘦黑。 Loader.io最終由于大量的錯(cuò)誤停止測(cè)試。
這些都似乎是500狀態(tài)碼內(nèi)部錯(cuò)誤或其他未指定的網(wǎng)絡(luò)錯(cuò)誤。 我們查過(guò)API服務(wù)器沒(méi)有返回任何錯(cuò)誤桨螺,所以問(wèn)題的源頭可能是Nginx灵奖,其中日志顯示大量的這些:
2015/04/12 23:07:10 [alert] 2573#0: *147508 256 worker_connections are not enough while connecting to upstream, client: ..., server: , request: "GET /question HTTP/1.1", upstream: "http://.../question", host: "..."
Nginx需要為每個(gè)請(qǐng)求至少打開(kāi)兩個(gè)連接桌粉,一個(gè)到客戶端丈牢,另一個(gè)到代理服務(wù)器。 它還需要打開(kāi)連接到3scale骤菠,但不是每個(gè)請(qǐng)求都要連(我們用的是增強(qiáng)版的3scale API網(wǎng)關(guān)它改,它能批量授權(quán)和生成報(bào)告)。
考慮到這一點(diǎn)商乎,以10000次請(qǐng)求/秒的速率央拖,Nginx將需要保持的同時(shí)打開(kāi)連接的數(shù)量將遠(yuǎn)高于256。
調(diào)整API代理網(wǎng)關(guān)以達(dá)最大性能
配置nginx的worker_connections可配置配置同時(shí)打開(kāi)的連接數(shù)鹉戚。該設(shè)置也高度依賴于底層系統(tǒng):Nginx不能打開(kāi)比系統(tǒng)可提供的套接字更多的連接鲜戒。如果我們想提高數(shù)字,有幾個(gè)設(shè)置要修改抹凳。
修改文件/etc/security/limits.conf:
# 如果你沒(méi)配過(guò)以下參數(shù)遏餐,請(qǐng)?jiān)谖募撞吭黾右韵滦校枰貑⑾到y(tǒng)
* soft nofile 200000
* hard nofile 200000
修改文件/etc/sysctl.conf:
# 增加打開(kāi)文件的限制數(shù)
# 改完后運(yùn)行這命令以生效: ?sudo sysctl -p /etc/sysctl.conf
fs.file-max = 5000000
改完以上內(nèi)容后赢底,你接下來(lái)可以修改nginx的配置文件nginx.conf:
...
worker_rlimit_nofile 100000;
events {
worker_connections ?100000;
}
...
Nginx和系統(tǒng)級(jí)的優(yōu)化還有其他一些方法失都,你可以在Nginx的官方文檔中查閱。
在本文案例中幸冻,下面的配置修改粹庞,極大提高了網(wǎng)絡(luò)資源的利用率:
(1)在upstream中啟用Keep alive,這個(gè)需要將HTTP協(xié)議設(shè)為1.1版洽损,這也是Node.js默認(rèn)使用的版本庞溜。
(2)減少tcp_fin_timeout以最小化TIME_WAIT狀態(tài)中的連接數(shù),這樣我們就不需要很多過(guò)時(shí)的連接碑定,記得也要啟用tcp_tw_reuse流码。
(3)將worker_processes設(shè)為auto ,這樣Nginx就可為每一個(gè)可用CPU內(nèi)核啟動(dòng)一個(gè)worker進(jìn)程延刘。
還有很多設(shè)置可以提高Web服務(wù)器的性能旅掂,特別是在系統(tǒng)級(jí)的設(shè)置。你可以在這里對(duì)照一下更為完整的優(yōu)化配置列表访娶。建議你要對(duì)你的系統(tǒng)環(huán)境有足夠的了解,才能應(yīng)用這些優(yōu)化配置觉阅。
還有其他一些配置對(duì)負(fù)載測(cè)試環(huán)境的影響比在生產(chǎn)環(huán)境中影響更大崖疤,比較容易產(chǎn)生誤導(dǎo)性的測(cè)試結(jié)果秘车。比如,增加Nginx中?keepalive_requests?的值可以讓一個(gè)keep-alive連接發(fā)送更多的請(qǐng)求劫哼。在我們的測(cè)試標(biāo)準(zhǔn)中叮趴,所有的負(fù)載生成都是從單一源發(fā)出了,如果增大這個(gè)值权烧,明顯會(huì)比負(fù)載來(lái)自多個(gè)源更有效率眯亦。
檢查一下優(yōu)化設(shè)置是否生效,我們可以在Loader.io上以60秒運(yùn)行10000請(qǐng)求/秒的測(cè)試般码。測(cè)試結(jié)果如下:
測(cè)試結(jié)果現(xiàn)在沒(méi)問(wèn)題了妻率,沒(méi)有500錯(cuò)誤或網(wǎng)絡(luò)錯(cuò)誤。我們達(dá)到了我們預(yù)期的速率板祝。不過(guò)有點(diǎn)微小的差別宫静,就是曲線在延遲增加的地方有些波峰突起,這些突起點(diǎn)是當(dāng)Nginx需要向3scale反饋數(shù)據(jù)時(shí)發(fā)生的券时,這也影響了當(dāng)時(shí)正要處理的幾個(gè)客戶端請(qǐng)求孤里。網(wǎng)關(guān)中的報(bào)告生成是由每個(gè)客戶端完成的,這就是為什么這里的影響非常明顯橘洞,因?yàn)槲覀儚膯蝹€(gè)客戶端生成大量流量捌袜。此外,在測(cè)試期間這些報(bào)告成生的批處理也是相當(dāng)頻繁地進(jìn)行炸枣。如果我們將周期設(shè)置的比測(cè)試持續(xù)時(shí)間更長(zhǎng)虏等,基本上我們一訪問(wèn)完API,結(jié)果就馬上出來(lái)抛虏。
最后博其,我們用wrk重新來(lái)做和前面同樣的測(cè)試。結(jié)果發(fā)現(xiàn)通過(guò)API網(wǎng)關(guān)的性能和我們直接訪問(wèn)API的性能基本一致迂猴。但還是有一個(gè)比較大的區(qū)別慕淡,我們現(xiàn)在在我們的API前面多了一層,這一層讓我們可以控制它沸毁,可以設(shè)定速率限制峰髓,可以身份驗(yàn)證,可以看到API的使用情況統(tǒng)計(jì)分析息尺。而這一切都不需要再修改我們的API代碼携兵。
運(yùn)行1分鐘測(cè)試 @ http://api-gateway/question
4 threads and 1000 connections
Thread Stats ??Avg ?????Stdev ????Max ??+/- Stdev
Latency ??85.27ms ??90.29ms ??1.27s ???92.76%
Req/Sec ????3.98k ??588.91 ????4.27k ???64.50%
Latency Distribution
50% ?85.75ms
75% ?96.61ms
90% ?127.49ms
99% ?230.90ms
955320 requests in 1.00m, 194.17MB read
Requests/sec: ?15942.54
Transfer/sec: ?????3.23MB
總結(jié)
通過(guò)這兩篇文章,我們講述 如何對(duì)API進(jìn)行一個(gè)有效的負(fù)載測(cè)試搂誉。我們先要配置好測(cè)試環(huán)境徐紧,為準(zhǔn)備好測(cè)試提供了一些建議。然后我們介紹了市面上以及開(kāi)源社區(qū)里的幾個(gè)負(fù)載測(cè)試工具。我們測(cè)算出API能實(shí)現(xiàn)的峰值性能并级,同時(shí)在性能不受損的前提下增加了API的訪問(wèn)控制層拂檩。
從本文的測(cè)試中,我們總結(jié)出以幾個(gè)關(guān)鍵點(diǎn):
(1)在運(yùn)行測(cè)試之前嘲碧,你要先定好目標(biāo)稻励,這些目標(biāo)最好是基于你目前流量數(shù)據(jù)來(lái)定的。這有助于你確定你的API要達(dá)到的性能目標(biāo)線愈涩。
(2)要花點(diǎn)時(shí)間準(zhǔn)備好一個(gè)可測(cè)量的穩(wěn)定基線環(huán)境望抽。如果你一開(kāi)始就沒(méi)弄好,你的測(cè)試結(jié)果就毫無(wú)價(jià)值履婉。
(3)別讓測(cè)試工具成為你測(cè)試的限制因素煤篙,要研究了解每個(gè)測(cè)試工具的特性(比如單線程、多線程)谐鼎,多個(gè)測(cè)試工具的測(cè)試可以讓你更全面的了解你的API性能舰蟆。
(3)當(dāng)你微調(diào)了你架構(gòu)中某部分組件的性能時(shí),你需要對(duì)架構(gòu)中所有部分進(jìn)行觀測(cè)狸棍。如果限制因素在系統(tǒng)級(jí)別上身害,那么在API層做優(yōu)化調(diào)整也沒(méi)用。
(4)有一個(gè)API網(wǎng)關(guān)管理層可以讓你更安心草戈,因?yàn)楣芾韺涌梢园踩Wo(hù)好你的API塌鸯,API只會(huì)獲得可預(yù)測(cè)的流量,不會(huì)受爆炸性的意外流量影響唐片。對(duì)于非可預(yù)測(cè)的流量丙猬,API網(wǎng)關(guān)會(huì)處理好。
希望本文能給你帶來(lái)幫助费韭!
本文來(lái)自馬克在 APIStrat / APIDays 柏林站的演講整理茧球。
本文譯自:How to load test & tune performance on your API (Part II)