成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

你的解耦戰術,決定了架構高度!

開發 架構
什么是耦合?就是每每我們作為技術人,在心中罵上下游、罵兄弟部門,說這個東西跟我有什么關系?為什么我要配合來做這個事情?這里面就非常有可能是系統中存在耦合的地方。

 架構設計中,大家都不喜歡耦合,但有哪些典型的耦合是我們系統架構設計中經常出現的,又該如何優化?

[[210027]]

這里列舉了 6 個點:IP、jar 包、數據庫、服務、消息、擴容。

這些點,如果設計不慎,都會導致系統出現一些耦合問題,基本都是大家實際遇到的痛點。本文將與大家分享如何用常見的方案去解除這些耦合。

如何找到系統中的耦合

什么是耦合?就是每每我們作為技術人,在心中罵上下游、罵兄弟部門,說這個東西跟我有什么關系?為什么我要配合來做這個事情?這里面就非常有可能是系統中存在耦合的地方。

明明我們不應該聯動,但兄弟部門要做一個事情,上下游要做一個事情,我卻要被動地配合來做這個事情。還有可能這個配合的范圍特別特別的大,那就說明耦合非常非常的重。

下面來看具體的六個案例。

典型耦合與對應解耦實踐

IP 耦合


 

第一個案例,特別常見。原來線上有服務或者有條數據庫,因為各種原因,例如磁盤硬件有故障,要換一臺機器,然后運維給了我們一臺機器,我們把數據庫或者把服務給部署好了。

部署好了 IP 要換,原來有個舊 IP,現在有個新 IP。那就有很多上游依賴我,我 IP 換了怎么辦?就找到上游說我的 IP 換了,麻煩上游部門改配置重啟一下,連到我新的 IP 上去。

不知道大家工作中會不會遇到這樣的場景,這時如果你作為上游的調用方,不管你調數據庫還是調服務,你心里可能就在罵他了,明明是你 IP 變了,為什么配合重啟、配合改配置的人是我?

特別是如果一個基礎服務或者一個基礎數據庫,依賴它的人很多,那么你可能要找到這些依賴它的人,可能有 A 部門、B 部門、C 部門,所有業務都依賴你,你要全部找一遍,全部重啟。

所以這個因為 IP 配置使得上下游耦合在一起的案例,它的耦合范圍其實是非常廣的,我們都覺得很討厭。

我們的希望是:你改一個 IP,能不能我不動,你自己升級了,我流量就默默遷移過去,這是一個非常直觀的理解上下游的耦合。

內網 IP 修改為內網域名,這是我們的實踐,強烈的建議大家回去馬上干這個事情。為什么我們 IP 要修改、要重啟?

很有可能是我們將 IP 寫在了自己的配置文件中。如果我們把這個內網 IP 變為內網域名,那么我們是不是就可以不讓上游配合去改配置重啟呢?

假設我們現在不用 IP 了,用域名了。現在換了一臺機器域名沒變,IP 指向變了。我們可以讓運維統一將內網 DNS 切到新的機器上面去,并將舊機器的連接切斷,重連后就會自動連到新機器上去了。

這樣的話只要運維配合就可以完成遷移,對于所有上游的調用方、服務的調用方、數據的調用方都不需要動,這是第一個案例。

我們的最佳實踐是強烈建議使用內網域名來替換內網的 IP,連服務、連數據庫統統取走。

公共庫耦合

第二個案例是公共庫,這個公共庫可能是一個跟業務相關的通用業務庫,比如用戶的業務、支付的業務,這些業務寫在了一個 jar 包里,各個業務線通過這個 jar 包來實現相關的一些業務邏輯。

所有的業務方因為這個公共庫耦合了,不管你是 so、dll,還是 jar 包代碼,不同語言的公共庫方式不一樣,本質是上游通過這個公共庫耦合在一起。

我們曾經碰到什么樣的情況呢?58 有招聘、房產、二手很多業務線,用戶的一些操作,登錄、查詢信息、修改信息可能都是相通的,所以我們有一個 user.jar,對所有用戶的操作可能通過這個 jar 包去做。

然后有個業務線,比如說招聘,他可能修改了用戶的操作的一些代碼,修改了這個 jar 包。

修改之后,上線之前會進行測試,但招聘只會測試自己的業務,不會測試兄弟業務線的業務,導致上線的結果是,上線后兄弟業務線全掛了。

于是就出現了一個很有意思的場景, A 和 B 的業務老大在群里面說怎么業務都掛了,然后有研發兄跳出來解釋說 C 部門上線了,所以我們都掛了,這個解釋是很難說通的。

為什么兄弟部門好好的,他上線了他沒問題,而我們掛了,就是因為 jar 包耦合在一起,可能我們也在心里會默默地罵他們,修改代碼的是你,沒問題的也是你,有問題的是我,我其實什么都沒動,我很委屈。

