日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

项目复盘思考

發(fā)布時間:2023/12/10 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 项目复盘思考 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

對自己所參與過的事物做個復盤是個好習慣,能讓自己對事物有個更深的了解。比如說,讀了一本書,那么這個時候你需要回去思考:這本書講了些啥,對你有何影響;又或者,你參與了一個活動,你完了后,你也可以對其進行復盤,思考下這個活動的意義,這個活動是讓你增加見識了還是讓你放松心情了等;再或者,你參與了一個項目,這個時候還是可以復盤,考慮項目的進展中的難點等。其實復盤,就是對自己經(jīng)歷過的事物進行思考總結(jié)。是一個很好的自我矯正升華的方式。

下面我以一個程序員參與的項目的復盤來簡要說明下,復盤過程中可能思考的問題和方向。

拋出問題

  • 為什么要做這個項目?
  • 項目是怎么選型的?
  • 項目的規(guī)模(數(shù)據(jù)量、并發(fā)量、增量)?
  • 項目中遇到了什么難點?是如何解決這些問題的?
  • 項目還有什么不足?有什么解決方案?
  • 問題解答

    這里以之前我做過的一個出單項目為例子簡單說一下可能的問題思考總結(jié)。


    為什么要做這個項目

    面對日益增加的互聯(lián)網(wǎng)合作伙伴對接平安的出單系統(tǒng),原有的系統(tǒng)已經(jīng)無法完全滿足與日俱增出單壓力。對此,針對保險單較為單一的投保,分離業(yè)務,做成一個互聯(lián)網(wǎng)出單系統(tǒng)。快速響應合作伙伴的出單需求.

    項目是怎么選型的

    SpringCloud: 成熟的為服務體系,JAVA生態(tài),成員已有springboot基礎. 公司內(nèi)部已有基于springcloud的成功案例.
    MongoDB: 簡單保單類型適合嵌套文檔形式存儲. 分布式(支持分片,可擴展), 高可用(可配置副本)
    RockMq: 在保證了可靠性的前提下,隊列特性足夠豐富,可運維程度比較高。其快速橫向擴展的能力,也能保證未來幾年我們對其性能的要求。RocketMQ基于Java語言開發(fā)

    RabbitMQ由于采用同步刷盤,其可靠性非常強(采用ACK機制),但是性能卻是這三款開源產(chǎn)品中最差的,在實際的測試中也能很輕易的得到驗證。所以RabbitMQ更適合使用在對消息可靠性要求很高,但對消息吞吐量不太敏感的場景中。這里額外提一下一個個人經(jīng)驗,我們在對開源產(chǎn)品選型時,建議大家需要了解該產(chǎn)品是基于什么協(xié)議/規(guī)范實現(xiàn)的,這樣大致就清楚了這款開源產(chǎn)品可以解決什么問題,適用于哪些場景。例如消息中間件領域的AMQP、JMS、STOMP協(xié)議,工作流領域的bpmn2.0標準。
    Kafka是由LinkedIn開發(fā)的一個分布式的消息系統(tǒng),使用Scala編寫,它以可水平擴展和高吞吐率而被廣泛使用。目前越來越多的開源分布式處理系統(tǒng)如Cloudera、Apache Storm、Spark都支持與Kafka集成。Kafka的高吞吐是其最重要的一個特點,這也帶來了一個潛在隱患在異常情況下,其消息丟失率較高。所以它比較適用于將高吞吐作為首要考慮,能容忍少量消息丟失的場景。例如作為大數(shù)據(jù)平臺數(shù)據(jù)傳輸?shù)牧魇焦艿?#xff0c;其在日志采集場景中也被廣泛應用。
    RocketMQ的核心架構(gòu)設計參考了Kafka,有網(wǎng)友甚至提出它是Kafka Java版本的實現(xiàn)。不可否認的是RocketMQ的設計實現(xiàn)的確參考了很多Kafka的設計思想,比如說均采用了基于文件的存儲方案、Topic的并行化操作、底層網(wǎng)絡協(xié)議均基于TCP (RocketMQ使用netty成熟的解決方案,Kafka使用一套自行設計的基于TCP層的協(xié)議),但兩者之間相對特點還是比較明顯,RocketMQ在犧牲了部分性能的前提下,提供了更多的機制來保證消息的可靠性,同時也提供了更為豐富和實用的消息隊列特性。比如說消息的查詢、消息的回溯。這些接口的提供,極大的便利了消息中間件的運維,提高了在一些異常場景中的故障恢復速度。
    最終選擇了RocketMQ,理由是RocketMQ在保證了可靠性的前提下,隊列特性足夠豐富,可運維程度比較高。其快速橫向擴展的能力,也能保證未來幾年我們對其性能的要求。另外RocketMQ基于Java語言開發(fā),也降低了我們后續(xù)對其進行擴展和二次開發(fā)的難度。

    項目的規(guī)模(數(shù)據(jù)量、并發(fā)量、增量等)

    1wQPS, 每日單量60w、目前已有6000w單量.
    還有比如說項目部署的規(guī)模等情況(eg. 服務器多少臺,緩存服務,消息中間件等是如何部署的)

    項目中遇到了什么難點?是如何解決這些問題的

    壓測監(jiān)控查看各方面的系統(tǒng)資源并未達到瓶頸,但是并發(fā)量達不到預期

    問題解決和排查思路: 老一套方案,首先定位性能瓶頸: CPU/內(nèi)存/IO等

  • ps aux | grep appname 查看進程ID

  • top -H pid查看cpu和內(nèi)存的使用情況(未發(fā)現(xiàn)應用服務器的cpu和內(nèi)存有較高的使用率)
    cpu繁忙一般可能的情況如下:

    • 線程中的不合理循環(huán)
    • 發(fā)生了頻繁的full gc
    • 多線程的上下文頻繁切換
  • 通過jmap/jstack命令查看內(nèi)存/線程信息(可能是線程出現(xiàn)等待導致,所以也需要查看線程信息)

  • 通過Arthas工具查看接口執(zhí)行過程中每個方法的耗時情況

    $trace xxx #cost
    方法內(nèi)部調(diào)用路徑,并輸出方法路徑上的每個節(jié)點上耗時, trace 命令能主動搜索 class-pattern/method-pattern 對應的方法調(diào)用路徑,渲染和統(tǒng)計整個調(diào)用鏈路上的所有性能開銷和追蹤調(diào)用鏈路。trace 能方便的幫助你定位和發(fā)現(xiàn)因 RT 高而導致的性能問題缺陷,但其每次只能跟蹤一級方法的調(diào)用鏈路

    結(jié)果如下(包名經(jīng)過處理):

    +---[0.001162ms] com.xxx.service.dto.ApplyResultDTO:setApplyPolicyNo()+---[0.511972ms] com.xxx.service.apply.save.ApplySaveService:fillApplyPolicyNo()+---[19.709352ms] com.xxx.service.apply.save.ApplySaveService:saveContractDTOInfo()+---[1.313593ms] com.xxx.service.apply.save.ApplySaveService:saveApplyParameterInfo()+---[min=4.35E-4ms,max=9.48E-4ms,total=0.002326ms,count=3] java.lang.StringBuilder:<init>()+---[min=5.1E-4ms,max=0.00146ms,total=0.004705ms,count=6] java.lang.StringBuilder:append()+---[0.001361ms] com.xxx.base.dto.BaseInfoDTO:getTransactionNo()+---[min=4.86E-4ms,max=6.61E-4ms,total=0.001777ms,count=3] java.lang.StringBuilder:toString()+---[523.544075ms] com.xxx.common.service.redis.RedisService:stringSet()+---[9.91E-4ms] com.xxx.common.util.StringUtils:isNotBlank()+---[min=6.07E-4ms,max=7.75E-4ms,total=0.001382ms,count=2] java.lang.String:equals()+---[min=5.03E-4ms,max=6.95E-4ms,total=0.001198ms,count=2] java.lang.Integer:intValue()+---[min=592.763104ms,max=868.853641ms,total=1461.616745ms,count=2] com.xxx.common.service.redis.RedisService:ObjectSet()
  • 通過trace 定位到是redis耗時后,定位redis問題

  • 查看redis服務器狀態(tài),發(fā)現(xiàn)壓測時有臺服務器的 查看redis服務器狀態(tài),發(fā)現(xiàn)壓測時有臺服務器的CPU達到70%左右
  • slowlog get 命令獲取redis慢查詢定位到是某個key的讀取導致, 到此發(fā)現(xiàn)是redis數(shù)據(jù)的熱點問題
  • 解決方案

  • 出現(xiàn)該問題是有工具類濫用redis的問題,每次獲取數(shù)據(jù)都從redis獲取。首先,調(diào)整代碼,增加內(nèi)存緩存。redis緩存刷新時發(fā)布事件動態(tài)刷新內(nèi)存緩存; 然后,優(yōu)化存儲的dto,只緩存必要的數(shù)據(jù)。減小數(shù)據(jù)量;最后,替換序列化工具,將jackson序列化替換為fastjson.
  • 流程中部分耗時的IO操作線程異步后臺處理
  • 項目還有什么不足?有什么解決方案?

  • 缺少網(wǎng)關限流

    spring-cloud-zuul-ratelimit、 針對不同合作伙伴分別限流

  • 使用了較多的內(nèi)存緩存,這些緩存通常無需改變

    調(diào)整jvm參數(shù),如增加老年代比例。減少gc耗時停頓時間

  • 使用緩存時沒考慮并發(fā)問題導致的數(shù)據(jù)不一致性

    目前使用緩存的時候,策略是先刪除緩存后更新數(shù)據(jù)庫的,在并發(fā)情況下,可能會導致緩存和數(shù)據(jù)庫的數(shù)據(jù)不一致,該問題需要解決。目前考慮的解決方案有如下幾種:

    • 在寫數(shù)據(jù)庫操作的時候。利用Redis加鎖,使得數(shù)據(jù)更新完成之后才能讀緩存
    • 寫數(shù)據(jù)庫后,啟動一個延遲定時任務,定時任務負責讀取數(shù)據(jù)庫的最新數(shù)據(jù)更新Redis中的緩存
    • Redis讀寫請求入隊列,根據(jù)請求類型決定是否需要阻塞等待,以保證數(shù)據(jù)的一致性

  • 總結(jié)

    上面只是給了一個例子,還有更多的思考點等著自己去發(fā)掘。再者每個人的經(jīng)歷也不一樣,思考方向也許也會有更多的不同,但是最重要的是一個保持思考總結(jié)的習慣,該習慣并不是一定要等事情完結(jié)后才去考慮,在過程中我們也需要不斷的思考總結(jié)。
    人會在思考總結(jié)中進步,如果只是走馬觀花一般,那就真的像網(wǎng)上傳的一樣(十年工作經(jīng)驗,其實就是一年的工作經(jīng)驗重復可十年)。希望大家不是活成了段子,而是在不斷的進步,看到越來越好的自己。

    總結(jié)

    以上是生活随笔為你收集整理的项目复盘思考的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。