架構師之路--應用架構的選型和dubbo


小時候總是跟媽媽着去上班。媽媽是兒科醫生。有一天來了一個媽媽帶着他的寶寶掛了媽媽的專家號。寶寶長得很可愛,但是臉上沒有任何表情,腦袋很大,四肢和剛出生的寶寶一樣大。媽媽抬起寶寶的四肢,一放手它又耷拉回去。媽媽說話聲音很沉重,說我直接給你開個證明吧,你可以再要一個孩子。那個媽媽一句話都沒說,只是坐在那里抱着她的寶寶。這個媽媽在化工廠工作,天天和染料打交道。這已經不是她的第一個寶寶了,每個寶寶命運都差不多。這個媽媽的絕望和醫學無關。所以高考的時候,怎么都不肯聽媽媽的。自己報了計算機。媽媽知道后讓我去找老師改回來。我走到半路給媽媽買了件衣服就回來了。媽媽雖然還是很想讓我學醫,但是看到我買的衣服顯然很高興,也明白她是拗不過我的,只好作罷。

這個選型主要決定於系統復雜度。先回顧一下。

 

  1>單一應用架構:對於一個流量很小的網站來說,只需一個應用,將所有功能都部署在一起,以減少部署節點和成本。之前在上家公司做過一個微信公眾號的開發就是基於這種架構,我和一個大牛的前端架構師兩個人就是一個項目,還是挺happy的。但是這種架構其實用java的成本有點高,用PHP更快。所以我自己接了個私活做個類似攜程+如家的網站用的就是php。

 

  2>垂直應用架構:訪問量再大一點,可以將應用拆成互不相干的幾個應用,以提升效率。8年前剛進人人網的時候用的就是這個架構。因為是社交網站,被拆分成了SNS,UGC,各個游戲等子模塊。

 

  3>分布式服務架構:垂直應用多了,交互不可避免,將核心業務抽取出來作為獨立的服務,形成穩定的服務中心。大概從11年起,人人網逐漸采用這種架構。隨之而來的是采用一些技術,記得最初也采用過RMI的,都是內部調用,防火牆也應該不是問題。但是后來hession和thrift開始流行,我們又進行了這方面的嘗試。zookeeper用作注冊中心,主要是配置管理方面。

 

  4>流動計算架構:當服務越來越多,容量的評估,小服務資源的浪費等問題逐漸顯現,此時需要增加一個調度中心基於訪問壓力實時管理集群容量,資源調度和提高集群利用率。

 

  Dubbo是Alibaba開源的分布式服務框架,按照分層來架構,使各個層之間解耦合。在我們項目中,作為服務層和業務層的橋梁來使用。Dubbo層可以用servlet容器啟動,也可以直接用main函數直接加載ApplicationContext。總之,dubbo是依賴於spring來管理的。Dubbo框架設計共划分了10層。其中服務接口層,配置層,服務代理層是開發需要自行寫入的,用法自行百度。

 

下面說一下服務注冊層。它以服務URL為中心,擴展接口為RegistryFactory,Registry和RegistryService。打開RegistryFactory的源碼可以看到,這是一個SPI的,核心工作就是取得其注冊的信息。內部實現類是DubboRegistryFactory。作用就是根據url從一個本地的concurrenthashmap中取出其注冊信息,如果注冊信息不存在,則創建一個。同時將此注冊目錄加入集群。這種concurrenthashmap的東西要返回視圖,返回的一般都是一個unmodify的拷貝。Dubbo里為了減少對apache的依賴,用的是java.util里的Collections.unmodifiableCollection。

集群層。這一層是上面提到的流動架構的體現。封裝多個提供者的路由及負載均衡,並橋接注冊中心,以Invoker為中心,擴展接口為Cluster,Directory,Router和LoadBalance。從SPI的配置文件來看,支持4種常用的負載均衡

random=com.alibaba.dubbo.rpc.cluster.loadbalance.RandomLoadBalance

roundrobin=com.alibaba.dubbo.rpc.cluster.loadbalance.RoundRobinLoadBalance

leastactive=com.alibaba.dubbo.rpc.cluster.loadbalance.LeastActiveLoadBalance

consistenthash=com.alibaba.dubbo.rpc.cluster.loadbalance.ConsistentHashLoadBalance

具體類里基本都是算法的實現,可以不用看了。Cluster支持的算法如下:

mock=com.alibaba.dubbo.rpc.cluster.support.wrapper.MockClusterWrapper

failover=com.alibaba.dubbo.rpc.cluster.support.FailoverCluster

failfast=com.alibaba.dubbo.rpc.cluster.support.FailfastCluster

