5分鐘實現SpringBoot整合Dubbo構建分布式服務
概述:
Dubbo是Alibaba開源的分布式服務框架,它最大的特點是按照分層的方式來架構,使用這種方式可以使各個層之間解耦合(或者最大限度地松耦合)。從服務模型的角度來看,Dubbo采用的是一種非常簡單的模型,要么是提供方提供服務,要么是消費方消費服務,所以基于這一點可以抽象出服務提供方(Provider)和服務消費方(Consumer)兩個角色。
我們來看一下Dubbo 的RPC 調用流程,這里主要涉及到4個模塊:
- Registry:服務注冊,我們一般會采取Zookeeper 作為我們的注冊中心
- Provider:服務提供者(生產者),提供具體的服務實現
- Consumer:消費者,從注冊中心中訂閱服務
- Monitor:監控中心,RPC調用次數和調用時間監控
從上圖中我們可以了解到整個RPC 服務調用的過程主要為:
- 生產者發布服務到服務注冊中心中
- 消費者在服務注冊中心中訂閱服務
- 消費者調用已經注冊的服務
一、項目構建
開發環境主要涉及以下幾個方面:
- Spring-boot
- JDK 8
- Dubbo
- Zookeeper
項目構建通過: http://start.spring.io/ 快速構建web 項目,具體操作可以參考
http://www.cnblogs.com/jaycekon/p/7562688.html
由于Dubbo 中需要使用到服務注冊中心,我們這里將使用Zookeeper 作為服務注冊中心,具體安裝配置,可以參考
http://www.cnblogs.com/jaycekon/p/7553909.html
在基礎環境確定好了之后,我們項目的目錄結構如下:
上圖所示,我們項目主要分為了兩個模塊,一部分是生產者:spring-boot-dubbo ,一部分是:spring-boot-consumer。
整個項目的結構非常簡單,這很符合Spring-Boot 的特性,簡單便捷,下面我們開始一步步的剖析整個項目的結構
二、Productor
2.1、Pom.xml
項目依賴這一塊主要使用到了基本的Spring-Boot-Web 依賴,然后我們需要額外引入Dubbo 與Zookeeper的依賴(詳細依賴可參考源碼,博文底部會有項目Github 地址):
- <dependency>
- <groupId>io.dubbo.springboot</groupId>
- <artifactId>spring-boot-starter-dubbo</artifactId>
- <version>1.0.0</version>
- </dependency>
- <dependency>
- <groupId>org.apache.zookeeper</groupId>
- <artifactId>zookeeper</artifactId>
- <version>3.4.6</version>
- <exclusions>
- <exclusion>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-log4j12</artifactId>
- </exclusion>
- <exclusion>
- <groupId>log4j</groupId>
- <artifactId>log4j</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
2.2、配置文件
由于我們底層使用的是Spring-Boot 進行開發,那么我們就應該善于利用Spring-Boot 給我們帶來的優勢,因此我們可以直接在Application.properties 文件中配置Dubbo 服務:
- ## Dubbo 服務提供者配置
- spring.dubbo.application.name=provider --服務名稱
- spring.dubbo.registry.address=zookeeper://127.0.0.1:2181 -- 注冊中心地址
- spring.dubbo.protocol.name=dubbo -- dubbo 協議
- spring.dubbo.protocol.port=20880
- spring.dubbo.scan=com.jaycekon.dubbo.service --聲明需要暴露的服務接口
如果不采用Spring-Boot 進行自動配置,大家可以參考一下的配置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="provider" />
- <!-- 注冊中心服務地址 -->
- <dubbo:registry protocol="zookeeper" address="127.0.0.1" check="false" />
- <!-- 用dubbo協議-->
- <dubbo:protocol name="dubbo" port="-1" dispather="all" check="false" />
- <dubbo:provider timeout="10000" threads="10" threadpool="fixed" loadbalance="roundrobin"/>
- <!-- 聲明需要暴露的服務接口 -->
- <dubbo:service interface="com.jaycekon.dubbo.service" ref="userService"/> </beans>
2.3、服務提供
在服務提供主要包括兩部分,一個是暴露服務,一個是服務實現
暴露服務:即我們平常開發中所使用的的接口,這里我們創建一個 UserService 的接口,主要包括一個保存用戶的方法。
- import com.jaycekon.dubbo.domain.User;
- /**
- * Created by Jaycekon on 2017/9/19.
- */
- public interface UserService {
- User saveUser(User user);
- }
服務實現:服務實現,與我們平常的服務一樣,對接口進行實現,比較特別的是,我們這里需要使用到Dubbo 的 @Service 注解。更多springboot實戰內容,Java知音公眾號內回復“springboot聚合”
- import com.alibaba.dubbo.config.annotation.Service;
- import com.jaycekon.dubbo.domain.User;
- import com.jaycekon.dubbo.service.UserService;
- /**
- * Created by Jaycekon on 2017/9/19.
- */
- @Service
- public class UserServiceImpl implements UserService {
- @Override
- public User saveUser(User user) {
- user.setId(1);
- System.out.println(user.toString());
- return user;
- }
- }
2.4、總體結構
Dubbo 的服務提供端,已經總體開發完成,非常簡單,總體的目錄結構如下:
三、Consumer
3.1、pom.xml
消費者的相關依賴,與生產者的依賴一致。
- <?xml version="1.0" encoding="UTF-8"?>
- <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.jaycekon</groupId>
- <artifactId>spring-boot-consumer</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- <packaging>jar</packaging>
- <name>spring-boot-consumer</name>
- <description>Demo project for Spring Boot</description>
- <parent>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-parent</artifactId>
- <version>1.5.7.RELEASE</version>
- <relativePath/> <!-- lookup parent from repository -->
- </parent>
- <properties>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
- <java.version>1.8</java.version>
- </properties>
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- <scope>test</scope>
- </dependency>
- <!-- Spring Boot Dubbo 依賴 -->
- <dependency>
- <groupId>io.dubbo.springboot</groupId>
- <artifactId>spring-boot-starter-dubbo</artifactId>
- <version>1.0.0</version>
- </dependency>
- <dependency>
- <groupId>org.apache.zookeeper</groupId>
- <artifactId>zookeeper</artifactId>
- <version>3.4.6</version>
- <exclusions>
- <exclusion>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-log4j12</artifactId>
- </exclusion>
- <exclusion>
- <groupId>log4j</groupId>
- <artifactId>log4j</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <!-- mvn spring-boot:run 熱部署啟動 -->
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>springloaded</artifactId>
- <version>1.2.3.RELEASE</version>
- </dependency>
- <dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- <version>1.16.18</version>
- <scope>provided</scope>
- </dependency>
- </dependencies>
- <build>
- <plugins>
- <plugin>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-maven-plugin</artifactId>
- </plugin>
- </plugins>
- </build>
- </project>
3.2、配置文件
配置文件與生產者稍有區別:
- ## 避免和 server 工程端口沖突
- server.port=8081
- ## Dubbo 服務消費者配置
- spring.dubbo.application.name=consumer
- spring.dubbo.registry.address=zookeeper://127.0.0.1:2181
- spring.dubbo.scan=com.jaycekon.dubbo.service
基于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="provider" />
- <!-- 注冊中心服務地址 -->
- <dubbo:registry protocol="zookeeper" address="${dubbo.registry.address}" check="false" />
- <!-- 用dubbo協議-->
- <dubbo:protocol name="dubbo" port="-1" dispather="all" check="false" />
- <dubbo:provider timeout="10000" threads="10" threadpool="fixed" loadbalance="roundrobin"/>
- <!-- 聲明需要暴露的服務接口 -->
- <dubbo:service interface="com.jaycekon.dubbo.service" ref="userService"/>
- </beans>
3.3、服務實現
在這里,如果我們需要調用注冊服務中的相關服務,則需要實現相關的接口。
- import com.jaycekon.dubbo.domain.User;
- /**
- * Created by Jaycekon on 2017/9/19.
- */
- public interface UserService {
- User saveUser(User user);
- }
例如,在這里我們需要使用到生產者中的 saveUser(User user) 方法,則需要創建一個接口,然后再調用時,使用 @Reference 注解進行引用:
- import com.alibaba.dubbo.config.annotation.Reference;
- import com.jaycekon.dubbo.domain.City;
- import com.jaycekon.dubbo.domain.User;
- import org.springframework.stereotype.Component;
- /**
- * 城市 Dubbo 服務消費者
- * <p>
- * Created by Jaycekon on 20/09/2017.
- */
- @Component
- public class CityDubboConsumerService {
- @Reference
- CityDubboService cityDubboService;
- @Reference
- UserService userService;
- public void printCity() {
- String cityName = "廣州";
- City city = cityDubboService.findCityByName(cityName);
- System.out.println(city.toString());
- }
- public User saveUser() {
- User user = new User();
- user.setUsername("jaycekon")
- .setPassword("jaycekong824");
- return userService.saveUser(user);
- }
- }
3.4、服務調用
最后,我們需要實現一個RESTful 接口,提供給用戶調用:
- import com.jaycekon.dubbo.service.CityDubboConsumerService;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RestController;
- /**
- * Created by Jaycekon on 2017/9/19.
- */
- @RestController
- public class UserController {
- @Autowired
- private CityDubboConsumerService service;
- @RequestMapping("/save")
- public Object saveUser() {
- return service.saveUser();
- }
- }
3.5、目錄結構
四、總結
本篇博客主要是博主在學習Spring-boot 的時候,總結下來的。在經過一些列的對比后,感覺Dubbo 與Spring-Cloud 還是有點差距的,不管是從服務提供,還是社區活躍來說,Spring-Cloud 還是會強一點。但是由于公司內部使用的是Dubbo,因此還是需要學習一下,后續的話,會對Spring-Cloud 進行學習以及分項。
GitHub地址
https://github.com/jaycekon/SpringBoot