1. 程式人生 > >Dubbo的初瞭解

Dubbo的初瞭解

一、Dubbo簡介
1.Dubbo的概念:
DUBBO是一個分散式服務治理框架,致力於提供高效能和透明化的RPC遠端服務呼叫方案,可以和 Spring框架無縫整合,是阿里巴巴SOA服務化治理方案的核心框架,每天為2000+個服務提供3000000000+次訪問量支援,並被廣泛應用於阿里巴巴集團的各成員站點,同時,國內有大量的大型平臺都是基於Dubbo的分散式服務治理架構完成服務的分散式訪問。
Dubbo採用的是一種非常簡單的模型,要麼是提供方提供服務,要麼是消費方消費服務,所以基於這一點可以抽象出服務提供方(Provider)和服務消費方(Consumer)兩個角色。
2.Dubbo的作用:
(1)使用一個註冊中心來存放大量的服務,動態註冊和發現服務。
(2)自動畫出應用間的依賴關係圖,以幫助架構師理清理關係。
(3)將服務現在每天的呼叫量,響應時間,都統計出來,作為容量規劃的參考指標。以此資訊確定何時需要加減伺服器。

3.Dubbo核心要點
① 服務定義
服務是圍繞服務提供方和服務消費方的,服務提供方實現服務,而服務消費方呼叫服務。
② 服務註冊
對於服務提供方,它需要釋出服務,而且由於應用系統的複雜性,服務的數量、型別也不斷膨脹;對於服務消費方,它最關心如何獲取到它所需要的服務,而面對複雜的應用系統,需要管理大量的服務呼叫。而且,對於服務提供方和服務消費方來說,他們還有可能兼具這兩種角色,即既需要提供服務,有需要消費服務。
通過將服務統一管理起來,可以有效地優化內部應用對服務釋出/使用的流程和管理。服務註冊中心可以通過特定協議來完成服務對外的統一。Dubbo提供的註冊中心有如下幾種型別可供選擇:
Multicast(多播/組播)註冊中心(開發測試用)、Zookeeper註冊中心(生產環境用官方推薦)、Redis註冊中心、Simple註冊中心
③ 服務監控
無論是服務提供方,還是服務消費方,他們都需要對服務呼叫的實際狀態進行有效的監控,從而改進服務質量。
④ 遠端通訊與資訊交換
遠端通訊需要指定通訊雙方所約定的協議,在保證通訊雙方理解協議語義的基礎上,還要保證高效、穩定的訊息傳輸。Dubbo繼承了當前主流的網路通訊框架,主要包括如下幾個:
Mina、Netty、Grizzly
⑤ 服務呼叫

節點角色說明:
Provider: 暴露服務的服務提供方。
Consumer: 呼叫遠端服務的服務消費方。
Registry: 服務註冊與發現的註冊中心。
Monitor: 統計服務的呼叫次調和呼叫時間的監控中心。
Container: 服務執行容器。
呼叫關係說明:

  1. 服務容器負責啟動,載入,執行服務提供者。

  2. 服務提供者在啟動時,向註冊中心註冊自己提供的服務。

  3. 服務消費者在啟動時,向註冊中心訂閱自己所需的服務。

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

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

  6. 服務消費者和提供者,在記憶體中累計呼叫次數和呼叫時間,定時每分鐘傳送一次統計資料到監控中心。
    4.Dubbo的獲取(官網hello world)
    官方Maven倉庫
    阿里巴巴已將Dubbo已釋出到Maven中央倉庫中:
    http://central.maven.org/maven2/com/alibaba/dubbo。

     <project>
         <dependencies>
             <dependency>
                 <groupId>com.alibaba</groupId>
                 <artifactId>dubbo</artifactId>
                 <version>2.6.2</version>
             </dependency>
         </dependencies>
     </project>
    

