轉(zhuǎn)帖|行業(yè)資訊|編輯:龔雪|2016-05-06 17:46:34.000|閱讀 267 次
概述:你的Java應(yīng)用程序的性能是怎樣診斷和優(yōu)化的?不妨看看這兩位西醫(yī)的方子。如果你有更好療效的藥方,也歡迎在評論區(qū)告訴我們。
# 界面/圖表報(bào)表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
當(dāng)我在幫助一些開發(fā)者或架構(gòu)師分析及優(yōu)化Java應(yīng)用程序的性能時(shí),關(guān)鍵往往不在于對個(gè)別方法進(jìn)行微調(diào),以節(jié)省一或兩微秒的執(zhí)行時(shí)間。雖然對某些軟件來說,微秒級的優(yōu)化確實(shí)非常重要,但我認(rèn)為這并非著眼點(diǎn)所在。我在2015年間對數(shù)百個(gè)應(yīng)用進(jìn)行了分析,發(fā)現(xiàn)多數(shù)性能與可伸縮性問題都來源于糟糕的架構(gòu)決策、框架的錯(cuò)誤配置、錯(cuò)誤的數(shù)據(jù)庫訪問模式、過量的日志記錄,以及由于內(nèi)存過度消耗而導(dǎo)致的垃圾回收所帶來的影響。
在我看來,性能工程的根本在于通過大量的觀察,將關(guān)鍵的架構(gòu)指標(biāo)、可伸縮性指標(biāo)以及性能指標(biāo)關(guān)聯(lián)在一起。通過對每次構(gòu)建的結(jié)果以及不同負(fù)載情況下的表現(xiàn)進(jìn)行分析,以發(fā)現(xiàn)系統(tǒng)中的回歸缺陷或瓶頸所在。以下圖中的儀表板作為示例:
通過將系統(tǒng)負(fù)載、響應(yīng)時(shí)間與SQL語句的執(zhí)行次數(shù)等指標(biāo)相關(guān)聯(lián),可得出某些性能工程方面問題的根本原因。
最上面一張圖叫做“層分解”圖表,它顯示了你的應(yīng)用中各個(gè)邏輯組件(例如Web Service、數(shù)據(jù)庫訪問、業(yè)務(wù)邏輯、Web服務(wù)器等等)的總體執(zhí)行時(shí)間。紅色部分所表示的是某個(gè)后端Web Service所花費(fèi)的時(shí)間,很明顯這里產(chǎn)生了一個(gè)組件熱點(diǎn)。
我們同時(shí)可以發(fā)現(xiàn),該Web Service并沒有承受異常的負(fù)載,因?yàn)閺牡诙垐D來看,當(dāng)時(shí)應(yīng)用程序所處理的請求數(shù)量這條線比較平穩(wěn)。一般情況下,整體響應(yīng)時(shí)間多數(shù)都耗費(fèi)在數(shù)據(jù)層,但這并不代表數(shù)據(jù)庫本身的速度緩慢!我了解,低效的數(shù)據(jù)庫訪問往往是造成性能不佳的主要原因,因此通常會結(jié)合分析SQL語句的執(zhí)行次數(shù)。在這個(gè)示例中,已經(jīng)能夠很清楚地看到它與大多數(shù)響應(yīng)時(shí)間的峰值是相關(guān)的。
我所觀察到最常見的問題模式就是糟糕的數(shù)據(jù)庫訪問模式,此外還有過于細(xì)粒度的服務(wù)調(diào)用、糟糕的共享數(shù)據(jù)訪問共享、過度的日志記錄,以及由內(nèi)存泄露以及大量的對象創(chuàng)建所導(dǎo)致的垃圾回收影響或是應(yīng)用程序的崩潰。
在本文中,我將專注于探討數(shù)據(jù)庫方面的問題,因?yàn)槲沂执_信你的所有應(yīng)用都是因這些訪問模式中的某一種而產(chǎn)生問題的!你可以在市場上已有的各種性能診斷、追蹤,或是APM工具之間隨意選擇。Perfino就是一款不錯(cuò)的產(chǎn)品,還有免費(fèi)的Dynatrace Personal License。Java本身也提供了各種出色的工具,例如Java Mission Control等等。許多提供數(shù)據(jù)訪問功能的框架也經(jīng)常通過其日志輸出提供各種診斷選項(xiàng),例如Hibernate或Spring等等。
在使用這些跟蹤工具時(shí),通常不需要對代碼進(jìn)行任何修改,因?yàn)樗麄兌祭昧薐VMTI(JVM Tooling Interface)以捕獲代碼層面的信息,甚至能夠跨遠(yuǎn)程的各層次進(jìn)行調(diào)用追蹤,這一點(diǎn)對于分布式、面向(微)服務(wù)的應(yīng)用來說非常實(shí)用。你所要做的就是修改你的JVM啟動(dòng)命令行選項(xiàng),以加載這些工具。
某些工具的開發(fā)商還提供了與IDE的集成功能,你只需簡單地表示“在運(yùn)行時(shí)開啟XYZ性能診斷功能”。我在YouTube上做了一個(gè)簡單的視頻指南,演示了如何對在Eclipse中啟動(dòng)的應(yīng)用進(jìn)行追蹤。(//www.youtube.com/watch?v=unrey8wfq-M&list=PLqt2rd0eew1bmDn54E2_M2uvbhm_WxY_6&index=14)
即使你已經(jīng)發(fā)現(xiàn)造成應(yīng)用整體響應(yīng)時(shí)間過長的主要原因在于數(shù)據(jù)庫,但也不要因此就輕率地指責(zé)數(shù)據(jù)庫與DBA!造成數(shù)據(jù)庫繁忙的原因可能有以下幾種:
在本文中,我將著重講解如何在應(yīng)用程序端將訪問數(shù)據(jù)庫所消耗的時(shí)間減至最低。
在對應(yīng)用程序進(jìn)行問題診斷時(shí),我通常總要檢查幾個(gè)數(shù)據(jù)庫訪問模式。我會逐個(gè)分析應(yīng)用的請求,并將這些問題分別放入以下這個(gè)“DB問題模式”的分類表中:
我的第一個(gè)示例是一個(gè)web應(yīng)用程序,它能夠提供某幢大樓中的會議室信息。會議室的信息都保存在某個(gè)數(shù)據(jù)庫中,每次當(dāng)用戶生成會議室信息的報(bào)表時(shí),就會調(diào)用某個(gè)自定義的數(shù)據(jù)訪問層以訪問該數(shù)據(jù)庫。
在對個(gè)別請求進(jìn)行分析時(shí),我總是從所謂的事務(wù)流(Transaction Flow)著手檢查。事務(wù)流是一種可視化選項(xiàng),可展現(xiàn)出應(yīng)用程序處理請求的過程。對于會議室信息報(bào)表這個(gè)請求來說,可以看到,該請求首先進(jìn)入web服務(wù)器層(圖左)、隨后進(jìn)入應(yīng)用服務(wù)層(圖中),然后對數(shù)據(jù)層發(fā)起調(diào)用(圖右)。這些層之間的“鏈接”表現(xiàn)了這些層之間的交互次數(shù),例如這個(gè)單一的請求執(zhí)行了多少次SQL查詢。
從這個(gè)屏幕上我們可以立即發(fā)現(xiàn)造成問題的頭兩種模式,即過多的SQL執(zhí)行模式以及數(shù)據(jù)庫繁忙模式。讓我們來分析一下:
很容易就可以看出這個(gè)請求產(chǎn)生了大量的SQL語句執(zhí)行,并且造成數(shù)據(jù)庫繁忙效應(yīng):它總共執(zhí)行了24889次SQL!花費(fèi)了40.27秒(占整個(gè)請求時(shí)間的66.51%)才完成整個(gè)執(zhí)行過程!
如果我們對個(gè)別的SQL語句進(jìn)行分析,將發(fā)現(xiàn)這個(gè)請求還有另外的問題,即N+1 次查詢問題以及低效的連接池訪問(下文將進(jìn)行詳細(xì)討論):
這種糟糕的訪問模式是無法通過對數(shù)據(jù)庫的索引進(jìn)行優(yōu)化而解決的。
我已經(jīng)無數(shù)次看到這種問題發(fā)生了。應(yīng)用的邏輯需要對某個(gè)對象列表進(jìn)行迭代,但它并沒有選擇使用“貪婪加載”(Eager Loading)方式,則是使用了“延遲加載”(Lazy Loading)方式。這種選擇可能來自于O/R映射框架,例如Hibernate或Spring,也可能來自于自主開發(fā)的框架,正如上文所述的示例一樣。該示例使用了某種自主開發(fā)的實(shí)現(xiàn)方式,它會加載每個(gè)會議室對象,并通過獨(dú)立的SQL查詢語句獲取每個(gè)會議室的全部屬性。
每個(gè)SQL查詢都是在一個(gè)向連接池獲取的JDBC連接中執(zhí)行的,然后在每個(gè)查詢完成之后都會返回。這也解釋了為什么該請求會產(chǎn)生12444次set clientname操作,因?yàn)镾ybase JDBC驅(qū)動(dòng)每次向連接池請求連接時(shí)都會提交這一請求。這就是問題所在!其他的JDBC驅(qū)動(dòng)未必會產(chǎn)生set clientname這個(gè)調(diào)用,你可以查看一下調(diào)用getConnection的次數(shù),這同樣可反映出這個(gè)問題。
對于N+1次查詢問題本身來說,使用連接查詢就可以輕易地避免這一問題。在這個(gè)會議室與屬性的示例中,可以使用以下連接查詢:
select r.*, p.* from meeting_rooms as r inner join room_properties as p on p.room_id = r.room_id
結(jié)果就是整個(gè)執(zhí)行過程只產(chǎn)生了1次查詢執(zhí)行,不再是12000多次了!同時(shí)也免除了12000次連接的獲取操作以及對“set clientname”的調(diào)用。
據(jù)我所知,Hibernate或其他O/R映射器有許多使用者。我想要提醒你們一點(diǎn),O/R映射器所提供的延遲加載與貪婪加載選項(xiàng),以及其他各種緩存層各有其存在的理由。對于特定的用例,需要確保你正確地使用了這些特性與選項(xiàng)。
在下面這個(gè)示例中,延遲加載并不是一種好的選擇,因?yàn)榧虞d2千個(gè)對象以及他們的屬性會導(dǎo)致產(chǎn)生4千多次SQL查詢。考慮到我們總是需要獲取所有對象,那么更好的方式是貪婪加載這些對象,然后考慮對他們進(jìn)行緩存,前提是這些對象不會變更得十分頻繁:
在使用Hibernate或Spring等O/R映射器時(shí),需要選擇正確的加載與緩存選項(xiàng)。你需要理解他們的幕后工作原理。
大多數(shù)O/R映射器都會通過日志記錄提供優(yōu)秀的診斷選項(xiàng),同時(shí)也可以查看在線社區(qū)中的內(nèi)容,以了解各種最佳實(shí)踐。推薦你閱讀由Alois Reitbauer撰寫的一系列博客文章,他曾經(jīng)在Hibernate推出的早些年頭對其進(jìn)行過非常深入的研究。在這系列文章中,他特別強(qiáng)調(diào)了如何有效地使用緩存與加載選項(xiàng)。
當(dāng)數(shù)據(jù)庫引擎完成對某條SQL語句的解析,并創(chuàng)建了數(shù)據(jù)訪問的執(zhí)行計(jì)劃后,該結(jié)果會被保存在數(shù)據(jù)庫中的一個(gè)緩存區(qū)域中以便重用,而無需重新解析這一語句(語句解析是數(shù)據(jù)庫中最耗費(fèi)CPU時(shí)間的操作)。用于在緩存中找到某個(gè)查詢的鍵是語句的全文本。這也意味著,如果你調(diào)用了1000次相同的語句,卻為其傳了100個(gè)不同的參數(shù)值(例如where語句中的值),那么在緩存中就會產(chǎn)生1000個(gè)不同的條目,而使用了新參數(shù)的第1001次查詢也必須被再次解析。這種工作方式非常低效。
因此,我們提出了“預(yù)處理的語句”這一概念:某條語句經(jīng)過預(yù)處理、解析后被保存在緩存中,以占位符的方式表示變量。在這條語句的實(shí)際執(zhí)行過程中,這些占位符會被實(shí)際的值所替換,無需再次解析這條語句,可以直接從緩存中找出執(zhí)行計(jì)劃。
數(shù)據(jù)庫訪問框架通常在這一點(diǎn)上做得很出色,會對查詢語句進(jìn)行預(yù)處理。但在自定義代碼中,我發(fā)現(xiàn)開發(fā)者經(jīng)常會忽略這一點(diǎn)。在以下示例中,只有一小部分SQL執(zhí)行經(jīng)過了預(yù)處理過程:
通過對SQL執(zhí)行次數(shù)與已預(yù)處理的SQL執(zhí)行次數(shù)進(jìn)行對比,發(fā)現(xiàn)了未經(jīng)預(yù)處理的數(shù)據(jù)庫訪問的問題
如果你打算自行開發(fā)數(shù)據(jù)庫訪問代碼,請?jiān)俅未_認(rèn)你正確地調(diào)用了prepareStatement。舉例來說,如果你調(diào)用某個(gè)查詢不止1次,那么通常來說最好能夠使用PreparedStatement。如果你選擇使用框架以訪問數(shù)據(jù),也請?jiān)俅未_認(rèn)這些框架的行為,以及在優(yōu)化和執(zhí)行所生成的SQL時(shí)有哪些配置選項(xiàng)可以選擇。實(shí)現(xiàn)一點(diǎn)最簡單的方式是對executeStatement與prepareStatement執(zhí)行的次數(shù)進(jìn)行監(jiān)控。如果你重復(fù)對每個(gè)SQL查詢進(jìn)行相同的監(jiān)控,那么將很容易地找到優(yōu)化熱點(diǎn)。
我經(jīng)常發(fā)現(xiàn)有些應(yīng)用會使用默認(rèn)的連接池大小,例如每個(gè)池10或20個(gè)連接。開發(fā)者總是會忽略對連接池大小的優(yōu)化,因?yàn)樗麄儧]有進(jìn)行必要的大規(guī)模負(fù)載測試,也不知道有多少個(gè)用戶會使用這些新特性,更不了解并行的DB訪問會導(dǎo)致什么結(jié)果。也有可能是從預(yù)發(fā)布環(huán)境轉(zhuǎn)向生產(chǎn)環(huán)境的部署時(shí)“丟失”了連接池的配置信息,導(dǎo)致生產(chǎn)環(huán)境中的配置使用了應(yīng)用服務(wù)器中的默認(rèn)配置。
通過JMX指標(biāo)信息,能夠方便地對連接池的使用情況進(jìn)行監(jiān)控。每種應(yīng)用服務(wù)器(Tomcat、JBoss、Websphere等等)都會提供這些指標(biāo),不過有些服務(wù)器需要你明確地開啟這種特性。下圖展示了某個(gè)群集中的WebLogic服務(wù)器的連接池使用情況。你可以看到,在其中三臺應(yīng)用服務(wù)器中,“活動(dòng)的DB連接數(shù)量”都已經(jīng)達(dá)到最大值。
確保你適當(dāng)?shù)卣{(diào)整了連接池的大小,不要使用與你期待的負(fù)載情況不符的默認(rèn)設(shè)置
出現(xiàn)這一問題的根本原因不在于訪問量的峰值。在本文開頭部分所介紹的“系統(tǒng)負(fù)載 / 響應(yīng)時(shí)間 / 數(shù)據(jù)庫執(zhí)行次數(shù)”這個(gè)儀表板中顯示,應(yīng)用并沒有產(chǎn)生特別的訪問量峰值情況。最終發(fā)現(xiàn),在每天下午2點(diǎn)多這個(gè)時(shí)間段設(shè)定了一個(gè)運(yùn)行報(bào)表的計(jì)劃,它需要執(zhí)行多個(gè)運(yùn)行時(shí)間相當(dāng)長的UPDATE語句,每個(gè)語句都使用了不同的連接。這會在幾分鐘內(nèi)阻塞其他連接,導(dǎo)致了應(yīng)用程序在“正常的”訪問量下出現(xiàn)性能問題,因?yàn)橛脩舻恼埱鬅o法獲得數(shù)據(jù)庫的連接:
個(gè)別的SQL執(zhí)行阻塞了其他連接達(dá)幾分鐘,造成了連接池資源消耗殆盡的問題
如果你已經(jīng)了解到某些請求會使連接掛起一段較長的時(shí)間,你可以選擇以下幾種方案:
不過,首先你要確保對這些查詢進(jìn)行優(yōu)化。通過分析SQL查詢執(zhí)行計(jì)劃,以找出哪些操作是最耗時(shí)的。如今,大多數(shù)APM工具都能夠讓你以某種方式獲取某個(gè)SQL語句的執(zhí)行計(jì)劃。如果沒有可用的工具,最簡單的方式就是使用數(shù)據(jù)庫的命令行工具,或者咨詢某個(gè)DBA,讓他幫助你生成執(zhí)行計(jì)劃。
通過學(xué)習(xí)SQL查詢執(zhí)行計(jì)劃,對你的SQL語句進(jìn)行優(yōu)化
執(zhí)行計(jì)劃能夠顯示出DB引擎處理SQL語句的方式。造成SQL語句執(zhí)行緩慢的原因多種多樣,不僅僅限于缺少索引或是使用索引的方式不對,很多情況下是因?yàn)樵O(shè)計(jì)、結(jié)構(gòu)或連接查詢所造成的。如果你并非SQL方面的專家,可以向DBA或SQL大牛求助。
負(fù)載測試以及在生產(chǎn)環(huán)境中進(jìn)行監(jiān)控的提示與技巧
除了對各個(gè)請求進(jìn)行分析,以指出這些問題模式之外,我同樣也會關(guān)注當(dāng)某個(gè)應(yīng)用程序在負(fù)載情況下的長期趨勢。除了我在本文開頭為你展示的儀表板之外,我也會指出數(shù)據(jù)驅(qū)動(dòng)行為的變化,并對數(shù)據(jù)緩存是否正確運(yùn)行進(jìn)行驗(yàn)證。
下面這張圖表展示了SQL語句執(zhí)行的平均次數(shù)(綠色)以及SQL語句執(zhí)行的總次數(shù)(藍(lán)色)。我們?yōu)閼?yīng)用進(jìn)行了一次兩小時(shí)的性能測試,保持負(fù)載始終處于較高水平。我所期望的結(jié)果是平均次數(shù)逐漸減少,而總次數(shù)則趨向平穩(wěn)。因?yàn)榘凑瘴业募僭O(shè),從DB所獲取的數(shù)據(jù)大多數(shù)是靜態(tài)的,或是會被緩存在某個(gè)不同的層。
如果你的應(yīng)用表現(xiàn)不符合這一預(yù)期,那么可能是遇到了數(shù)據(jù)驅(qū)動(dòng)的性能問題,或是產(chǎn)生了緩存問題
假設(shè)如我之前所展示的一樣,你的應(yīng)用中產(chǎn)生了常見的N+1次查詢問題。那么隨著終端用戶在DB中產(chǎn)生越來越多的數(shù)據(jù),應(yīng)用程序所產(chǎn)生的SQL平均次數(shù)也將不斷提高,因?yàn)檫@些查詢所返回的數(shù)據(jù)也會越來越多!因此,請務(wù)必注意這些數(shù)字!
示例4表現(xiàn)了某個(gè)后臺報(bào)表應(yīng)用在每天下午2點(diǎn)執(zhí)行所造成的問題,與之類似,我同樣也會關(guān)注SQL訪問隨著時(shí)間變化的模式。我所關(guān)注的不僅包括總執(zhí)行時(shí)間,同時(shí)也包括SELECT、INSERT、UPDATE與DELETE的執(zhí)行次數(shù)。這樣一來,我就能夠指出是否在某個(gè)時(shí)間段內(nèi)會進(jìn)行一些特別的活動(dòng),例如通過后臺作業(yè)對大批數(shù)據(jù)進(jìn)行更新。
通過觀察總執(zhí)行時(shí)間,以及SELECT、INSERT、UPDATE與DELETE的執(zhí)行次數(shù),了解應(yīng)用的數(shù)據(jù)庫訪問行為
進(jìn)行大量更新操作的批處理作業(yè)的執(zhí)行需要一段時(shí)間才能完成,尤其對于包含大量行的表來說更為明顯。如果整張表因此被鎖住,那么其他需要對這張表、哪怕只是對其中某些行進(jìn)行更新的請求都必須等待鎖被釋放。你應(yīng)考慮在沒有其他用戶在線的時(shí)間段運(yùn)行這些作業(yè),或?qū)崿F(xiàn)某種不同的加鎖邏輯,實(shí)現(xiàn)對單個(gè)行的加鎖、更新以及釋放操作。
在本文中,我著重分析的數(shù)據(jù)庫性能問題多數(shù)與數(shù)據(jù)庫服務(wù)器本身是否緩慢是無關(guān)的,而主要是由使用了糟糕的數(shù)據(jù)庫訪問模式(N+1次查詢問題、未經(jīng)預(yù)處理的語句等等)的應(yīng)用程序代碼、或是配置錯(cuò)誤(低效的連接池訪問、數(shù)據(jù)驅(qū)動(dòng)問題)所導(dǎo)致的問題。
但是,如果我們完全忽略了數(shù)據(jù)庫本身,那也是不明智的。因此,我總是會對關(guān)鍵的數(shù)據(jù)庫性能指標(biāo)進(jìn)行檢查。大多數(shù)數(shù)據(jù)庫都會通過特殊的系統(tǒng)表提供豐富的性能信息,比如Oracle就會提供某些v$表以及視圖,以訪問關(guān)鍵的數(shù)據(jù)庫性能指標(biāo)(會話、等待時(shí)間、解析時(shí)間、執(zhí)行時(shí)間等等),或是表鎖以及運(yùn)行時(shí)間較慢的SQL等信息,這些信息來自于使用這個(gè)共享的數(shù)據(jù)庫實(shí)例的各個(gè)應(yīng)用程序。
我在進(jìn)行數(shù)據(jù)庫健康檢查時(shí)通常會觀察兩個(gè)儀表板,你可以在此看到來自于這些性能表中的指標(biāo)數(shù)據(jù):
觀察數(shù)據(jù)庫是處于健康狀態(tài),還是由于共享該數(shù)據(jù)庫實(shí)例的應(yīng)用產(chǎn)生過多的負(fù)載而產(chǎn)生了影響。
通過表鎖等信息,判斷是否有某個(gè)正在執(zhí)行中的SQL語句對服務(wù)器乃至你的應(yīng)用造成了負(fù)面影響
在持續(xù)集成流程中對數(shù)據(jù)庫指標(biāo)進(jìn)行自動(dòng)檢測
在我為你介紹分析關(guān)鍵數(shù)據(jù)庫指標(biāo)以及用例的一些新點(diǎn)子之前,我希望首先能夠彌補(bǔ)一個(gè)缺失的主題,而這一點(diǎn)是我們都應(yīng)當(dāng)考慮到的,那就是自動(dòng)化!
我建議你不要手動(dòng)地執(zhí)行這些檢查步驟,而是通過持續(xù)集成工具檢查這些指標(biāo),將這一步驟與單元測試、集成測試、REST API或其他類型的功能性測試等步驟結(jié)合在一起。如果你已經(jīng)設(shè)計(jì)出一套測試用例集,用于檢查各種REST API或新特性的功能,那么為什么不在每次構(gòu)建的測試執(zhí)行期間去捕獲這些指標(biāo)呢?這種方式可以帶來以下益處:
下面這幅屏幕截圖展示了每次構(gòu)建與每次測試時(shí)對這些指標(biāo)的追蹤,并在其表現(xiàn)異常時(shí)發(fā)出警告。你可以將這些指標(biāo)集成在你的構(gòu)建管道中,并且當(dāng)某個(gè)代碼變更造成影響時(shí)通過通知信息了解情況,隨后立即修復(fù)這一問題,避免當(dāng)代碼發(fā)布到生產(chǎn)環(huán)境時(shí)產(chǎn)生系統(tǒng)崩潰的情況。
在你的持續(xù)集成流程中加入這些指標(biāo),并對指標(biāo)的變化進(jìn)行觀察,以自動(dòng)地找出各種糟糕的數(shù)據(jù)庫訪問模式!
在本文中,我們專注的是數(shù)據(jù)庫方面的熱點(diǎn)問題。但在我的工作過程中,我也在其他領(lǐng)域發(fā)現(xiàn)許多類型的性能問題。在2015年,我參與了一個(gè)將一體性應(yīng)用遷移為(微)服務(wù)的項(xiàng)目,在其中發(fā)現(xiàn)了一個(gè)巨大的峰值問題。該問題類似于我們已分析過的某些模式,例如N+1次查詢問題,原因在于某個(gè)用例會數(shù)百次調(diào)用某個(gè)后端服務(wù)。
大多數(shù)情況下,這種問題都是由糟糕的接口設(shè)計(jì)而造成的,并且沒有考慮到某個(gè)原本在本地調(diào)用的方法在Docker容器或云計(jì)算環(huán)境中被執(zhí)行時(shí)會發(fā)生什么。網(wǎng)絡(luò)問題會突然間出現(xiàn),包括通過網(wǎng)絡(luò)傳輸?shù)男畔⒁约靶碌倪B接池(意味著你需要考慮線程與套接字),這些問題是你必須處理的。
原文翻譯自:
文章轉(zhuǎn)載自:
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請郵件反饋至chenjj@fc6vip.cn