微服務架構成了當下的技術熱點,實現微服務是要付出很大成本的,但也許是因爲微服務的優點太過於吸引人,以至於大部分開發者都將它當成未來的發展趨勢。
微服務架構的演進過程
dubbo的用戶手冊中介紹了服務化架構的進化過程,如下圖:
圖一、服務化架構的演進過程
一個高內聚版本,所有功能部署在一起。數據訪問框架(orm)成爲關鍵。這個架構很少被人使用,幾乎接近滅絕了吧。
優點:成本低,適合功能少又簡單 缺點:很多,比如無法適應高流量,二次開發難,部署成本高
2.mvc架構 - 垂直應用架構
當訪問量漸漸增大,慢慢演化成用的很多的mvc架構。雖然還是所有的功能都是部署在同一個進程中,但是可以通過雙機或者前置負載均衡來實現負載分流。這樣應用也可以拆分成不同的幾個應用,以提升性能和效率。
此時,mvc架構用於分離前後端邏輯。一方面,有一定的模塊化。另一方面,加速和方便了開發。
3.rpc架構 - 分佈式服務架構
當mvc垂直應用分成不同應用時,越來越多的情況下。不可避免的事應用a與應用b之間的交互。此時將核心和公共的 業務功能抽出來,作爲單獨的服務,並實現前後端邏輯分離。
此時則就需要提高業務的複用及整合的分佈式rpc框架,例如dubbo等。
4.soa架構 - 流動計算架構
當rpc架構中的服務越來越多時,服務的生命週期的管控,容量的評估等各種問題會出現,使服務化成爲瓶頸。需要增加一個調度中心來進行對服務管控,監督等。
微服務的技術關注點
要實現一個微服務的架構,我們需要關注的技術點包括:服務註冊、發現、負載均衡和健康檢查,前端路由(網關),容錯,服務框架的選擇,動態配置管理等模塊。這些模塊可以組成一個簡化的微服務架構圖如下:
圖二、簡化的微服務架構圖
筆者使用螞蟻金融雲有一年的時間,螞蟻金服通過螞蟻金融雲輸出了積累多年的技術組件。給其他企業的服務化體系和框架建設提供了很好的設計思路。除了微服務所需要的基礎組件之外,還提供了分佈式消息組件,分庫分表組件,分佈式調度組件等企業開發常用的中間件。根據螞蟻金融雲的設計思路,一個網站的基礎組件架構圖如下:
圖三、網站的基礎組件架構圖
可惜螞蟻金融雲中的產品並不是開源的,一個企業想擁有屬於自己的網站架構,就要選出最適合的開源的服務框架實現這些組件,從而使後續開發者更關注於業務邏輯實現。
這些組件的實現方式以後有時間的話會一一講解,這篇文章接下來先介紹一下dubbo+zookeeper來實現微服務中的前端服務、後端通用服務、服務註冊中心中所涉及到的功能。
使用dubbo+zookeeper實現簡化的微服務架構
dubbo是一個分佈式服務框架,是阿里巴巴SOA服務化治理方案的核心框架。zookeeper是一個爲分佈式應用提供一致性服務的軟件,提供的功能包括:配置維護、域名服務、分佈式同步、組服務等。zookeeper可以作爲dubbo服務的註冊中心,兩者結合起來可以實現微服務中的 服務註冊、發現、負載均衡和健康檢查,容錯,動態配置管理的功能。由於dubbo沒有提供前端路由的功能,所以我們還需實現一個具備監控、安全認證、限流、服務反向路由功能的網關組件才能實現完整的微服務。這個組件實現起來比較複雜,在這篇文章中不做介紹,我們先用springMVC將dubbo服務暴露成瀏覽器可訪問的http接口。
第一步:zookeeper集羣的部署
使用zookeeper作爲dubbo的註冊中心,部署起來並不麻煩。爲了保持註冊中心的高可用性,在生產環境下我們需要配置多個zookeeper協同運行。在集羣模式下,zookeeper會基於Paxos算法從集羣中選擇一臺作爲leader,其他機器作爲follower,註冊中心的數據都以leader爲準。一臺zk機器成爲leader的條件是超過這臺機器是可用的,且被超過半數的機器選舉爲leader。基於這種實現方式,我們選擇zk集羣的數量時最好爲奇數個,最少爲3個,這樣只要有超過半數的zk機器存活那註冊中心就是可用的。
注:如果我們選擇2臺機器作爲zk的集羣,那只要有一臺zk掛掉,另一臺機器就無法得到超過半數的選票,那麼這個zk集羣就直接失效了。因此選2臺機器作爲zk集羣的穩定性在理論上不如一臺機器作爲註冊中心的穩定性。
以3臺機器作爲zk集羣爲例,每臺zk的具體部署方式爲:
1、下載安裝包並解壓到安裝目錄,zookeeper安裝包的下載地址爲:http://www.apache.org/dist/zookeeper/
2、進入解壓目錄的conf文件夾,配置zookeeper啓動的基本參數。
在conf文件夾下有一個 zoo_sample.cfg的文件,是zk啓動的配置樣例,zookeeper進程在啓動的時候會找zoo.cfg文件作爲默認的配置文件,所以我們複製一個名稱爲zoo.cfg的文件,並編輯其中的配置信息如下:
圖四、zookeeper的配置文件
圖中用紅框標出來的地方是zk啓動需要額外注意的參數:
dataDir爲內存數據庫快照的存放位置,
clientPort 爲zk進程的監聽端口
server.A=B:C:D
A爲數字,標識這條配置爲第幾個zk服務器,即機器id
B爲host名,標識這個服務器的主機地址
C和D爲zk集羣的成員用於選舉leader時的通訊端口
3、在dataDir路徑下創建myid文件,標識這臺機器對應的機器id
4、運行zookeeper進程,在zookeeper目錄下的bin文件夾中,運行
./zkServer.sh start
ps: 停止方法——運行 ./zkServer.sh stop
5、服務驗證
zk進程啓動後,默認會從三臺機器中選出一個leader,2個follower,在bin目錄下運行./zkServer.sh status可以查看zk進程的運行狀態
圖五、三臺機器zookeeper的運行狀態
如圖所示,集羣選擇zoo2作爲leader,其他機器作爲 follower 的方式運行。
第二步:開發前端服務和後端通用服務
第二步需要創建兩個項目:
我們使用springMVC模塊代替一下服務前端路由,與前端服務合成一個項目,作爲服務的調用者。
開發一個後端通用服務接口,作爲服務的提供者。
如果開發者是用maven做的項目管理,給大家推薦一個十分實用的多模塊項目結構,模塊的分層和依賴關係如下:
圖六:項目模塊劃分
如果項目的數據層操作比較複雜,可以在DAO層前面加一個領域層,模塊依賴關係如下:
圖七:項目模塊劃分(帶領域層)
按照圖中的maven模塊結構,我們生成服務提供方和服務調用方兩個項目,如圖:
圖八、服務提供方項目結構
圖九、服務調用方項目結構
我們將服務提供方命名爲dubboservice,服務調用方命名爲dubboclient。
首先在dubboservice項目中實現一個簡單的Hello World 服務。
1、接口:
- public interface TestService {
- String sayHello(String name);
- }
2、實現類:
- "testService")(
- public class TestServiceImpl implements TestService {
- public String sayHello(String name) {
- return String.format("Hi! Client_%s! ", name);
- }
- }
3、然後在dubboservice中引入dubbo,zookeeper所用的依賴,座標如下:
- <dependency>
- <groupId>com.alibaba</groupId>
- <artifactId>dubbo</artifactId>
- <version>2.5.3</version>
- </dependency>
- <dependency>
- <groupId>org.apache.zookeeper</groupId>
- <artifactId>zookeeper</artifactId>
- <version>3.4.5</version>
- </dependency>
- <dependency>
- <groupId>com.github.sgroschupf</groupId>
- <artifactId>zkclient</artifactId>
- <version>0.1</version>
- </dependency>
4、將Hello World服務在spring的配置文件中暴露出來,如圖:
- "1.0" encoding="UTF-8" xml version=
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
- xmlns:tx="http://www.springframework.org/schema/tx" xmlns:task="http://www.springframework.org/schema/task"
- xsi:schemaLocation="
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
- http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
- http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd
- http://code.alibabatech.com/schema/dubbo
- http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
- <context:property-placeholder location="classpath:/META-INF/app.properties" />
- <!--提供方應用信息,用於計算依賴關係-->
- <dubbo:application name="dubboservice_provider" />
- <!--使用zookeeper註冊中心暴露服務地址-->
- <dubbo:registry protocol="zookeeper" address="10.139.99.231:2181,10.139.106.145:2181,10.139.103.116:2181"/>
- <!--聲明需要暴露的服務接口-->
- <dubbo:service interface="org.zhdd.test.dubboservice.service.TestService" ref="testService"/>
- </beans>
5、將dubboservice項目啓動,我們便向註冊中心提供了一個簡易的後端通用服務。
然後在dubboclient項目中實現對後端服務的引用,和對外的路由
1、除了在dubboclient中引入dubbo,zookeeper所用的依賴之外,我們還需要引入dubboservice中所用到的服務依賴,如下:
- <dependency>
- <groupId>com.alibaba</groupId>
- <artifactId>dubbo</artifactId>
- <version>2.5.3</version>
- </dependency>
- <dependency>
- <groupId>org.apache.zookeeper</groupId>
- <artifactId>zookeeper</artifactId>
- <version>3.4.5</version>
- </dependency>
- <dependency>
- <groupId>com.github.sgroschupf</groupId>
- <artifactId>zkclient</artifactId>
- <version>0.1</version>
- </dependency>
- <!--
- 服務提供方的接口依賴
- -->
- <dependency>
- <groupId>org.zhdd.test</groupId>
- <artifactId>dubboservice-service</artifactId>
- <version>1.0.0-SNAPSHOT</version>
- </dependency>
2、在spring的配置文件中聲明所引用的服務:
- <!--提供方應用信息,用於計算依賴關係-->
- <dubbo:application name="dubboservice_consumer" />
- <!--使用zookeeper註冊中心暴露服務地址-->
- <dubbo:registry protocol="zookeeper" address="10.139.99.231:2181,10.139.106.145:2181,10.139.103.116:2181"/>
- <!--聲明需要暴露的服務接口-->
- <dubbo:reference interface="org.zhdd.test.dubboservice.service.TestService" id="testService"/>
3、新建一個controller,將引用的服務通過controller暴露出去,代碼如下:
- public class HelloController {
- private TestService testService;
- "/hello/{name}")(
- public String hello(@PathVariable String name){
- String rslt=testService.sayHello(name);
- return rslt;
- }
- }
我們可以通過zookeeper的查看工具更直觀的查看dubbo在zookeeper中的註冊和訂閱信息,此時的註冊和訂閱信息如下:
後續:
dubbo與zookeeper的複雜配置還有很多,本文只介紹了dubbo與zookeeper最基本的用法。要想了解更多的信息可以通過官方文檔進行學習:
dubbo中文文檔:http://dubbo.io/
zookeeper文檔:http://zookeeper.apache.org/
轉自: http://blog.csdn.net/zhdd99/article/details/52263609