Dubbo分佈式系統架構


        Dubbo是Alibaba開源的分佈式服務框架,它最大的特點是按照分層的方式來架構,使用這種方式可以使各個層之間解耦合(或者最大限度地鬆耦合)。

從服務模型的角度來看,Dubbo採用的是一種非常簡單的模型,要麼是提供方提供服務,要麼是消費方消費服務,所以基於這一點可以抽象出服務提供方(Provider)和服務消費方(Consumer)兩個角色。關於註冊中心、協議支持、服務監控等內容如下圖所示:




調用關係說明:


0. 服務容器(spring)負責啓動,加載,運行服務提供者。


1. 服務提供者在啓動時,向註冊中心註冊自己提供的服務(以接口的方式提供,包括服務提供者的ip及端口號)。


2. 服務消費者在啓動時,向註冊中心訂閱自己所需的服務(仍然以接口的形式)。


3. 註冊中心返回服務提供者地址列表給消費者,如果有變更,註冊中心將基於長連接推送變更數據給消費者。


4. 服務消費者,從提供者地址列表中,基於軟負載均衡算法,選一臺提供者進行調用,如果調用失敗,再選另一臺調用。


5. 服務消費者和提供者,在內存中累計調用次數和調用時間,定時每分鐘發送一次統計數據到監控中心。




二、搭建分佈式開發架構

      下面以開發一個用戶模塊爲例說明架構的搭建過程,功能包括用戶登錄、註冊、用戶信息展示、刪除、修改等等。整個系統可以劃分爲4個maven工程,分別是dubbo1-common(公共模塊)、dubbo1-user-facade(服務接口模塊:對外提供服務接口_服務提供者和消費者都需要用到)、dubbo1-user-service(服務提供者模塊)、dubbo1-web(服務消費者模塊)。


      環境:


      jdk1.7+myeclipse8.6.1+maven3.3.9+mysql5.6+dubbo2.5.3+zookeeper-3.4.6+spring3.2.2+springmvc+mybatis3.2.2


      1. 搭建dubbo1-common(公共模塊)


        公共模塊:我們可以把服務提供者和消費者都可能用到的東西都放到這裏來,到時候讓服務提供者和消費者來依賴它即可。例如我們這裏把公共的dao層代碼BaseDao,工具類MD5加密類,公共的配置文件(連接池及註冊中心地址配置),以及服務提供者和消費者全部的依賴的jar包都配置公共模塊裏面,如圖所示:




dubbo1-common搭建完畢後,需要以jar包的形式發佈到maven本地庫中,如圖所示操作:




2. 搭建dubbo1-user-facade(服務接口模塊)


   服務接口模塊非常簡單,只需寫對外發布的接口以及依賴的實體類。但是我們必須把它單獨劃分成一個工程,因爲服務提供者和消費者都要用到它。如圖所示:




同理,搭建完畢後,需要以jar包的形式發佈到maven本地庫中,跟第一個工程操作類似,這裏就不截圖了。


3. 搭建dubbo1-user-service(服務提供者模塊)


    


添加依賴,如圖:




這時候的pom.xml文件如下所示:


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

  <modelVersion>4.0.0</modelVersion>

  <groupId>com.wx</groupId>

  <artifactId>dubbo1-user-service</artifactId>

  <version>0.0.1-SNAPSHOT</version>

  

  <!-- 項目jdk版本配置 -->

  <build>

<plugins>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-compiler-plugin</artifactId>

<version>3.5.1</version>

<configuration>

<source>1.7</source>

<target>1.7</target>

<encoding>utf-8</encoding>

</configuration>

</plugin>

</plugins>

  </build>

  <dependencies>

  <dependency>

  <groupId>com.wx</groupId>

  <artifactId>dubbo1-common</artifactId>

  <version>0.0.1-SNAPSHOT</version>

  <type>jar</type>

  <scope>compile</scope>

  </dependency>

  <dependency>

  <groupId>com.wx</groupId>

  <artifactId>dubbo1-user-facade</artifactId>

  <version>0.0.1-SNAPSHOT</version>

  <type>jar</type>

  <scope>compile</scope>

  </dependency>

  </dependencies>

</project>

================================

服務提供者的配置文件dubbo-provider.xml如下:


<?xml version="1.0" encoding="UTF8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"

xsi:schemaLocation="http://www.springframework.org/schema/beans  

            http://www.springframework.org/schema/beans/spring-beans.xsd  

            http://code.alibabatech.com/schema/dubbo  

            http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

 

<!-- 服務提方的服務名,注意不要和其它服務重名 -->

<dubbo:application name="dubbo1-service-user" />

 

<!-- 使用zookeeper註冊中心暴露服務地址 -->

<dubbo:registry protocol="zookeeper" address="${dubbo.register.address}" />

 

<!-- 用dubbo協議在19880端口暴露服務 -->

<dubbo:protocol name="dubbo" port="19880" />

<!-- 用戶服務接口 -->

<dubbo:service interface="com.wx.service.IUserBiz" ref="userBiz" />

</beans>  

當spring容器啓動後,會生成userBiz的實例,<dubbo:service interface="com.wx.service.IUserBiz" ref="userBiz" />表示以接口名com.wx.service.IUserBiz向註冊中心註冊服務,提供的對象是userBiz,這個對象裏面就包含的提供服務的數據。

============================


spring核心配置文件applicationContext.xml如下所示:


<?xml version="1.0" encoding="UTF8"?>

<beans

xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:p="http://www.springframework.org/schema/p"

xmlns:aop="http://www.springframework.org/schema/aop"

xmlns:tx="http://www.springframework.org/schema/tx"