多個上游因為 jar 包耦合在了一起,那有什么樣的優化方法?

如果代碼庫個性很強

如果這個 jar 包、這個公共庫的個性比較強,如果是偏招聘的、房產的、二手的,我們的建議是把這些個性的代碼拆分到各個業務線自己的 jar 包里面去。

這樣的話,你修改的那一塊只影響你自己,至少不會擴大影響范圍,這個需要對業務進行剖析,把個性的地方拿出來。

如果長時間解決不了,我剛剛說的那種耦合頻發,出現的次數特別多,最差的情況下我們可以 copy 代碼,比如說拷三份,但這個不推薦。

我們的建議:還是抽取其中的個性部分,把原來的一個 business 的 jar 包變成三個加包,每一塊只跟一塊業務相關。

如果公共庫通用性很強

那如果這個庫的共性比較強,我們建議通用的部分下沉獨立一個 service,這個 service 對上游提供接口,我每次測試你也要測試接口的兼容性。

如果是新的業務,我們建議新增接口,這樣至少不會對舊有的代碼產生影響,通過 service 或 RPC 調用的方式來解除耦合。

數據庫耦合

第三個案例應該也是大家會遇到比較多的情況,數據庫的耦合。

我先說一下業務場景:業務 A、業務 B、業務 C,這里還是拿用戶的業務舉例,有些用戶的數據是通用的,存在 table-user 里,而個性的數據我們存在個性的數據庫里。

比如業務 A 我們可能有個 table-A、業務 B 有 table-B、業務 C 有 table-C。

假設我的業務線既要取個性的數據,又要取共性的數據,我們的代碼往往這么寫,個性表 join 個性表,UID 相同,UID 等于我的用戶 1、2、3,個性的數據和共性的數據一起抽取出來,沒有任何問題。

業務線 B、業務線 C 也是這么做的。所以你會發現 join 語句其實導致了 user 的 table 和業務線 A、B、C 的 table 耦合到一個數據庫實例里。

這樣會導致什么問題呢?比如 A 業務線要上線一個功能,這個功能沒有索引,對全表都要掃描,數據庫 CPU 100%,數據庫實例 IO 性能下降,影響業務。

對B 和 C 都有影響,即某個業務線的數據庫性能急劇下降導致所有業務都受影響。

這時 DBA 兄弟、運維兄弟殺過來說性能不行了,我再給你兩臺機器,給我兩個實例,你會發現沒用,所有表都耦合在一個實例里,給機器也拆不開,擴不了容。

2015 年我調去 58 到家時,當時整個 58 到家有一個庫叫做 58 到家庫,里面有幾百個表,性能越來越低,但因為各種 join 又必須耦合在一個實例里,很悲慘。

我們怎么做呢?垂直切分與服務化。你會發現跟 jar 包解耦非常相似,垂直拆分。

比如說用戶的基礎數據,我抽向一個用戶的服務,user 最基礎的數據庫只能夠被這個服務鎖訪問,數據庫私有是服務化的一個特點。

此時業務線原來的業務怎么樣滿足?原來是業務方直接一個 join 既取了共有的數據又取了私有的數據,此時原來的一次數據庫訪問變成了兩次數據庫訪問,第一次取個性數據,第二次取共性數據,然后業務層拼裝。

之前的方式和之后的方式相比,之前的方式業務代碼可能會更簡單一些,因為它是將這個業務邏輯放在了 SQL 語句中,但是導致數據庫耦合在了一起。

后面這種方式就是業務的代碼會更復雜,會變成多次訪問,將原來在 SQL 中進行的邏輯計算變成我們自己的代碼的邏輯計算。

此時業務有自己的庫,公共有公共的庫,你會發現很有可能這些庫早期也在一個實例,但是性能下降時可以很容易地新增實例,把其中一個公共的庫從一個實例里放到另外一個實例,甚至新增一臺機器做到硬件的擴容。

所以垂直切分是指業務側自己的數據庫放到自己的上去,公共的放到公共的上去,不要耦合在一個實例當中,這是一個比較典型的業務場景。

服務化耦合

第四個案例是服務化耦合的例子。服務化之后,如果業務代碼拆分得不干凈,即使你做了服務化也不能夠解除耦合。這里舉一個服務化解耦不徹底的案例。

上面是 ABC 三個業務方,底下是一個通用的服務。假如你解耦不徹底,你這個通用的服務里有業務側的代碼,最典型的業務側的代碼是什么樣的?

即服務層 switch case,根據調用方的類型走不通的業務邏輯代碼。我們做服務化其實是想把共性的部分抽象下沉,是共性的部分會做的服務。但如果解耦不徹底,就會有傳入不同 biz-type 執行不同邏輯這樣的代碼。

