優化直播app原始碼介面效能,我們可以採取的手段
直播app原始碼中各個功能的實現都需要利用介面,所以介面的效能對整個系統的效能影響是很大的,為了優化直播app原始碼的介面效能,我們可以採取哪些手段呢?
一、非同步處理
有時候,進行直播app原始碼介面效能優化,需要重新梳理一下業務邏輯,看看是否有設計上不太合理的地方。
比如有個使用者請求介面中,需要做業務操作,發站內通知,和記錄操作日誌。為了實現起來比較方便,通常我們會將這些邏輯放在介面中同步執行,勢必會對介面效能造成一定的影響。
介面內部流程圖如下:
直播app原始碼的這個介面表面上看起來沒有問題,但如果你仔細梳理一下業務邏輯,會發現只有業務操作才是核心邏輯,其他的功能都是非核心邏輯。
在這裡有個原則就是:核心邏輯可以同步執行,同步寫庫。非核心邏輯,可以非同步執行,非同步寫庫。
上面這個例子中,發站內通知和使用者操作日誌功能,對實時性要求不高,即使晚點寫庫,使用者無非是晚點收到站內通知,或者運營晚點看到使用者操作日誌,對業務影響不大,所以完全可以非同步處理。
直播app原始碼開發中,通常非同步主要有兩種:多執行緒 和 mq。
1、執行緒池
使用執行緒池改造之後,介面邏輯如下:
發站內通知和使用者操作日誌功能,被提交到了兩個單獨的執行緒池中。
這樣介面中重點關注的是業務操作,把其他的邏輯交給執行緒非同步執行,這樣改造之後,讓介面效能瞬間提升了。
但在直播app原始碼中使用執行緒池有個小問題就是:如果伺服器重啟了,或者是需要被執行的功能出現異常了,無法重試,會丟資料。
那麼這個問題該怎麼辦呢?
2、mq
使用mq改造之後,介面邏輯如下:
對於發站內通知和使用者操作日誌功能,在介面中並沒真正實現,它只傳送了mq訊息到mq伺服器。然後由mq消費者消費訊息時,才真正的執行這兩個功能。
這樣改造之後,直播app原始碼的介面效能同樣提升了,因為傳送mq訊息速度是很快的,我們只需關注業務操作的程式碼即可。
二、分頁處理
有時候我會呼叫某個介面批量查詢資料,比如:通過使用者id批量查詢出使用者資訊,然後給這些使用者送積分。
但如果你一次性查詢的使用者數量太多了,比如一次查詢2000個使用者的資料。引數中傳入了2000個使用者的id,遠端呼叫介面,會發現該使用者查詢介面經常超時。
呼叫程式碼如下:
List<User> users = remoteCallUser(ids);
眾所周知,直播app原始碼的呼叫介面從資料庫獲取資料,是需要經過網路傳輸的。如果資料量太大,無論是獲取資料的速度,還是網路傳輸受限於頻寬,都會導致耗時時間比較長。
那麼,這種情況要如何優化呢?
答:分頁處理。
將一次獲取所有的資料的請求,改成分多次獲取,每次只獲取一部分使用者的資料,最後進行合併和彙總。
其實,處理這個問題,要分為兩種場景:同步呼叫 和 非同步呼叫。
1、同步呼叫
如果在job中需要獲取2000個使用者的資訊,它要求只要能正確獲取到資料就好,對獲取資料的總耗時要求不太高。
但對每一次遠端介面呼叫的耗時有要求,不能大於500ms,不然會有郵件預警。
這時,我們可以同步分頁呼叫批量查詢使用者資訊介面。
具體示例程式碼如下:
List<List<Long>> allIds = Lists.partition(ids,200); for(List<Long> batchIds:allIds) { List<User> users = remoteCallUser(batchIds); }
程式碼中我用的google的guava工具中的Lists.partition方法,用它來做分頁簡直太好用了,不然要巴拉巴拉寫一大堆分頁的程式碼。
2、非同步呼叫
如果是在直播app原始碼的某個介面中需要獲取2000個使用者的資訊,它考慮的就需要更多一些。
除了需要考慮遠端呼叫介面的耗時之外,還需要考慮該介面本身的總耗時,也不能超時500ms。
這時候用上面的同步分頁請求遠端介面,肯定是行不通的。
那麼,只能使用非同步呼叫了。
程式碼如下:
List<List<Long>> allIds = Lists.partition(ids,200); final List<User> result = Lists.newArrayList(); allIds.stream().forEach((batchIds) -> { CompletableFuture.supplyAsync(() -> { result.addAll(remoteCallUser(batchIds)); return Boolean.TRUE; }, executor); })
使用CompletableFuture類,多個執行緒非同步呼叫遠端介面,最後彙總結果統一返回。
三、加快取
解決直播app原始碼的介面效能問題,加快取是一個非常高效的方法。
但不能為了快取而快取,還是要看具體的業務場景。畢竟加了快取,會導致介面的複雜度增加,它會帶來資料不一致問題。
在直播app原始碼有些併發量比較低的場景中,比如使用者下單,可以不用加快取。
還有些場景,比如在商城首頁顯示商品分類的地方,假設這裡的分類是呼叫介面獲取到的資料,但頁面暫時沒有做靜態化。
如果查詢分類樹的介面沒有使用快取,而直接從資料庫查詢資料,效能會非常差。
那麼如何使用快取呢?
1、redis快取
通常情況下,我們使用最多的快取可能是:redis和memcached。
但對於java應用來說,絕大多數都是使用的redis,所以接下來我們以redis為例。
由於在關係型資料庫,比如:mysql中,選單是有上下級關係的。某個四級分類是某個三級分類的子分類,這個三級分類,又是某個二級分類的子分類,而這個二級分類,又是某個一級分類的子分類。
這種儲存結構決定了,想一次性查出這個分類樹,並非是一件非常容易的事情。這就需要使用程式遞迴查詢了,如果分類多的話,這個遞迴是比較耗時的。
所以,如果每次都直接從資料庫中查詢分類樹的資料,是一個非常耗時的操作。
這時直播app原始碼可以使用快取,大部分情況,介面都直接從快取中獲取資料。操作redis可以使用成熟的框架,比如:jedis和redisson等。
用jedis虛擬碼如下:
String json = jedis.get(key); if(StringUtils.isNotEmpty(json)) { CategoryTree categoryTree = JsonUtil.toObject(json); return categoryTree; } return queryCategoryTreeFromDb();
先從redis中根據某個key查詢是否有選單資料,如果有則轉換成物件,直接返回。如果redis中沒有查到選單資料,則再從資料庫中查詢選單資料,有則返回。
此外,我們還需要有個job每隔一段時間,從資料庫中查詢選單資料,更新到redis當中,這樣以後每次都能直接從redis中獲取選單的資料,而無需訪問資料庫了。
這樣改造之後,能快速的提升直播app原始碼效能。
但這樣做效能提升不是最佳的,還有其他的方案,我們一起看看下面的內容。
2、二級快取
上面的方案是基於redis快取的,雖說redis訪問速度很快。但畢竟是一個遠端呼叫,而且選單樹的資料很多,在網路傳輸的過程中,是有些耗時的。
有沒有辦法,不經過請求遠端,就能直接獲取到資料呢?
答:使用二級快取,即基於記憶體的快取。
除了自己手寫的記憶體快取之後,目前使用比較多的記憶體快取框架有:guava、Ehcache、caffine等。
我們在這裡以caffeine為例,它是spring官方推薦的。
第一步,引入caffeine的相關jar包
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <dependency> <groupId>com.github.ben-manes.caffeine</groupId> <artifactId>caffeine</artifactId> <version>2.6.0</version> </dependency>
第二步,配置CacheManager,開啟EnableCaching
@Configuration @EnableCaching public class CacheConfig { @Bean public CacheManager cacheManager(){ CaffeineCacheManager cacheManager = new CaffeineCacheManager(); //Caffeine配置 Caffeine<Object, Object> caffeine = Caffeine.newBuilder() //最後一次寫入後經過固定時間過期 .expireAfterWrite(10, TimeUnit.SECONDS) //快取的最大條數 .maximumSize(1000); cacheManager.setCaffeine(caffeine); return cacheManager; } }
第三步,使用Cacheable註解獲取資料
@Service public class CategoryService { @Cacheable(value = "category", key = "#categoryKey") public CategoryModel getCategory(String categoryKey) { String json = jedis.get(categoryKey); if(StringUtils.isNotEmpty(json)) { CategoryTree categoryTree = JsonUtil.toObject(json); return categoryTree; } return queryCategoryTreeFromDb(); } }
呼叫categoryService.getCategory()方法時,先從caffine快取中獲取資料,如果能夠獲取到資料,則直接返回該資料,不進入方法體。
直播app原始碼如果不能獲取到資料,則再從redis中查一次資料。如果查詢到了,則返回資料,並且放入caffine中。
如果還是沒有查到資料,則直接從資料庫中獲取到資料,然後放到caffine快取中。
具體流程圖如下:
該方案的效能更好,但有個缺點就是,如果資料更新了,不能及時重新整理快取。此外,如果有多臺伺服器節點,可能存在各個節點上資料不一樣的情況。
由此可見,二級快取給直播app原始碼帶來效能提升的同時,也帶來了資料不一致的問題。使用二級快取一定要結合直播app原始碼實際的業務場景,並非所有的業務場景都適用。
但上面我列舉的分類場景,是適合使用二級快取的。因為它屬於使用者不敏感資料,即使出現了稍微有點資料不一致也沒有關係,使用者有可能都沒有察覺出來。
本文轉載自網路,轉載僅為分享乾貨知識,如有侵權歡迎聯絡雲豹科技進行刪除處理
原文連結:https://mp.weixin.qq.com/s/0ez_mkyr0i4MZd7DEN7M8A
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69996194/viewspace-2849102/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 婚戀app原始碼開發,如何實現介面效能優化?APP原始碼優化
- 相親交友原始碼前端效能優化,通常使用哪些手段?原始碼前端優化
- 使用 Go 優化我們的介面Go優化
- 遊戲陪玩原始碼前端效能優化,開發階段可採取的措施遊戲原始碼前端優化
- 成品app直播原始碼搭建,常用資料處理手段程式碼分析APP原始碼
- 影視APP直播盒子原始碼 第三方介面無需採集APP原始碼
- 直播帶貨app原始碼,獲取直播影片的第一幀APP原始碼
- 直播app系統原始碼,css優化滾動條樣式APP原始碼CSS優化
- 直播app原始碼,uniapp獲取當前位置APP原始碼
- petite-vue原始碼剖析-優化手段template詳解Vue原始碼優化
- app直播原始碼,Vue獲取URL圖片的寬高APP原始碼Vue
- 四點總結直播帶貨app原始碼的優劣性APP原始碼
- 如何優化我們的程式碼(vue專案)優化Vue
- 實現語音社交原始碼介面效能優化,從索引入手原始碼優化索引
- 如何實現婚戀app原始碼中直播首屏載入優化?APP原始碼優化
- mysql查詢太慢,我們如何進行效能優化?MySql優化
- API採集介面原始碼電商採集工具介面API原始碼
- 婚戀交友原始碼開發,採用連線複用實現效能優化原始碼優化
- 直播系統app原始碼,自定義可以暫停的倒數計時APP原始碼
- 手機直播軟體系統搭建原始碼,聚合採集器採集平臺介面!原始碼
- 優秀原始碼帶給我們的一些啟示原始碼
- 使用這11個程式碼,可以大大地簡化我們的程式碼。
- 陪玩原始碼介面效能優化,需要你掌握的關於呼叫的一些事原始碼優化
- 使用APICloud開發App的效能優化探索——合理使用同步/非同步介面APICloudAPP優化非同步
- app直播原始碼,ButtonTextView的背景設定APP原始碼TextView
- 從快取角度入手實現聊天室軟體原始碼的前端效能優化快取原始碼前端優化
- 記一次介面效能優化實踐總結:優化介面效能的八個建議優化
- 直播程式開發+直播原始碼,讓我們策馬奔騰,共享人世繁華原始碼
- App瘦身、效能優化總結APP優化
- 婚戀app原始碼開發,相親直播間聊天訊息列表卡頓優化APP原始碼優化
- iOS效能優化 - APP啟動時間優化iOS優化APP
- iOS 介面效能優化淺析iOS優化
- HMS Core Insights第三期直播回顧 – 當我們在談論App的時候,我們還可以談論什麼?APP
- HMS Core Insights第三期直播預告—— 當我們在談論App的時候,我們還可以談論什麼?APP
- 做好陪玩系統原始碼的前端效能優化,提升系統效能原始碼前端優化
- android 系統原始碼挖掘之Animator效能優化Android原始碼優化
- Android 效能優化(十二)之我為什麼寫效能優化Android優化
- 當我們談優化時,我們談些什麼優化