1. 
          

          1. 新聞動(dòng)態(tài)

            天天說(shuō)要做性能優(yōu)化,到底在優(yōu)化什么?

            網(wǎng)站優(yōu)化 發(fā)布者:zyh123 2020-11-09 11:09 訪(fǎng)問(wèn)量:141

            SQL 優(yōu)化

            當你開(kāi)發(fā)的接口響應時(shí)間超過(guò)了 200ms 的時(shí)候就得優(yōu)化了,當然 200ms 不是絕對值,具體還是看應用場(chǎng)景。以 App 舉例,進(jìn)一個(gè)頁(yè)面調用 5 個(gè)接口(題外話(huà):也可以做聚合),那么總共就是 1s 的時(shí)間,對用戶(hù)來(lái)說(shuō)體驗還算可以,當然是越快響應越好。

            接口耗時(shí) 200ms,其中占大頭的還是對數據庫的操作,一個(gè)接口中會(huì )有 N 次數據庫操作。所以?xún)?yōu)化 SQL 的速度優(yōu)先級是最高的,大量的慢 SQL 會(huì )拖垮整個(gè)系統。

            關(guān)于 SQL 的優(yōu)化不是本文的重點(diǎn),大部分慢 SQL 還是跟各位平時(shí)開(kāi)發(fā)時(shí)的習慣有關(guān)系。大部分在寫(xiě) SQL 的時(shí)候不太會(huì )去考慮性能,只要寫(xiě)出來(lái)就可以了,join 隨手就來(lái),也不梳理查詢(xún)字段,不加索引,剛開(kāi)始上線(xiàn)沒(méi)問(wèn)題,等到并發(fā)量,數據量起來(lái)的時(shí)候就涼涼了。

            關(guān)于數據庫的使用規范大家可以參考下這篇文章:老大讓我整理下公司內部mysql使用規范,分享給大家

            當數據量大了后肯定要做讀寫(xiě)分離和分庫分表的,這也是優(yōu)化的必經(jīng)之路。

            減少重復調用

            性能不好的另一個(gè)致命問(wèn)題就是重復調用,相同的邏輯在不同的方法中重復對數據庫查詢(xún),重復調用 RPC 服務(wù)等。

            比如下面的代碼:

            skuDao.querySkus(productId).stream().map(sku -> {
              skuDao.getById(sku.getId());
            })

            明明數據已經(jīng)查詢(xún)出來(lái)了,又根據 ID 重新去查詢(xún)了一次,數量越多,浪費的時(shí)間越多。這里只是舉例,我相信在真實(shí)的項目中大量存在重復查詢(xún)的情況,之前我還寫(xiě)過(guò)一篇文章,講解如何解決這種重復查詢(xún)問(wèn)題,感興趣的可以查看這篇文章:簡(jiǎn)直騷操作,ThreadLocal還能當緩存用

            按需查詢(xún)

            很多業(yè)務(wù)邏輯不復雜的功能,卻響應很慢。往往都是寫(xiě)代碼的時(shí)候沒(méi)有思考,隨便就調用一些已經(jīng)存在的方法,導致整體響應變慢,總結起來(lái)就是:性能問(wèn)題大部分都是代碼寫(xiě)出來(lái)的。

            說(shuō)個(gè)場(chǎng)景,大家肯定都見(jiàn)到過(guò)。參數是一個(gè)商品 ID, 功能是上架商品,需要進(jìn)行狀態(tài)的判斷,符合條件才能上架。這個(gè)場(chǎng)景下只需要獲取商品的狀態(tài)進(jìn)行判斷即可,有的時(shí)候你看到的代碼往往都是下面的方式:

            GoodsDetail goods = goodsService.detail(id);
            if (goods.getStatus() == GoodsStatusEnum.XXXX) {

            }

            detail 中有大量的邏輯,除了基本的商品信息,還有很多其他的內容,這就是慢的原因。

            并行調用

            針對一個(gè)接口,如果設計到多個(gè)內部 RPC 服務(wù)或者多個(gè)外部接口,在接口之間沒(méi)有關(guān)聯(lián)關(guān)系的情況下,我們可以采用并行調用的方式來(lái)提高性能。

            CompletableFuture 就非常適合并行調用的場(chǎng)景,關(guān)于 CompletableFuture 的使用本文不做詳細說(shuō)明,做 Java 的都要會(huì )用。

            除了 CompletableFuture 之外,對于集合類(lèi)的處理,可以用 parallelStream 來(lái)實(shí)現并行調用。

            在微服務(wù)中有一層專(zhuān)門(mén)用于聚合 API, 聚合層就非常適合并行調用,一個(gè)功能或者一個(gè)頁(yè)面展示會(huì )涉及到多個(gè)接口,通過(guò)聚合層在后端進(jìn)行接口的聚合和數據的裁剪,一起響應給前端。

            上緩存

            緩存也是優(yōu)化中最常用的,效果提升最明顯的,成本也不大。對于緩存,也不要濫用,不是所有場(chǎng)景都可以靠堆緩存來(lái)提高性能的。

            首先對于實(shí)時(shí)性要求不高的業(yè)務(wù)場(chǎng)景可以?xún)?yōu)先使用緩存,也不用太考慮更新的問(wèn)題,自然過(guò)期就行。

            實(shí)時(shí)性要求高的業(yè)務(wù)場(chǎng)景,用緩存一定要有完整的緩存更新機制,否則很容易造成業(yè)務(wù)數據和緩存數據不一致的情況。

            建議的做法是訂閱 binlog 來(lái)統一更新緩存,不要在代碼中去更新或者失效緩存,簡(jiǎn)單的場(chǎng)景還好,入口就那幾個(gè),問(wèn)題不大。有些數據在多個(gè)場(chǎng)景下使用,需要更新的入口太多了,

            異步處理

            有些邏輯,不需要實(shí)時(shí)反饋給用戶(hù)那就可以采用異步的方式在后臺進(jìn)行處理。

            異步處理的方式最常見(jiàn)的就是將任務(wù)加到線(xiàn)程池中進(jìn)行處理,線(xiàn)程池需要考慮容量以及對一些指標的監控,相關(guān)的文章可以查看我的這篇:一時(shí)技癢,擼了個(gè)動(dòng)態(tài)線(xiàn)程池,源碼放Github了

            除了一些指標的監控,線(xiàn)程池的使用另一個(gè)需要關(guān)注的問(wèn)題就是任務(wù)的持久化。如果你的數據本來(lái)就是存儲好了的,然后讀取出來(lái)通過(guò)線(xiàn)程池去執行是沒(méi)問(wèn)題的。如果是沒(méi)有持久化直接丟入線(xiàn)程池中進(jìn)行執行,就有可能出現丟失的情況,比如服務(wù)重啟之類(lèi)的場(chǎng)景。

            關(guān)于持久化,無(wú)論是線(xiàn)程池還是 EventBus 這種,都會(huì )遇到,所以針對異步的場(chǎng)景我建議大家使用消息隊列比較好。

            消息隊列可以存儲任務(wù)信息,保證不會(huì )丟失。單獨消費隊列的消息進(jìn)行邏輯處理,如果想提高消費速度,也可以在隊列的消費方使用線(xiàn)程池進(jìn)行多線(xiàn)程消費,多線(xiàn)程消費也要避免消息丟失的情況,可以查看我的這篇文章:噓!異步事件這樣用真的好么?

            JVM 參數調整

            JVM 參數的調整,一般情況下我們都不用怎么去調整。偶爾有些代碼寫(xiě)的不好,導致內存溢出了,這個(gè)時(shí)候會(huì )去做一些調整和優(yōu)化代碼。

            參數調整主要是去降低 GC 的導致的停頓問(wèn)題,如果你的程序一直在 GC, 一直在停頓,你的接口自然就慢了。

            只要沒(méi)有頻繁的 Full GC,在優(yōu)化這塊 JVM 的參數調整可以最后再做,優(yōu)先以 SQL 優(yōu)化這些為主。

            加機器

            加機器是最后的終極大招了,并發(fā)量上去的時(shí)候,你在怎么優(yōu)化單機器和單數據庫抗并發(fā)能力也是有限的,這個(gè)時(shí)候只能水平擴展了。

            如果是創(chuàng )業(yè)初期,并且在快速發(fā)展,加機器是最直接的優(yōu)化方式了,雖然說(shuō)成本上去了,但是開(kāi)發(fā)資源也是成本,節約下來(lái)可以實(shí)現更多的業(yè)務(wù)需求。等到中期穩定了再考慮架構,性能方面整體的優(yōu)化和重構。

            就像玩游戲一樣,有裝備的玩家才能所向睥睨啊,對于后端應用來(lái)說(shuō)也是一樣,高配的機器,高配的數據庫配置,高配的緩存等。

            關(guān)于作者:尹吉歡,簡(jiǎn)單的技術(shù)愛(ài)好者,《Spring Cloud 微服務(wù)-全棧技術(shù)與案例解析》, 《Spring Cloud 微服務(wù) 入門(mén) 實(shí)戰與進(jìn)階》作者, 公眾號猿天地發(fā)起人。

            我整理了一份很全的學(xué)習資料,感興趣的可以微信搜索「猿天地」,回復關(guān)鍵字 「學(xué)習資料」獲取我整理好了的 Spring Cloud,Spring Cloud Alibaba,Sharding-JDBC 分庫分表,任務(wù)調度框架 XXL-JOB,MongoDB,爬蟲(chóng)等相關(guān)資料。



            關(guān)鍵字:

            文章連接: http://www.gostscript.com/wzyh/769.html

            版權聲明:文章由 晨展科技 整理收集,來(lái)源于互聯(lián)網(wǎng)或者用戶(hù)投稿,如有侵權,請聯(lián)系我們,我們會(huì )立即刪除。如轉載請保留

            双腿国产亚洲精品无码不卡|国产91精品无码麻豆|97久久久久久久极品|无码人妻少妇久久中文字幕
                1.