二、Dubbo本地服務化實現
1.Dubbo服務化架構包含的內容
服務提供者: 提供服務介面的實現,釋出服務地址,提供服務。
服務消費者:獲取服務地址,使用服務介面呼叫服務,處理服務呼叫結果。
公共專案:包含公共配置、DO、VO、工具包等…
2.服務提供者專案搭建(Maven專案管理方式):
① 建立公共專案工程:普通的Maven工程,提供utils、DO、介面的程式碼。
pom.xml 無任何依賴
② 建立服務提供者專案:普通的Maven工程(依賴Dubbo),提供服務實現、服務啟動功能。

pom.xml

<dependencies>
				<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>dubbo</artifactId>
			<version>2.6.2</version>
		</dependency>
		<dependency>
			<groupId>dubbo-api</groupId>
			<artifactId>dubbo-api</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
         <dependency>
    <groupId>com.github.sgroschupf</groupId>
    <artifactId>zkclient</artifactId>
    <version>0.1</version>
</dependency>

	<!-- junit測試包 -->
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>4.12</version>
		<scope>test</scope>
	</dependency>

	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-test</artifactId>
		<version>4.3.16.RELEASE</version>
	</dependency>

	
</dependencies>

dubbo-provider.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-2.5.xsd
	http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

	<dubbo:application name="dubbo-test-provider" owner="sampson"></dubbo:application>
	
	<dubbo:protocol name="dubbo" port="20880" ></dubbo:protocol>
	
	<!-- 區域網廣播註冊中心 -->
	<dubbo:registry address="multicast://239.5.6.7:1234" />
	
	<!-- 配置式釋出 -->
	<bean id="userService" class="cn.itsource.dubbo.provider.service.UserServiceImpl"></bean>
	<dubbo:service interface="cn.itsource.dubbo.core.service.IUserService" ref="userService"></dubbo:service>
<!-- 註解式釋出 -->
	<!-- 掃描註解包路徑,多個包用逗號分隔,不填pacakge表示掃描當前ApplicationContext中所有的類 -->
	<dubbo:annotation package="cn.itsource.dubbo.provider.service" />
</beans>

啟動服務監聽
String configLocation = “classpath*:/dubbo-provider.xml”;
ApplicationContext context = new ClassPathXmlApplicationContext(configLocation);
System.out.println(“dubbo-server服務正在監聽,按任意鍵退出”);
System.in.read();
3.服務消費者專案搭建(Maven專案管理方式):
建立服務消費者專案:普通的Maven工程(依賴Dubbo),完成服務呼叫功能。

pom.xml

<dependencies>
	<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>dubbo</artifactId>
			<version>2.6.2</version>
		</dependency>
<dependency>
			<groupId>dubbo-api</groupId>
			<artifactId>dubbo-api</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
   <dependency>
    <groupId>com.github.sgroschupf</groupId>
    <artifactId>zkclient</artifactId>
    <version>0.1</version>
</dependency>
	</dependencies>

dubbo-consumer.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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-2.5.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd 
http://www.springframework.org/schema/context  
http://www.springframework.org/schema/context/spring-context.xsd">

<dubbo:application name="dubbo-test-consumer"></dubbo:application>

<!-- 區域網廣播註冊中心 -->
<dubbo:registry address="multicast://239.5.6.7:1234" />
	
<!-- 配置式呼叫服務 -->

	<!-- <dubbo:reference id="helloService" interface="cn.itsource.dubbo.core.service.IHelloService"></dubbo:reference> -->

<!-- 註解式呼叫服務 -->
<!-- 掃描註解包路徑,多個包用逗號分隔,不填pacakge表示掃描當前ApplicationContext中所有的類 -->
	<dubbo:annotation package="cn.itsource.dubbo.consumer" />
</beans>

JUnit4呼叫dubbo服務測試類

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath*:/dubbo-consumer.xml"})
public class DubboServiceTest {
	@Reference
	private IHelloService helloService;

@Test
public void testHello(){
	String sayHi = helloService.sayHi("老宋");
	System.out.println(sayHi);
}

}