xmlns:context="http://www.springframework.org/schema/context"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

http://www.springframework.org/schema/aop 

http://www.springframework.org/schema/aop/spring-aop-3.0.xsd

http://www.springframework.org/schema/tx

http://www.springframework.org/schema/tx/spring-tx-3.0.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-3.0.xsd">

 

<!-- 導入dubble配置 -->

<import resource="classpath:configs/dubbo-provider.xml"/>

<!-- 掃描包含註解類所在的包 -->

<context:component-scan base-package="com.wx.dao.*"></context:component-scan>

<context:component-scan base-package="com.wx.biz"></context:component-scan>

<bean id="config" class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer">

<property name="locations">

<list>

  <value>classpath:service.properties</value>

  <value>classpath:druidConfig_6.properties</value>

</list>

</property>

</bean>

<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">

<property name="driverClassName" value="${driverClassName}" />

<property name="url" value="${url}" />

<property name="username" value="${username}" />

<property name="password" value="${password}" />

<property name="filters" value="${filters}" />

<property name="initialSize" value="${initialSize}" />

<property name="maxActive" value="${maxActive}" />

<property name="minIdle" value="${minIdle}" />

<property name="maxWait" value="${maxWait}" />

<property name="validationQuery" value="${validationQuery}" />

<property name="testWhileIdle" value="${testWhileIdle}" />

<property name="testOnBorrow" value="${testOnBorrow}" />

<property name="testOnReturn" value="${testOnReturn}" />

<property name="maxPoolPreparedStatementPerConnectionSize" value="${maxPoolPreparedStatementPerConnectionSize}" />

<property name="removeAbandoned" value="${removeAbandoned}" />

<property name="removeAbandonedTimeout" value="${removeAbandonedTimeout}" />

<property name="timeBetweenEvictionRunsMillis" value="${timeBetweenEvictionRunsMillis}" />

<property name="minEvictableIdleTimeMillis" value="${minEvictableIdleTimeMillis}" />

</bean>

<bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

<property name="dataSource" ref="druidDataSource"></property>

<property name="configLocation">

<value>classpath:configs/mybatis-config.xml</value>

</property>

<property name="mapperLocations">

<list>

<value>classpath:configs/mappers/*.xml</value>

</list>

</property>

</bean>

<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">

<constructor-arg name="sqlSessionFactory" ref="sessionFactory"></constructor-arg>

</bean>

<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

<property name="dataSource" ref="druidDataSource"></property>

</bean>

<tx:advice id="txAdvise" transaction-manager="txManager">

<tx:attributes>

<tx:method name="find*" read-only="true"/>

<tx:method name="search*" read-only="true"/>

<tx:method name="query*" read-only="true"/>

<tx:method name="get*" read-only="true"/>

<tx:method name="add*" propagation="REQUIRED"/>

<tx:method name="save*" propagation="REQUIRED"/>

<tx:method name="do*" propagation="REQUIRED"/>

<tx:method name="update*" propagation="REQUIRED"/>

<tx:method name="del*" propagation="REQUIRED"/>

</tx:attributes>

</tx:advice>

<aop:config>

<aop:pointcut expression="execution(* com.wx.biz.*.*(..))" id="myCut"/>

<aop:advisor advice-ref="txAdvise" pointcut-ref="myCut"/>

</aop:config>

</beans>

==============================

接下來創建測試類啓動服務:


package dubbo.test;

 

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

import org.springframework.context.support.ClassPathXmlApplicationContext;

 

/**

 * 

 * @描述: 啓動Dubbo服務用的MainClass.

 * @作者: wx

 * @創建時間: 2015-11-5,下午9:47:55 .

 * @版本: 1.0

 */

public class DubboProvider {

private static final Log log = LogFactory.getLog(DubboProvider.class);

 

public static void main(String[] args) {

try {

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:configs/applicationContext.xml");

context.start();

} catch (Exception e) {

log.error("== DubboProvider context start error:",e);

}

synchronized (DubboProvider.class) {

while (true) {

try {

DubboProvider.class.wait();

} catch (InterruptedException e) {

log.error("== synchronized error:",e);

}

}

}

}

    

}

單擊右鍵運行,沒報錯,服務就正常啓動了,這時候可以在監控中心看到如下結果:




4.  搭建dubbo1-web(服務消費者模塊)

     這時候服務消費者完全可以在不同的地方,不同的項目組開發,體現分佈式。消費者模塊搭建的是一個maven   web工程,如下圖所示:






---------------------------------------------




如圖所示:消費者工程需要依賴dubbo1-common和dubbo1-user-facade。


消費者核心配置文件dubbo-consumer.xml   如下:


<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"

xsi:schemaLocation="http://www.springframework.org/schema/beans  

        http://www.springframework.org/schema/beans/spring-beans.xsd  

        http://code.alibabatech.com/schema/dubbo  

        http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

 

<!-- 消費方應用名,不要與提供方一樣 -->

<dubbo:application name="dubbo1-user-web" />

 

<!-- 使用zookeeper註冊中心暴露服務地址 -->

<!-- 註冊中心地址 -->

<dubbo:registry protocol="zookeeper" address="${dubbo.register.address}" />

<!-- 用戶服務接口 id=userBiz表示服務以名稱userBiz向消費者的控制器注入對象  check=false表示不檢查服務端是否正常 -->

<dubbo:reference interface="com.wx.service.IUserBiz" id="userBiz" check="false" />

    

</beans>

啓動消費者,即發佈到tomcat啓動。然後運行,監控界面如下所示:



運行效果如圖:




ok,到此爲止,分佈式開發框架搭建完畢!






















發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章