failsafe=com.alibaba.dubbo.rpc.cluster.support.FailsafeCluster

failback=com.alibaba.dubbo.rpc.cluster.support.FailbackCluster

forking=com.alibaba.dubbo.rpc.cluster.support.ForkingCluster

available=com.alibaba.dubbo.rpc.cluster.support.AvailableCluster

mergeable=com.alibaba.dubbo.rpc.cluster.support.MergeableCluster

broadcast=com.alibaba.dubbo.rpc.cluster.support.BroadcastCluster

監控層:RPC調用次數和調用時間監控,以Statistics為中心,擴展接口為MonitorFactory, Monitor和MonitorService。實現上和注冊層的實現是一樣的。

遠程調用層:封裝RPC調用,以Invocation和Result為中心,擴展接口為Protocol,Invoker和Exporter。Protocal是服務域,它是Invoker暴露和引用的主功能入口,負責Invoker的生命周期管理。Invoker是實體域,它是Dubbo的核心模型,其他模型轉換成它。它代表一個可執行體,可向它發起invoker調用,它有可能是一個本地實現,也可能是一個遠程的實現,也可能是一個集群實現。相信了解過java動態代理的話,這個不難理解。

信息交換層:封裝請求響應模式,同步轉異步,以Request和Response為中心,擴展接口為Exchanger,ExchangeChannel,ExchangeClient和ExchangeServer。

網絡傳輸層:抽象mina和netty為統一接口,以Message為中心,擴展接口為Channel,Transporter,Client,Server和Codec。

數據序列化層:可復用的一些工具,擴展接口為Serialization,ObjectInput,ObjectOutput和ThreadPool。

 可以以dubbo配置項的解析為入口跟進源碼。在dubbo jar包下META-INF里面的spring.handlers里,有自定義的spring命名空間處理器,可以找到對應的java類。dubbo的引入不可避免的帶來IO,像咱們寫代碼的,這兒壓縮幾個字節,那兒解開一個循環,這些代碼優化可能輕易就被低效的IO所抵消。IO操作比在內存中進行數據處理所需的時間一般長20倍。前段時間用CAT做性能監控就發現,如果沒有dubbo層大概幾ms的操作,引入dubbo執行時間正常都在幾百ms。所以SOA要謹慎。要懂一些底層原理的話,其實架構的選擇就能少些糾結,看各種框架也能馬上就明白。網友問我在讀什么書,其實現在很少有時間讀,開放平台項目進入聯調階段了,還有很多細節可以優化的地方,還是挺忙的。之所以看到我的文章亂序嚴重也是因為我是用特別零散的時間來寫的。但是前段時間不是看了<netty in action>嘛,看這本書就不得不再看看<java nio>做一下對比,看了<java nio>呢,里面作者又推薦讀一下《操作系統第六版》,話說我大學也是計算機的,但是這本書還是需要重新看一遍的。每本書作者都會引入一些相關的好書,所以我的書單永遠空不了。

 

  dubbo底層不管是用mina也好,netty也好,IO原理都是一樣的。比如和底層相關的,之前我也提到我曾經自己分析過圖片的二進制流來獲取圖片翻轉信息。在這個過程中我了解到和底層操作系統相關的兩個標准,Intel標准和摩托羅拉標准。分別對應兩種字節順序:大端字節順序和小端字節順序。了解這個對於nio的緩沖區也有幫助。而通道不是分為單工,雙工,半雙工嘛。面向流的socket肯定是雙工的,所以流在網絡中請求和響應的讀寫操作才可以同時進行。而像文件IO這樣的,讀寫肯定是分離的,單工進行的。

 

上周有人問我我們的項目使用緩存和數據庫就能解決問題,為啥要開發一個搜索引擎,考慮問題的角度不是應該放在數據分析上嗎?我表示同意他的觀點,因為我自己沒組織好語言說服不了人家的時候我都是這個態度。實際上,首先說我們已經分析出來了,瓶頸就在緩存上了。緩存采用memcached也是緩存,redis也是緩存。實際上solr也是緩存啊!這種緩存是基於多維數據結構的獲取,合適我們的項目也合適很多列表帶維度的項目。我認為以后是很有前景的。而solr或者說es或者說dubbo或者memcached或者redis面臨的問題都是一樣的,性能嘛,而性能最大的消耗點就是io。我們項目用的dubbo+緩存。是兩次跨網絡的io。dubbo解決的是服務復用的問題,緩存解決的是空間換時間的問題,搜索引擎可以做為一個獨立的服務一次io同時解決這兩個問題,我為啥讓人家明白不了呢


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM