一個簡單Dubbo例項
作為一個分散式框架Dubbo在專案中使用逐步越來越多,通過該框架很容易實現分散式,之前已經寫了一個大致步驟,今天有時間就整理一下,寫一個完整的例項作為記錄一下過程,
在專案進行之前,首先下載並搭建maven服務,建立maven本地倉庫,然後在eclipse中配置maven,步驟如下,
Eclipse -> Window -> Preferences
一,分散式專案框架建立;
因為是分散式專案,所以可以是相互分散在不同的物理機上,通過dubbo框架建立通訊,專案有些公共的東西,也有些是相互不同,所以這裡專案建立一個父子工程,父工程用於整合各個子專案,子專案分別完成各自的功能,最終完成如下圖;
其中 dubbo03為父工程,子工程dubbo03api為提供公共項工程,如api和model,子工程dubbo03provider為服務提供端工程,子工程dubbo03consumer為服務消費端工程,需要注意的是建立父工程後,先不要修改對應pom.xml檔案(否則新增子模組時該檔案出現莫名其妙的異常),而是緊接著新增各個子工程,完成之後,這樣父工程的 pom.xml 就自動增加了各個子模組,然後再對各個工程進行修改;注意在所有專案增加之前,
二,父工程建立;
父工程主要作為管理工程,
Eclipse -> File -> New -> Maven Project
注意圖中紅框之處,把其中的src目錄刪除,只留下 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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.qyh01</groupId> <artifactId>dubbo03</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>pom</packaging> <name>dubbo03</name> <description>dubbo03例項</description> <properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <!-- spring版本號 --> <spring.version>4.2.5.RELEASE</spring.version> <!-- log4j日誌包版本號 --> <slf4j.version>1.7.18</slf4j.version> <log4j.version>1.2.17</log4j.version> </properties> <dependencyManagement> <dependencies> <!-- start: 新增spring 和 junit4依賴 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <!-- end: 新增spring 和 junit4依賴 --> <!-- start: 新增日誌相關jar包 --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.2</version> </dependency> <!-- start: 新增日誌相關jar包 --> <!-- start: dubbo依賴相關 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.5.3</version> <exclusions> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring</artifactId> </exclusion> </exclusions> </dependency> <!-- end: dubbo依賴相關 --> <!-- start: 註冊中心Zookeeper zkclient依賴--> <dependency> <groupId>com.github.sgroschupf</groupId> <artifactId>zkclient</artifactId> <version>0.1</version> </dependency> <!-- end: 註冊中心Zookeeper zkclient依賴--> </dependencies> </dependencyManagement> <modules> <module>dubbo03api</module> <module>dubbo03provider</module> <module>dubbo03consumer</module> </modules> </project>
三,公共子專案API建立;
API工程注意是定義服務介面和對應的model模型,服務的提供端和消費端將都是用到,
右鍵單擊 dubbo03工程 -> New -> Other,彈出的視窗,左邊選中 maven 展開後選擇 Maven Module,如下圖,
點選下一步,
Next(下一步),
Next(下一步),
最後點選 Finish 完成,最後如下圖,
在api工程的 src/main/ 建立java資料夾,然後在其上分別建立兩個包 org.dubbo03.api 和 org.dubbo03.model ,右鍵點選src/main -> New -> Package,如下圖,
同樣方式建立 org.dubbo03.model,如下圖,
1,公共API介面定義;
這裡定義的介面就是提供服務的介面,在 org.dubbo03.api 定義一個介面,如下,
/**
* dubbo 例項
* @author shenzhenNBA
*/
package org.dubbo03.api;
import org.dubbo03.model.Product;
/**
* 介面定義
* @since 2018.05.18.
*/
public interface ProductService {
public Product getProductByCode(String productCode);
}
最終如下圖,
2,公共model建立
同樣在 org.dubbo03.model 定義一個Product的模型,如下,
/**
* dubbo 例項
* @author shenzhenNBA
*/
package org.dubbo03.model;
/**
* @author shenzhenNBA
* @since 2018.05.18.
*/
public class Product implements java.io.Serializable {
private static final long serialVersionUID = 2018051801000L;
private String productCode;
private String productName;
private Integer productNumber;
private String userName;
public Product() {
super();
}
public Product(String productCode, String productName,
Integer productNumber, String userName) {
super();
this.productCode = productCode;
this.productName = productName;
this.productNumber = productNumber;
this.userName = userName;
}
public String getProductCode() {
return productCode;
}
public void setProductCode(String productCode) {
this.productCode = productCode;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public Integer getProductNumber() {
return productNumber;
}
public void setProductNumber(Integer productNumber) {
this.productNumber = productNumber;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
最終如下圖,3,修改 api 工程的 pom.xml,如下,
<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.qyh01</groupId>
<artifactId>dubbo03</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.qyh01</groupId>
<artifactId>dubbo03api</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>dubbo03api</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>
</project>
四,服務提供端Provider子專案建立;
參照 api 工程的方式,在本工程中本分別建立 src/main/java 和 src/main/resources 資料夾,然後在 src/main/java 上建立 org.dubbo03.provider 和 org.dubbo03.service.impl 兩個包,在 src/main/resources 下建立 dubboProvider.xml 和 日誌的 log4j.xml 檔案,最終如下圖,
1,實現API介面,完成介面具體業務功能;
/**
* dubbo 例項
* @author shenzhenNBA
*/
package org.dubbo03.service.impl;
import org.dubbo03.api.ProductService;
import org.dubbo03.model.Product;
/**
* 介面實現類
* @since 2018.05.18.
*/
public class ProductServiceImpl implements ProductService {
@Override
public Product getProductByCode(String productCode) {
//query from DB system, more operation in here
if (null == productCode || productCode.trim().isEmpty()) {
return null;
} else {
return new Product("product001","優質大米001號",120,"張三");
}
}
}
2,建立服務提供端的啟動類;
/**
* dubbo 例項
* @author shenzhenNBA
*/
package org.dubbo03.provider;
import java.io.IOException;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* provider main啟動類
* @since 2018.05.18.
* zookeeper地址 F:\SoftwareTool\zookeeper\zookeeper-3.5.2-alpha\bin\zkServer.cmd
*/
public class ProviderMain {
public static void main(String[] args) throws IOException{
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("classpath:dubboProvider.xml");
System.out.println(context.getDisplayName() + ": show name here");
context.start();
System.out.println("=======================================================");
System.out.println("Dubbo provider run//Dubbo服務提供端已經啟動...");
System.out.println("=======================================================");
System.out.println("注意:依次按如下順序啟動");
System.out.println("1,首先執行 zookeeper 啟動服務註冊服務中心,根據情況可以不使用zk服務註冊中心");
System.out.println("2,其次執行 provider 服務提供端");
System.out.println("3,最後執行 consumer 服務消費端");
System.out.println("=======================================================");
System.in.read();
context.close();
}
}
3,建立dubbo相關的配置檔案,提供對外服務;
<?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-admin 或 dubbo-monitor 會顯示該名字,方便識別-->
<dubbo:application name="dubboProvider" owner="programmer" organization="dubbox"/>
<!--使用 zookeeper 註冊中心暴露服務,注意要先開啟 zookeeper,配置見conf資料夾下,預設zoo.cfg-->
<!-- <dubbo:registry address="zookeeper://localhost:2181"/> -->
<!-- 如果不使用 zookeeper 等服務註冊中心,則啟動如下配置即可,注意不能省去 -->
<dubbo:registry address="N/A" />
<!-- 用dubbo協議在20880埠暴露服務,當不用 zk 註冊服務中心是必須定義該協議和埠,消費端方可使用 -->
<dubbo:protocol name="dubbo" port="20880" />
<!--使用 dubbo 協議實現定義好的 api工程的 ProductService 介面-->
<dubbo:service interface="org.dubbo03.api.ProductService" ref="productService" protocol="dubbo" />
<!--具體實現該介面的 bean,見provider工程的實踐類-->
<bean id="productService" class="org.dubbo03.service.impl.ProductServiceImpl"/>
</beans>
注意,有時看到配置檔案左邊出現幾個紅叉,這個是對應的 xsd 檔案無法找到引起出現的,注意dubbo的 jar 裡面含有這個檔案,Eclipse -> Window -> Preferences 彈出如下視窗,
按圖中順序選中 xsd 檔案,然後在第5不中對應key輸入對應的值即可,其實如果正確引入dubbo的 jar 包,出現紅叉也不影響執行的,我這裡就是引入 xsd 檔案同樣出現紅叉,但是不影響執行;
相關的 log4j.xml 日誌的配置檔案如下,
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{dd/MM/yy hh:mm:ss:sss z}] %t %5p %c{2}: %m%n" />
</layout>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="CONSOLE" />
</root>
</log4j:configuration>
4,修改工程的 pom.xml 檔案,
<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.qyh01</groupId>
<artifactId>dubbo03</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.qyh01</groupId>
<artifactId>dubbo03provider</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>dubbo03provider</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- start: 相關介面jar包依賴增加 -->
<dependency>
<groupId>com.qyh01</groupId>
<artifactId>dubbo03api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- end: 相關介面jar包依賴增加 -->
<!-- start: 新增spring 和 junit4依賴 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<!-- end: 新增spring 和 junit4依賴 -->
<!-- start: 新增日誌相關jar包 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
<!-- start: 新增日誌相關jar包 -->
<!-- start: dubbo相關依賴增加 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- start: dubbo相關依賴增加 -->
<!-- start: 服務註冊中心Zookeeper zkclient依賴增加-->
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
</dependency>
<!-- end: 服務註冊中心Zookeeper zkclient依賴增加-->
</dependencies>
</project>
五,服務消費端Consumer子專案建立;
參照 Provider 工程的方式,在本工程中分別建立 src/main/java 和 src/main/resources 資料夾,然後在 src/main/java 上建立 org.dubbo03.consumer 包,在 src/main/resources 下建立 dubboConsumer.xml 和 日誌的 log4j.xml 檔案,最終如下圖,
1,建立dubbo相關的配置檔案,去哪獲取服務;
<?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-admin 或 dubbo-monitor 會顯示該名字,方便識別-->
<dubbo:application name="dubboConsumer" owner="programmer" organization="dubbox"/>
<!--使用 zookeeper 註冊中心暴露服務,注意要先開啟 zookeeper,配置見conf資料夾下,預設zoo.cfg-->
<!-- <dubbo:registry address="zookeeper://localhost:2181"/> -->
<!-- 如果不使用 zookeeper 等服務註冊中心,則啟動如下配置即可,注意不能省去 -->
<dubbo:registry address="N/A" />
<!--使用 dubbo 協議實現定義好的 api 工程的 ProductService 介面-->
<!-- <dubbo:reference id="productService" interface="org.dubbo03.api.ProductService"/> -->
<!--
當不使用 zookeeper 等服務註冊中心時使用如下配置,其實關鍵是需指定url以及指定dubbo協議,url格式如下:
url="dubbo://ip:port/provider工程的dubbo配置檔案中相關dubbo:service標籤的interface屬性值"
-->
<dubbo:reference id="consumerService" interface="org.dubbo03.api.ProductService"
url="dubbo://localhost:20880/org.dubbo03.api.ProductService"/>
</beans>
如果正確引入dubbo的 jar 包,配置檔案左邊出現紅叉也不影響執行的;
與之相關的 log4j.xml 日誌的配置檔案如下,
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{dd/MM/yy hh:mm:ss:sss z}] %t %5p %c{2}: %m%n" />
</layout>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="CONSOLE" />
</root>
</log4j:configuration>
2,修改工程的 pom.xml 檔案,
<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.qyh01</groupId>
<artifactId>dubbo03</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.qyh01</groupId>
<artifactId>dubbo03consumer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>dubbo03consumer</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- start: 相關介面jar包依賴增加 -->
<dependency>
<groupId>com.qyh01</groupId>
<artifactId>dubbo03api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- end: 相關介面jar包依賴增加 -->
<!-- start: 新增spring 和 junit4依賴 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<!-- end: 新增spring 和 junit4依賴 -->
<!-- start: dubbo相關依賴增加 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- start: dubbo相關依賴增加 -->
<!-- start: 服務註冊中心Zookeeper zkclient依賴增加-->
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
</dependency>
<!-- end: 服務註冊中心Zookeeper zkclient依賴增加-->
</dependencies>
</project>
3,消費端獲取並使用對應的分散式服務,
/**
* dubbo 例項
* @author shenzhenNBA
*/
package org.dubbo03.consumer;
import org.dubbo03.api.ProductService;
import org.dubbo03.model.Product;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* 消費端
* @since 2018.05.18.
*/
public class ConsumerMain {
public static void main(String[] args) {
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("dubboConsumer.xml");
context.start();
System.out.println("dubbo consumer start here");
ProductService productService = (ProductService) context.getBean(ProductService.class);
Product product = productService.getProductByCode("pro01");
System.out.println("Dubbo consumer//Dubbo服務消費端執行");
System.out.println("=======================================================");
if (null == product) {
System.out.println("product empty ");
} else {
System.out.println("product name: " + product.getProductName());
System.out.println("product code: " + product.getProductCode());
System.out.println("product num: " + product.getProductNumber());
System.out.println("product user: " + product.getUserName());
}
System.out.println("=======================================================");
context.close();
}
}
六,啟動,
啟動問題,啟動有先後順序,
(1)如果使用 zookeeper 作為註冊服務中心,一般是上線時會用到,則需要首先到網上下載該軟體,根據需要自己修改配置,需要首先啟動 zk ,然後在啟動服務提供端 Provider ,再次啟動服務消費端 Consumer;
(2)如果不使用 zookeeper 其實也可以,這一般是在開發階段,這個時候就必須先啟動服務提供端 Provider ,其次啟動服務消費端 Consumer,否則順序倒了啟動出問題;
例如不使用 zk 啟動時:右鍵單擊 ProviderMain 類 -> Run as -> Java application,如下圖所示,
同樣,右鍵單擊 ConsumerMain 類 -> Run as -> Java application,首先切換一下,如下圖所示,
然後看到消費端執行的結果,如下圖所示,
這裡可以看到消費端確實呼叫了服務提供端的功能;
七,注意;
一般服務提供端端實現了相關功能,並配置提供對外服務,消費端才能通過相關配置,才知道去哪裡獲取服務然後使用,所以服務的提供端和消費端的配置檔案相應的埠或暴露的服務介面要一樣,否則就找不到;當上線時一般使用 zookeeper 作為服務註冊中心,需先啟動,然後才啟動提供端和消費端;當開發過程不使用 zk 時,則必須首先啟動服務提供端,然後再啟動消費端,在服務提供端的 dubbo 配置檔案必須增加
<dubbo:protocol name="dubbo" port="指定埠" />
配置 dubbo 協議相關資訊,然後消費端的 dubbo 配置檔案可以通過
<dubbo:reference id="consumerService" interface="api工程的介面xxx.yyy.kkk.zzzService"
url="dubbo://ip:指定埠/api工程的介面xxx.yyy.kkk.zzzService"/>
好了,寫了蠻久,就到此吧,歡迎拍磚...