4.直連除錯模式
服務提供者:
修改註冊中心為:N/A模式(不註冊)

<dubbo:registry address="N/A" check="false"/> 

服務消費者:
修改註冊中心為:N/A模式(不註冊)

<dubbo:registry address="N/A" check="false"/>

url 配置屬性

<dubbo:reference id="demoService" interface="cn.itsource.dubbo.DemoService"  url="dubbo://localhost:20881" />

配置本地呼叫地址對映:
然後在${user.home}/dubbo-resolve.properties檔案中配置對應服務呼叫的本地地址
${user.home} 一般代表:C:\Users{你當前登入名}
dubbo-resolve.properties示例

cn.itsource.dubbo.core.service.IUserService=dubbo://localhost:20880

5.Dubbo服務打包
(1)Dubbo服務的執行方式有三種
(2)使用Servlet容器(不用)
利用Tomcat、Jetty等WEB容器啟動Dubbo服務。
缺點:增加管理配置的複雜性,不必要地使用http埠,浪費記憶體資源
(3)Java的Main方法(不建議,本地除錯可以用)
基於Spring框架,寫一個Java類並提供Main方法啟動。
缺點:無法使用Dubbo的一些高階特性,服務的管理需要自己額外提供實現
(4)Dubbo框架Main方法
Dubbo框架本身提供了服務執行支援方法,基於com.alibaba.dubbo.container.Main
簡單高效地執行服務
很好地支援Dubbo服務的釋出、關停(ShutdownHook)
(5)Maven編譯打包

Pom.xml

cn.itsource.service
service-user
${service-user.version}
jar

<properties>
	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<!-- 打包jar詳細配置 -->
<build>
	<!-- jar包名字 -->
	<finalName>provder</finalName>
	<!-- 打包資源配置,如配置檔案 -->
	<resources>
		<resource>
			<targetPath>${project.build.directory}/classes</targetPath>
			<directory>src/main/resources</directory>
			<filtering>true</filtering>
			<includes>
				<include>**/*.xml</include>
				<include>**/*.properties</include>
			</includes>
		</resource>
		<!-- 結合com.alibaba.dubbo.container.Main 
		官方文件:dubbo會自動在classes/META-INF/spring下去載入spring的配置檔案
		因此打包時需要將spring配置檔案複製到該目錄
		-->
		<resource>
			<targetPath>${project.build.directory}/classes/META-INF/spring</targetPath>
			<directory>src/main/resources</directory>
			<filtering>true</filtering>
			<includes>
				<include>applicationContext.xml</include>
			</includes>
		</resource>
	</resources>
	
	<pluginManagement>
		<plugins>
			<!-- 解決Maven外掛在Eclipse內執行了一系列的生命週期引起衝突 -->
			<plugin>
				<groupId>org.eclipse.m2e</groupId>
				<artifactId>lifecycle-mapping</artifactId>
				<version>1.0.0</version>
				<configuration>
					<lifecycleMappingMetadata>
						<pluginExecutions>
							<pluginExecution>
								<pluginExecutionFilter>
									<groupId>org.apache.maven.plugins</groupId>
									<artifactId>maven-dependency-plugin</artifactId>
									<versionRange>[2.0,)</versionRange>
									<goals>
										<goal>copy-dependencies</goal>
									</goals>
								</pluginExecutionFilter>
								<action>
									<ignore />
								</action>
							</pluginExecution>
						</pluginExecutions>
					</lifecycleMappingMetadata>
				</configuration>
			</plugin>
		</plugins>
	</pluginManagement>
	<plugins>
		<!-- 打包jar檔案時,配置manifest檔案,加入lib包的jar依賴 -->
		<plugin>
			<groupId>org.apache.maven.plugins</groupId>
			<artifactId>maven-jar-plugin</artifactId>
			<configuration>
				<classesDirectory>target/classes/</classesDirectory>
				<archive>
					<manifest>
						<mainClass>com.alibaba.dubbo.container.Main</mainClass>
						<!-- 重要:打包時 MANIFEST.MF檔案不記錄的時間戳版本 -->
						<useUniqueVersions>false</useUniqueVersions>
						<addClasspath>true</addClasspath>
						<classpathPrefix>lib/</classpathPrefix>
					</manifest>
					<manifestEntries>
						<Class-Path>.</Class-Path>
					</manifestEntries>
				</archive>
			</configuration>
		</plugin>
		<plugin>
			<groupId>org.apache.maven.plugins</groupId>
			<artifactId>maven-dependency-plugin</artifactId>
			<executions>
				<execution>
					<id>copy-dependencies</id>
					<phase>package</phase>
					<goals>
						<goal>copy-dependencies</goal>
					</goals>
					<configuration>
						<type>jar</type>
						<includeTypes>jar</includeTypes>
						<useUniqueVersions>false</useUniqueVersions>
						<outputDirectory>
							${project.build.directory}/lib
						</outputDirectory>
					</configuration>
				</execution>
			</executions>
		</plugin>
	</plugins>