這會出現什么問題呢?如果新增業務需求,你會發現很有可能要改代碼的是底層的服務,比如說業務 1 來了一個需求,他過來找到你,說我這個需求有個擴展,麻煩你這邊升級一下。

業務 2 和業務 3 相同,明明有需求的是業務方,為什么修改代碼的是我底層呢,業務需求方很多,所有業務需求側都是你來實現,你是忙不過來的。這時你可能在心中罵他。

這個的耦合范圍相對較小,因為只有一個基礎服務維護的痛點。解決方案也很容易想到,當然是把業務個性化的 case 分支搬到上游去,底層只做通用的功能。

業務代碼上浮,這樣的話上游的業務迭代速度、迭代效率會提升,每塊業務有功能就會自己實現了,不需要兄弟部門去實現,沒有一個溝通的過程。這是服務化不徹底的一個常見的耦合的案例。

消息通知耦合

第五個案例是消息通知的耦合。我猜應該也有很多公司遇到過,有一些事件,這個事件可能要讓很多下游知曉,這里舉一個我們曾經出現過的案例。

58 同城發布帖子,發布帖子的這個事件可能要周知很多方,例如有一個用戶分級的服務,他發了帖之后,這個用戶發帖的一些統計數據,一些信息數據可能要進行更新。

還要通知離線消息反作弊的部門在發布這個帖子之后,可能做一些離線的分析和處理,看有沒有反作弊的嫌疑。

甚至我們這個消息可能要通知業務線,比如說招聘業務線,最近做了一些營銷活動,只要發招聘的帖子就給你獎積分。

帖子發布服務,這本來應該是一個非常基礎的服務,它是否要承擔將帖子消息同步給通知關注方的職責呢?

最早我們是怎么實現的?58 同城都是服務化的架構,通過 RPC 告訴你發布一個帖子。

所以我們的上游是帖子發布的基礎服務,他會通知反作弊的部門說發了一個帖子,會通知數據統計的部門發個帖子,會通知業務線說發個帖子,這樣的架構其實是因為這個通知上下游耦合在了一起。

然后我們在什么時候會偷偷地去罵這個下游呢?假設現在又新增了一個業務線,房產業務線也做營銷活動,也要關注帖子發布,麻煩發布的兄弟能不能調用一下我。

發布的兄弟會發現改的是發布服務的代碼,他原來要調 123,他現在還要調 4,有人有新增的需求還要調 5。發布服務的工程師很痛苦,明明有需求的是業務方,但修改代碼的卻是我。

原因就是消息的上下游耦合在一起。非常常見的解耦方案是通過 MQ,這個案例里的 MQ 以及下一個案例里的配置中心是互聯網架構中兩個非常常見的解耦工具。

MQ 能夠做到上下游物理上和邏輯上都解耦,增加 MQ 之后,首先上游互不知道彼此的存在,它當然不會建立物理連接了,大家都與 MQ 建立物理連接,就是物理連接上解耦了。

邏輯上也解耦了,消息發布方甚至不用知道哪些下游訂閱了這個消息。新增消息的訂閱方只需要找 MQ 就行了,上游不需要關注。

所以 MQ 是一個非常常見的物理上解耦、邏輯上也解耦的利器。

下游擴容耦合

第六個案例,我相信也幾乎是所有的公司都會遇到的一個案例,它和第一個案例很像,但又不一樣。

我們的第一個案例是說 IP 變化,上游調下游 IP 發生了變化,我們的建議是使用內網域名,而不是 IP 來做配置,來做上下游的連接解耦。

擴容換 IP 是一個場景,擴容又是第二個場景。

現在有 service1、service2、Web1,底層的 service 是個集群,隨著業務、數據量、并發的增長,service 要擴容了,我要新增兩個節點。

假設我要新增 IP4、IP5,你會發現案例一的場景又出現了,你得通知所有的上游麻煩幫忙增加兩 個IP,增加兩個內網域名,因為我擴容了。擴容的明明是下游,但需要修改配置、需要重啟的是上游。

我們早期的解決方案是怎么樣的?我們對配置采用的是配置私藏的方式。

一般對于每個上游來說,都有個自己的配置文件,依賴于下游,這個配置文件會放在上游的配置文件里。

service2 一般有一個配置 conf,這個里面寫了依賴于內網配置,內網域名是 123,然后這個服務在啟動時可能通過配置把這個連接建立上。

Web 也是一樣,它有一個 Web1.conf,大家想想自己所服務的公司是不是這樣的。

它是一個數據的擴散,本來數據在這一份,但是你會發現這個數據擴散到不同的上游,每個人都存儲一份這樣的數據,我這個數據要變動時每個上游都需要變動。

如果數據只存在一個地方,這一個地方變了就都變了,不用擔心數據的一致性。

