作者:木子魚皮 鏈接:https://www./discuss/368998 本文是個人(騰訊廣告全棧畢業(yè)生)從零開始一周緊急上線百萬高并發(fā)系統(tǒng)的相關經(jīng)驗、思路及感悟,在此記錄分享。 后續(xù)持續(xù)更新,歡迎先??后看! 花5-10分鐘閱讀本文,你將收獲: 1.加深對實際工作環(huán)境、工作狀態(tài)的了解2.學習高并發(fā)系統(tǒng)的設計思路、技術選型及理解3.學習工作中對接多方的溝通技巧4.學會與測試打配合的技巧5.學習緊急事故的處理方式6.事后如何進行歸納總結7.感受筆者爆肝工作的痛苦與掙扎 前言從年前開始和導師二人接手了一個加緊項目,年前加班做完一期后效果顯著,于是開工后加急開發(fā)二期,目標是7天上線(后來延長至9天)。由于項目難度大、工期緊、人手缺、對接方多,極具挑戰(zhàn)性,因此和導師二人開始了007的爆肝工作。
項目介紹首先要介紹下負責的項目及系統(tǒng)。項目背景、業(yè)務等信息自然不能透露,這里剝離業(yè)務,介紹一下抽象出的關鍵系統(tǒng)模型,如下圖: 如圖,我負責的是一個狀態(tài)流轉系統(tǒng)和查詢系統(tǒng),以及它們依賴的DB服務。 狀態(tài)流轉系統(tǒng)的作用主要是按照邏輯修改DB中的狀態(tài)值,并在修改成功時依據(jù)狀態(tài)向其他業(yè)務側發(fā)送通知。 查詢系統(tǒng),顧名思義就是查詢我們負責的DB的值,包括最基礎的鑒權、查詢等功能。 先分析一下系統(tǒng)中一些難點: 1.明顯,查詢系統(tǒng)是一個高扇入服務,被各其他業(yè)務側調用,必然會存在三個問題:·高并發(fā):各業(yè)務側流量聚集,經(jīng)評估,會產(chǎn)生百萬量級的高并發(fā)流量·兼容性:如何設計一套API,兼容各業(yè)務側的同時易被理解·對接復雜:要同時與4個業(yè)務側的同學溝通,想想就是一件很復雜的事情2.狀態(tài)流轉系統(tǒng)邏輯相當復雜(最后光邏輯就300多行代碼)3.狀態(tài)流轉系統(tǒng)與查詢系統(tǒng)、其他業(yè)務側存在交互(比如互相發(fā)送通知),對時延、一致性要求很高 分析出難點后,下面開始編寫技術方案。 設計思路在實際工作中,編寫好的、詳細的技術方案是非常有必要的。優(yōu)秀的工程師會在技術方案中考慮到各種場景、評估各種風險、工作量估時、記錄各種問題等,不僅幫助自己梳理思路、歸納總結,同時也給其他人提供了參照以及說服力(比如你預期7天上線,沒有方案誰信你?)。 根據(jù)二八定理,復雜的系統(tǒng)中,可能編寫技術方案、梳理設計思路的時間和實際敲代碼開發(fā)的時間比例為8 : 2。 設計遵循的原則是”貼合業(yè)務“,沒有最好的架構,只有最適合業(yè)務的架構。切忌過度設計! 此外,還要考慮項目的緊急程度和人力成本,先保證可用,再追求極致。 一些簡單的設計這里就略過了,下面針對系統(tǒng)難點和業(yè)務需求,列舉幾個重點設計及技術選型: 1. 高并發(fā)提到高并發(fā),大家首先想到的是緩存和負載均衡,缺一不可。 負載均衡說白了就是“砸錢,加機器!”,但是為公司省機器、省成本應該是每位后端工程師的基本理念,就要靠技術選型和架構設計來實現(xiàn)了,目標是保證每臺機器能抗住最大的并發(fā)流量。 選型如下: 1.編程框架:選擇輕量級的Restful框架Jersey,搭配輕量級依賴注入Guice(不用Spring,可以私信我問原因)2.Web服務器:選擇性能最高的輕量級NIO服務器Grizzly(各服務器性能對比[1])3.緩存:CKV+ 騰訊自研海量分布式存儲系統(tǒng)(支持Redis協(xié)議,有數(shù)據(jù)監(jiān)控平臺,已開源)4.DB分庫分表:公司自研基礎設施,不多說5.負載均衡:輕量級反向代理服務器 Nginx,百萬并發(fā)需要增加十余臺機器6.CDN及預熱:保證高效的下載服務 其中,緩存是抗住高并發(fā)流量的關鍵,須重點設計。 緩存方案1. 數(shù)據(jù)結構設計用過緩存的同學都了解,關于緩存Key的設計是很重要的,根據(jù)業(yè)務來,保證隔離和易查找(便于緩存更新)就好,這里我選擇請求參數(shù)+接口唯一id來拼接key。并且分頁接口可復用全量list接口。 2. 緩存降級 找不到對應key/redis連接失敗時直接查庫。 3. 緩存更新 當DB修改時,對緩存進行刪除。由于存在非必填的請求參數(shù),因此key可能是一個模糊值(比如有a、b兩個請求參數(shù),key可能為“a”,也可能為“ab”)。 針對請求字段固定(均必填)的接口,更新緩存時,直接拼接出唯一的key進行刪除即可。 而針對請求字段不固定(存在非必填字段)的接口,可使用redis的scan命令范圍掃描(千萬別用keys命令[2]!用了等著被優(yōu)化吧) 要更新的接口、對應key及匹配規(guī)則可能如下表:
4. 緩存穿透 無論查詢出的列表是否為空,都寫入緩存。但在業(yè)務會返回多種錯誤碼時,不建議采用這種方式,復雜度高,成本太大。 2. 兼容性兼容性主要考察接口的設計,為兼容多個業(yè)務側,需要將請求參數(shù)以及響應參數(shù)設置的盡可能靈活。在設計接口時,切忌一定要和所有的業(yè)務側對齊,否則可能導致滿盤皆輸! 這里有三個技巧: 1.提供可訪問鏈接的文檔,供調用方即時查閱(一般公司都有知識庫)。2.請求參數(shù)不能過多,且要易于理解,不能為了強制兼容而設置過于復雜的參數(shù),必要時可針對某一業(yè)務側定制接口。3.響應參數(shù)盡量多(多不是濫),要知道每次增加返回字段都要修改代碼,而適當冗余的字段避免了此問題。 3. 消息通知上面難點中提到:狀態(tài)流轉系統(tǒng)與查詢系統(tǒng)、其他業(yè)務側存在互相發(fā)送通知的交互,在查詢系統(tǒng)收到通知后,要對緩存進行即時更新,因此對消息的實時性要求很高。 這里最初有兩種方案: 1.各系統(tǒng)提供回調接口,用于接收通知。能保證實時性,但是各系統(tǒng)間緊耦合,不利于擴展。2.使用消息隊列,實現(xiàn)應用解耦及異步消息。 最后還是果斷采取了第二種方案,并選用公司自研 TubeMQ 萬億級分布式消息中間件[3](已開源Apache孵化),原因如下: 1.狀態(tài)流轉系統(tǒng)的通知數(shù)據(jù)之后可能存在其他消費方,使用消息隊列利于擴展,對代碼侵入性也少2.消息隊隊列可持久化消息3.TubeMQ支持消費方負載均衡,性能高4.TubeMQ容量大,可存放萬億數(shù)量級消息5.支持公司自研組件,便于形成統(tǒng)一規(guī)范(類似現(xiàn)在的全業(yè)務上云)
***險評估切忌,在使用中間件/框架前,要盡可能多的進行了解可能帶來的風險,一般公司內(nèi)都有KM(知識庫),可利用好內(nèi)部資源或者google! 這里我主要評估了TubeMQ帶來的風險,做一些分享,非技術的同學建議直接跳過! TubeMQ風險1. 消息可靠性Tube性能高,但是不保證消息的絕對可靠! Tube系統(tǒng)主要在兩個地方可能會有數(shù)據(jù)丟失: 1.第一是Tube采取了Consumer信任模型,即數(shù)據(jù)一旦被Consumer拉取到本地,就默認會消費成功,如果Consumer在實際消費的過程中出現(xiàn)錯誤,則Tube并不負責恢復。2.由于操作系統(tǒng)pagecache的利用,服務器斷電或宕機而可能帶來的數(shù)據(jù)丟失。 經(jīng)評估,本業(yè)務需同時保障發(fā)送方及消費方的消息可靠性。 2. 消息順序性Tube沿用了Kafka的分區(qū)設計思想,而分區(qū)的數(shù)據(jù)消費之間是沒有先后順序關系的,而且Tube支持消息的異步方式發(fā)送;在這種方式下,網(wǎng)絡并不能保證先發(fā)送的消息就一定會先到達服務端,所以Tube一般不提供順序性的保證。 經(jīng)評估,本業(yè)務消息消費方允許消息非順序。 3. 消息重復Tube集群中,Consumer的消費位置信息由Broker端進行管理,所以在某些異常情況下,Broker可能無準確獲得Consumer的實際消費情況而導致數(shù)據(jù)重復;另外就是出于性能考慮, Consumer的消費位置信息在每次變化時,并不會實時更新到持久化存儲中,而是暫存于內(nèi)存,周期性更新,如果此時broker宕機即會導致少量的數(shù)據(jù)重復。 經(jīng)評估,本業(yè)務消息消費方是相對冪等操作,可允許消息重復。 4. 監(jiān)控告警1.公司內(nèi)部提供監(jiān)控平臺,但數(shù)據(jù)有五分鐘延遲,非實時監(jiān)控2.提供了對消費方單分區(qū)滯后的告警,可在公司內(nèi)部平臺直接修改消費配置 那么,如何規(guī)避風險呢?設計了針對消息可靠性和數(shù)據(jù)一致性的解決方案。 消息可靠性方案1. 生產(chǎn)方消息可靠性1.Tube可保證消息一定送達,發(fā)送失敗時會自動重發(fā)。2.發(fā)送消息結束時會觸發(fā)回調,回調里可判斷ACK狀態(tài),將發(fā)送失敗的消息放入隊列,下次發(fā)送優(yōu)先從隊列里取。 2. 消費方消息可靠性1.消費失敗時記錄日志,確保消息不丟失 數(shù)據(jù)一致性方案1. 設計消息補償接口消息消費失敗時,會記錄日志,人工排查日志,調用補償接口再次消費消息。(其實也可以存db消息表,寫任務去輪詢消費,成本太高) 開發(fā)過程其實開發(fā)過程沒什么好說的,就是按照技術方案去敲代碼。 這里也有幾個要點: 1.同時開發(fā)多個項目時,每個項目一個獨立Git分支,合并的時候分批合并,否則別人CR你代碼的時候可能你就要打噴嚏了!2.給每個請求做一些打點數(shù)據(jù)上報,比如請求量、請求時間,便于監(jiān)控統(tǒng)計(這里我將數(shù)據(jù)上報至公司自研網(wǎng)關的系統(tǒng),可視化監(jiān)控)3.多打日志,打詳細清晰的日志,便于故障定位
問題解決問題主要在測試及線上被發(fā)現(xiàn),問題解決的過程就像坐過山車,經(jīng)常的狀態(tài)是:測試 => 開發(fā) => 測試 => 上線 => 開發(fā) => 測試,循環(huán)往復。。。 兩個溫馨小貼士: 1.遇到問題時,千萬不要慌,可以先深呼吸幾口氣,因為問題一定是可以解決的,解決不了那么你可能要被解決了!2.解決問題后,千萬別激動,可以先深呼吸幾口氣,因為你還會產(chǎn)生新的問題,而且往往新問題更嚴重! 這里分享一些印象深刻的問題。 1. 事務提交時報錯?原因:事務依賴的服務里也有事務,因此事務里套了事務,破壞了隔離性。 解決:修改代碼,保證事務隔離性。 2. 依賴包存在,項目啟動卻報錯?原因:存在多版本jar包,導致Java代碼使用反射機制動態(tài)生成類是不知道使用哪個版本的依賴的類。 解決:刪掉多余版本jar包。 3. 緩存未即時更新原因:經(jīng)排查,是由于實際的key數(shù)量可達千萬級,導致更新緩存前對要刪除的keys的scan掃描效率過低,長達20多秒! 解決:修改更新緩存方案,不再使用scan掃描,而是拼湊出所有可能的keys,直接delete。 以為這個問題這樣就結束了?不要忘記上面的小貼士: “解決問題后,千萬別激動,可以先深呼吸幾口氣,因為你還會產(chǎn)生新的問題,而且往往新問題更嚴重!” ↓↓↓ 4. 緩存仍未即時更新?原因:某業(yè)務側要求數(shù)據(jù)強一致性,而緩存雖然是毫秒級更新,但無法做到真正的實時一致。 解決:為其定制一個接口,該接口不查詢緩存,直接查DB,保證查到的數(shù)據(jù)一定是最新值。 5. 請求卡死服務運行一段時間后,發(fā)現(xiàn)所有的請求都被阻塞了!心臟受不了。 原因:jstack打印線程信息后分析thread_dump文件,發(fā)現(xiàn)是由于jedis未手動釋放連接使資源耗盡,導致新的請求中會不斷等待jedis連接資源釋放,從而卡死。 解決:補充釋放資源代碼即可。 6. 線上環(huán)境分析日志時突然告警磁盤IO占用超過99%???原因:誤用cat命令查看未分割的原始日志文件(31G?。。。?,導致磁盤IO直接刷爆! 解決:使用less、tail、head等命令替換cat,并移除已備份的大日志文件 7. 進程閃退排查:通常jvm進程閃退是有錯誤日志的,但是并沒有找到,排查陷入絕境。沒辦法,只能祈禱問題不再復現(xiàn)。后來問題真的沒出現(xiàn)過了,謝謝謝謝! 原因:最后,經(jīng)詢問,是有人手動kill掉了這個進程。。。好的,開啟問候模式 8. 線上環(huán)境的消息通知發(fā)送成功了,怎么沒有預期的數(shù)據(jù)更新效果?定位思路:先看消息是否被消費,再看對消息的處理是否正確 排查:查看線上日志,發(fā)現(xiàn)消息并未被消費;但是查看監(jiān)控界面,發(fā)現(xiàn)消息被測試環(huán)境的機器消費了?。?! 原因:由于測試環(huán)境和線上環(huán)境屬于同一個消費組,當消息到達時,同一個消費組只有一個消費者能夠成功消費該消息,被測試環(huán)境消費掉了,導致線上環(huán)境數(shù)據(jù)沒更新。 發(fā)現(xiàn)這個問題的時候,已經(jīng)是上線前一天的深夜。。。再申請一個消費組已經(jīng)來不及了,情急之下,只能先下掉測試環(huán)境的服務。第二天申請好消費組后,根據(jù)環(huán)境去區(qū)分使用哪個消費組就可以了,這樣每個消費組都會消費消息,成功避免了消息競爭。
9. 報告!流量太大,撐不住??!原因:現(xiàn)有4臺機器無法支撐百萬并發(fā),需進行緊急擴容 解決:緊急新申請了10臺機器,完成初始化配置,成功部署服務后修改負載均衡服務配置,成功增大了并發(fā)度。
10. 為什么新增機器上的服務沒有記錄日志?排查:先發(fā)請求測試服務是否可用。測試發(fā)現(xiàn)服務是可用的,只是沒有記錄日志。dump_thread發(fā)現(xiàn),日志線程被持續(xù)阻塞。 原因:服務啟動時,會激活TubeMQ消費者,上面提到,Tube消費者有消費組的概念,同組內(nèi)的消費者會競爭消息(負載均衡),只有一個消費者會收到消息。由于消費組中的最大消費者數(shù)量等同于配置的數(shù)據(jù)分區(qū)數(shù),導致新增機器的服務中,消費者訂閱不成功,訂閱線程持續(xù)占用日志資源(加鎖不釋放),導致日志線程被持續(xù)阻塞。 解決:另一個框架的日志能夠生成,因此影響不大,暫未解決。 11. 上線前一天你跟我說接口設計有問題?原因:溝通出現(xiàn)嚴重問題! 其實工作中,很多同事因為自身業(yè)務繁忙,可能在核對接口設計方案的時候不說話,周知的消息不看,給文檔也不看。等他們忙完了,會反復@你、私聊你詢問。我們一定不要這樣! 解決:緊急電話會議,拉群核對方案
12. 線上出bug了?。?!線上出bug,是一件很大的事,必須緊急響應。在夢里也得給我爬起來! 原因:測試環(huán)境和線上環(huán)境未必完全一致,且測試環(huán)境未必能測出所有問題。因此驗證時通常需要預發(fā)布環(huán)境,數(shù)據(jù)使用線上數(shù)據(jù),但卻是獨立的服務器,保證不影響線上。 解決:緊急排查定位問題,三分鐘成功修復! 修復bug有一定的技巧,分享下個人的排錯路徑: 截圖/問題 => 請求 => bug是否可復現(xiàn),和測試緊密配合 => 數(shù)據(jù) => 數(shù)據(jù)源(真實數(shù)據(jù)與接口數(shù)據(jù)是否一致) => 數(shù)據(jù)處理 解釋一下: 通常發(fā)現(xiàn)問題的是運維、用戶或者測試,他們會拋出一個問題或者問題的相關的截圖,這時,我們要快速想到這個問題對應的功能(即對應的請求/接口),然后讓問題描述者盡可能多的提供信息(比如請求參數(shù)、問題時間等)。 如果問題時間較久,看日志及監(jiān)控不易排查,可以詢問是否可以造一個復現(xiàn)該問題的case,這樣只需觀察最新的日志即可,方便排錯。 定位到請求后,我們要分析請求及響應的哪些數(shù)據(jù)是異常的,即定位關鍵數(shù)據(jù),然后定位數(shù)據(jù)來源(是從數(shù)據(jù)庫查的,還是從緩存查的),并觀察響應數(shù)據(jù)與真實數(shù)據(jù)源是否一致。如果不一致,可能是業(yè)務邏輯中對數(shù)據(jù)的處理出現(xiàn)了問題,再進一步去做分析。
13. 線上出現(xiàn)部分錯誤數(shù)據(jù)這是一個可以預見的問題。還好已經(jīng)在項目中配置了郵件告警,能夠報告錯誤數(shù)據(jù)的信息,錯誤數(shù)據(jù)量也不大。 解決:修復導致錯誤數(shù)據(jù)的bug后,編寫程序循環(huán)所有錯誤信息并生成請求list,然后手動發(fā)送請求,刷新線上不同步數(shù)據(jù)即可。
14. 線上機器OOM?。?!上線三天后發(fā)現(xiàn)的問題,部分線上機器竟然出現(xiàn)了OOM(堆內(nèi)存溢出)的情況,導致服務不可用。 血淚教訓1.有問題一定盡可能在測試環(huán)境去解決,否則線上出問題對心臟很不友好2.不要盲目樂觀,以為上線就沒問題,要多驗證,保持警惕。 PS:上線后如果發(fā)現(xiàn)問題,會經(jīng)歷如下的流程,我稱它為happy流程: 上線后的變更流程: 當發(fā)現(xiàn)DB服務的bug后,你只需要改DB服務的一行代碼。你需要重復如下流程: 1.修改DB服務的一行代碼2.跑單元測試3.DB服務打成依賴包4.修改“狀態(tài)流轉系統(tǒng)”、“查詢系統(tǒng)”對DB服務的依賴包(改動版本號/更新本地緩存拉取最新包)5.重新發(fā)布“狀態(tài)流轉系統(tǒng)”、“查詢系統(tǒng)”至測試環(huán)境6.可能還要重新交給測試的同學進行回歸測試7.測試通過,再次提交“狀態(tài)流轉系統(tǒng)”、“查詢系統(tǒng)”的代碼,發(fā)起CR(代碼審查)8.找同事/Leader讀代碼,通過CR9.合并分支10.發(fā)布“狀態(tài)流轉系統(tǒng)”、“查詢系統(tǒng)”至線上環(huán)境,每發(fā)一臺機器,都要進行一次驗證(滾動部署)11.再次發(fā)現(xiàn)新的bug 這是一件惡心到爆炸的事情,但是在這個過程中我們發(fā)現(xiàn),2、6、8狀態(tài)時,是存在空余時間的,這個時候我們可以做做其他工作,記錄一下工作內(nèi)容、問題等 刷刷抖音,看看??汀?/p> 總結首先總結一下這個項目各階段的耗時: ·理解需求:5%·開發(fā):15%·溝通確認問題:30%·測試及驗證:30%·上線及驗證:20% 其中,修復bug貫穿后面的幾個流程,大概占了總時間的60%。 項目過程存在的問題: 1.前期未參與需求評審,了解的信息較少。2.上線前一天晚上,竟然還在臨時對齊接口?這是在溝通方案階段應該確認好的。3.大約80%的時間花在溝通、查詢數(shù)據(jù)、提供數(shù)據(jù)及驗證。4.自己沒測試完,就開始串測,導致同一個bug被多方發(fā)現(xiàn),反復@,導致改bug效率低下。5.對自研中間件的不熟悉,導致花費的時間成本較高。6.全局觀還不夠,不能提前預見到一些可能的問題。 自我感覺良好的地方: 1.和測試同學配合緊密,互相體諒,測試效率較高2.為查詢系統(tǒng)編寫了詳細的接口文檔,上傳至公司知識庫供實時查閱3.最快3分鐘緊急修復線上bug4.最快30分鐘從接受需求到上線5.在發(fā)現(xiàn)中間件問題時,即時和對接方溝通,設計出了對其無任何影響的低成本解決方案6.積極幫助其他同學查詢數(shù)據(jù),排查問題7.編寫腳本高效解決部分錯誤數(shù)據(jù) 成長與收獲: 1.抗壓熬夜能力 ↑2.設計思維能力 ↑3.溝通能力 ↑4.解決問題能力 ↑5.高級命令熟悉度 ↑6.中間件熟悉度 ↑7.集群管理能力 ↑8.拒絕需求能力 ↑9.吐槽能力 ↑10.吹??能力 ↑ 后續(xù)項目上線后,通過總結復盤,發(fā)現(xiàn)了項目中值得優(yōu)化的地方,也思考到了一些更健全的機制,將逐漸去實現(xiàn)。 如下: 1. 兩個系統(tǒng)中有部分相同的配置,目前采用復制粘貼的方式去同步這種方式的優(yōu)點是比較簡單,無需額外的操作。但缺點也很明顯,如果一個系統(tǒng)的配置改了,而忘了修改另一個系統(tǒng)的配置,就會出現(xiàn)錯誤。 事實上,可以引入一個配置中心,集中管理配置文件,并且支持手動修改、多環(huán)境、灰度等功能。 公司內(nèi)部做了調研,發(fā)現(xiàn)了一個不錯的開源協(xié)同項目。當然也可以采用阿里的Nacos或攜程的Apollo。 2. 曾經(jīng)的進程閃退問題,必須重視!無法保證進程不閃退,但是可以采取對進程實時監(jiān)控,并自動對閃退進程進行重啟的策略。 實現(xiàn)方式有兩種: 1.使用工具,例如supervisor或monit,可以對進程進行管理和閃退重啟2.編寫shell腳本,再通過定時任務,實現(xiàn)周期性觀察進程狀態(tài)及重啟。推薦將定時任務接入分布式任務調度平臺,尤其當定時任務很多時,進行可視化的管理和方便的控制調度是必要的! 由于公司內(nèi)部的平臺比較完善,我選擇第二種方式。
工作簡單而不簡單,做著有意義的事就好~ ================================ 此處回答一些牛友們的問題,歡迎牛友們拋出疑問、指出不足、積極討論。 問題討論1. 事務依賴的服務也有事務,怎么處理? 答:同一個數(shù)據(jù)訪問對象(dao)開啟多個事務才會出現(xiàn)此問題,處理方式是不使用依賴服務中有事務的方法。比如可以用for循環(huán)單條刪除來代替批量刪除。 2. 為什么不用主流的Spring + SpringMVC,而是用Jersey + Guice框架? 的確,Spring是主流,生態(tài)好,一般大家都會選擇SpringBoot + Tomcat。但主流不代表適用于所有的業(yè)務場景,還是要貼合業(yè)務去做技術選型。其實這里應該拿SpringMVC去對標Jersey、Spring對標Guice,但實際上SpringMVC也依賴Spring(一家人)。 這里不用Spring有如下幾個原因: 1.系統(tǒng)較小型。Spring和SpringMVC功能雖大而全,但是相對于Jersey,顯得有些重量級,需要做更多的工作(比如編寫配置文件等等)。2.系統(tǒng)僅提供查詢服務。而Jersey框架專門提供Restful風格接口,完全可以滿足需求。3.由于Jersey輕量的特性,支持手動注冊接口,相對Spring更為靈活,與其他框架搭配使用也很方便(比如Guice、Grizzly),不易出現(xiàn)版本沖突。4.Guice可以在一個文件中手動注入管理所有依賴,便于查找。而用Spring的時候我們通常是在每個類上加注解掃包或者編寫配置文件,雖然寫起來爽的飛起,但非常不利于代碼閱讀(import *和lombok也是同理,最好不要用)! 這里也提一下用Grizzly服務器來替代Tomcat的好處,主要是: 1.性能更高,高并發(fā)場景表現(xiàn)更穩(wěn)定。2.操作管理方便,在代碼中啟動即可(雖然Tomcat也提供了embed版本)。 3. 負載均衡怎么實現(xiàn)? 企業(yè)負載均衡一般都是軟硬結合(例如l5、Nginx)、四七層結合(例如lvs+keepalived、Nginx)。 要提高負載,首先增加機器或擴容(以設置更大的jvm內(nèi)存),給每個機器部署相同的服務,然后配置負載均衡器,增加到新機器的路由即可。當然完成上述操作后要去做驗證,看是否有請求路由到了新機器。 緩存和DB都是集群的,提供統(tǒng)一接口供查詢服務調用,不用擔心各機器的查詢結果不一致。 References
|
|