</build>

<dependencies>
</dependencies>

(3)dubbo服務jar包執行
Cmd視窗:
① 定位到jar包所在目錄
② 輸入命令並回車執行:java -jar xxxxx.jar
三.P2P專案的分散式服務呼叫實現(crm)
1.作用
主要是對原有的程式碼進行重新整合,分為程式碼拆分、dubbo整合(分離出服務提供方和消費方)、服務釋出與接入(註冊中心zookeeper)
2.程式碼拆分
根據各層進行拆分,主要針對:
① pom.xml專案引用jar包
② 程式碼:DAO和Service層獨立為服務提供者。前端和Controller獨立為服務消費者。
③ Spring配置檔案進行拆分(參考②步拆分思路)
注意:利用tomcat外掛啟動web需要設定tomcat的calsspath選中依賴的專案
Idea 需要

    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.*</include>
            </includes>
            <excludes>
                <exclude>**/*.java</exclude>
            </excludes>
            <filtering>false</filtering>
        </resource>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.*</include>
            </includes>
            <filtering>false</filtering>
        </resource>
    </resources>

3.Dubbo整合
對服務提供方和服務消費者整合Dubbo的呼叫方式。
公共專案:
因為Dubbo涉及遠端呼叫傳輸物件,所有需要傳輸的物件的類都必須實現Serializable介面,如Domain層的所有類。
(1)服務提供方
① 修改原spring的@Service註解為dubbo的@Service註解
② 新建xxxx-dubbo-provider.xml,然後在spring contex的配置檔案最後引入
Xxxx-dubbo-provider.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服務釋出 -->
	<dubbo:application name="p2p-service" />
	<dubbo:protocol name="dubbo" port="20880"></dubbo:protocol>
	<dubbo:registry address="multicast://239.5.6.7:1236"></dubbo:registry>
	<dubbo:annotation package="cn.itsource.eloan.core.service.impl" />
</beans>

③ 服務釋出類

public class DubboServer {
	public static void main(String[] args) throws IOException {
		String configLocation = "classpath*:/spring-core.xml";
		ApplicationContext context = new ClassPathXmlApplicationContext(configLocation);
		System.out.println("p2p服務正在監聽");
		String[] names = context.getBeanDefinitionNames();
		System.out.print("Beans:");
		for (String string : names)
			System.out.println(string);
		System.out.println();
		System.in.read();
	}
}

(2)服務消費方
① 修改需要遠端呼叫的服務,從原spring的@Autoware註解為dubbo的@Reference註解
② 新建xxxx-dubbo-consumer.xml,然後在springmvc contex的配置檔案最後引入
Xxxx-dubbo-consumer.xml