如果你能夠知道上游是誰,通知你的上游去為用戶改善配置重啟還好,我們碰到的痛點是什么?

58 同城幾千號人,業務幾百個,那么多,我不知道誰依賴了我,如果我能知道 123 依賴了我,那我就告訴你就行了。

現在我不知道誰依賴了我,因為你連接我,你不需要經過我的允許,你在手冊上看調用方式是什么就看懂了。我們會增加 IP,我怎么通知你?

剛剛說根本的原因其實是一份配置數據擴散到了多個上游,那我們能不能將這個配置數據放在一個地方不擴散,我改了這一個地方就都改了?

解決方案是配置中心,配置中心的細節我在這不展開講,網上可能也有一些公司的實踐,配置后臺、DB 存儲等。

配置中心是一個典型的邏輯上解耦、但物理上不解耦的一個架構工具。我們的所有上游依賴于下游,還要建立物理的連接。

你引入配置中心之后,它不是通過私有的配置,也不是通過全局的配置文件去讀取下游的 IP,而是配置中心說我要訪問 user service。

配置中心告訴他 user service 的內網域名是 123,service 的 1、2、3 還是按照內網的 1、2、3,物理上還是連接 user service,所有的上游都按照這種方式讀取下游的配置。

在配置中心側,他就能夠知道有哪些人連接了 user service,他在配置中心的后臺就可以配哪些人我設置多少的限流,然后將這個限流可以同步到調用方的客戶端,當然也可以同步到服務端進行雙向的保護。

如果 user service 進行擴容,比如我要增加幾個節點,我增加了 4 和 5,那么我在配置后臺說增加了 4 和 5,后臺能夠知道哪些上游依賴了它,反向給后臺通知,就完全不需要上游去做了。

總結

解耦之后系統能夠更美好一點,程序員心中能夠少一點怨氣,希望今天分享的主題及案例能夠幫助大家解決一些工作中的實際問題,謝謝大家。

[[210028]]

沈劍,架構師之路公眾號作者。曾任百度高級工程師、58 同城高級架構師、58 同城技術委員會主席、58 同城 C2C 技術部負責人。現任 58 到家技術委員會主席,高級技術總監,負責 58 速運研發與管理工作。本質,技術人一枚。

 

責任編輯:武曉燕 來源: DBAplus社群
相關推薦

2020-11-20 15:22:32

架構運維技術

2018-04-18 08:47:17

Alluxio構建存儲

2017-12-26 15:52:31

MQ互聯網耦合

2022-09-02 08:23:12

軟件開發解耦架構

2025-05-20 07:13:22

Spring異步解耦Event

2018-01-01 06:41:44

耦合互聯網架構配置中心

2013-09-16 10:19:08

htmlcssJavaScript

2016-11-30 15:30:42

架構工具和方案

2021-03-10 05:50:06

IOCReact解耦組件

2024-03-08 16:27:22

領域事件DDD項目跨層解耦

2017-12-15 14:17:46

數字化轉型CIO

2015-05-22 17:31:39

寶德

2021-08-27 08:44:52

MQ架構耦合

2025-06-20 08:40:32

2023-07-07 09:08:21

2022-04-15 11:46:09

輕量系統解耦鴻蒙操作系統

2021-06-01 09:38:19

消息隊列核心系統下游系統

2019-06-20 10:23:23

架構代碼前端

2025-05-22 09:08:20

2017-10-17 12:42:47

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲免费在线 | 欧美国产在线一区 | 综合欧美亚洲 | 亚洲免费在线观看av | 日本大片在线播放 | 日韩精品 电影一区 亚洲 | 国产精品永久免费视频 | 国产色婷婷精品综合在线播放 | 一区二区三区四区在线视频 | 亚洲免费视频网站 | 亚洲一区二区三区在线视频 | www.操.com| 日韩欧美精品在线 | 日韩电影免费观看中文字幕 | 欧美日韩精品中文字幕 | 亚洲精品福利在线 | 欧美xxxx在线 | 国产精品久久一区二区三区 | 在线亚洲一区二区 | 亚洲综合色网站 | 久久免费精品 | 国产精品a久久久久 | 精品av久久久久电影 | 国外成人免费视频 | 亚洲精品1区| 毛片毛片毛片毛片 | 本道综合精品 | 中文字幕视频在线观看 | 日韩一级免费电影 | 午夜视频在线视频 | 日韩中文一区 | 国产精品明星裸体写真集 | 国产在线观看一区二区 | 日本一区二区高清视频 | 精品视频久久久久久 | 欧美群妇大交群中文字幕 | 玖玖久久 | 亚洲精品黄色 | 日韩中文字幕区 | 久草视频在线播放 | 日韩精品一区二区三区视频播放 |