Spring Boot入門教程(四十九): Dubbo
一:簡介
Apache Dubbo (incubating) |ˈdʌbəʊ| 是一款高效能、輕量級的開源Java RPC框架,它提供了三大核心能力:面向介面的遠端方法呼叫,智慧容錯和負載均衡,以及服務自動註冊和發現。
二:安裝dubbo管理控制檯(dubbo-admin)
下載dubbo-admin(https://github.com/apache/incubator-dubbo-ops/tree/master) 注意是dubbo-admin專案,不是其它專案。
# 打包 mvn clean install # 啟動專案 cd target java -jar dubbo-admin-0.0.1-SNAPSHOT.jar # 訪問 localhost:7001 使用者名稱:root 密碼:root
安裝監控中心(dubbo-monitor-simple)
# 打包dubbo-monitor-simple cd dubbo-monitor-simple mvn clean package # 解壓.tar.gz cd target tar -zxvf dubbo-monitor-simple-2.0.0-assembly.tar.gz mv dubbo-monitor-simple-2.0.0 ../.. # 啟動程式 cd ../../dubbo-monitor-simple-2.0.0/assembly.bin ./start.sh # 訪問 http://localhost:8080/
三:XML方式
① dubbo-api
package com.example.api;
public interface DemoService {
String sayHello(String name);
}
② dubbo-service-provider
<?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.example.provider</groupId> <artifactId>dubbo-service-provider</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.6.3</version> </dependency> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.13</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> <version>4.0.1</version> </dependency> <dependency> <groupId>com.example.api</groupId> <artifactId>dubbo-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies> </project>
DemoServiceImpl
package com.example.provider;
public class DemoServiceImpl implements DemoService {
public String sayHello(String name) {
return "Hello " + name;
}
}
src/main/resources/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://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://dubbo.apache.org/schema/dubbo
http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!-- 服務命名 -->
<dubbo:application name="service-provider"/>
<!-- 指定註冊中心 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<!-- 指定服務提供者和服務消費者的通訊協議 -->
<dubbo:protocol name="dubbo" port="20880"/>
<!--監控中心(不是必須的)-->
<dubbo:monitor protocol="registry"/>
<!-- 暴露服務介面及介面關聯的實現 -->
<dubbo:service interface="com.example.api.DemoService" ref="demoService" timeout="1000" retries="3">
<dubbo:method name="sayHello" timeout="2000"/>
</dubbo:service>
<bean id="demoService" class="com.example.provider.DemoServiceImpl"/>
</beans>
ProviderMain
package com.example.provider;
public class ProviderMain {
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("provider.xml");
context.start();
// 按任意鍵退出(阻塞程式停止結束)
System.in.read();
}
}
③ dubbo-client-consumer
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.example.consumer</groupId>
<artifactId>dubbo-client-consumer</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.3</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.13</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>com.example.api</groupId>
<artifactId>dubbo-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
src/main/resources/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://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://dubbo.apache.org/schema/dubbo
http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!-- 服務命名 -->
<dubbo:application name="client-consumer" />
<!-- 指定註冊中心 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<!--監控中心(不是必須的)-->
<dubbo:monitor protocol="registry"/>
<!-- 引用介面
timeout:服務呼叫超時時間,預設為1秒;
retries: 超時後重試次數(不包含第一次呼叫);
version: 版本號,可以在服務提供上對同一個類暴露多次,每次都指定一個版本號,服務消費者可以指定來使用哪個版本的服務,*表示隨機呼叫任意一本版本 -->
<dubbo:reference id="demoService" interface="com.example.api.DemoService" timeout="1000" retries="3"/>
</beans>
dubbo可以使用dubbo:reference針對介面做配置,也可以通過dubbo:method對介面的方法做配置,也可以使用dubbo:consumer用於全域性配置,越具體的配置優先順序越高
<dubbo:consumer timeout=“1000” retries=“3” check=“false”/>
package com.example.consumer;
public class ConsumerMain {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("consumer.xml");
context.start();
DemoService demoService = (DemoService)context.getBean("demoService");
String hello = demoService.sayHello("world");
System.out.println(hello);
// 阻塞程式結束
System.in.read();
}
}
先啟動zookeeper,然後再執行ProviderMain最後再執行ConsumerMain
重新整理控制檯
服務治理下有很多選單,可以檢視具體內容
四:API方式
使用ServiceConfig和ReferenceConfig API取代xml配置方式
public class ProviderMain {
public static void main(String[] args) throws IOException {
ServiceConfig<DemoService> serviceConfig = new ServiceConfig<DemoService>();
serviceConfig.setApplication(new ApplicationConfig("dubbo-service-provider"));
serviceConfig.setRegistry(new RegistryConfig("zookeeper://127.0.0.1:2181"));
serviceConfig.setInterface(DemoService.class);
serviceConfig.setRef(new DemoServiceImpl());
serviceConfig.export();
// 按任意鍵退出(阻塞程式停止結束)
System.in.read();
}
}
public class ConsumerMain {
public static void main(String[] args) {
ReferenceConfig<DemoService> referenceConfig = new ReferenceConfig<DemoService>();
referenceConfig.setApplication(new ApplicationConfig("dubbo-client-consumer"));
referenceConfig.setRegistry(new RegistryConfig("zookeeper://127.0.0.1:2181"));
referenceConfig.setInterface(DemoService.class);
DemoService demoService = referenceConfig.get();
String hello = demoService.sayHello("world");
System.out.println(hello);
// 阻塞程式結束
System.in.read();
}
}
五:Spring Boot
① 匯入dubbo-starter, 在application.properties配置屬性,使用@EnableDubbo開啟dubbo,使用@Service暴露服務,使用@Reference引用服務
注意:此種方式無法做到方法級別的配置
建立一個不依賴任何starter的Spring Boot工程springboot-dubbo-provider
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>
<dependency>
<groupId>com.example.api</groupId>
<artifactId>dubbo-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
@EnableDubbo 開啟Dubbo
@EnableDubbo
@SpringBootApplication
public class SpringbootDubboProviderApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootDubboProviderApplication.class, args);
}
}
application.properties
dubbo.application.name=springboot-dubbo-provider
dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
dubbo.monitor.protocol=registry
com.alibaba.dubbo.config.annotation.Service : 暴露介面
package com.example.dubbo.provider;
import com.alibaba.dubbo.config.annotation.Service;
@Service
@Component
public class DemoServiceImpl implements DemoService {
@Override
public String sayHello(String name) {
return "Hello " + name;
}
}
建立一個依賴Web starter的Spring Boot工程:springboot-dubbo-consumer
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>
<dependency>
<groupId>com.example.api</groupId>
<artifactId>dubbo-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
application.properties
server.port=8081
dubbo.application.name=springboot-dubbo-consumer
dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.monitor.protocol=registry
@EnableDubbo: 開啟Dubbo
@EnableDubbo
@SpringBootApplication
public class SpringbootDubboConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootDubboConsumerApplication.class, args);
}
}
@Reference:引用服務方提供的介面
@RestController
public class DemoController {
@Reference
private DemoService demoService;
@GetMapping("/sayHello")
public String sayHello(String name) {
return demoService.sayHello(name);
}
}
dubbo-api 一個普通的maven工程
package com.example.api;
public interface DemoService {
String sayHello(String name);
}
② 使用xml配置
匯入dubbo-starter, 配置使用xml配置(provider.xml、consumer.xml),application.properties就不需要任何dubbo配置,使用@ImportResource(location=“classpath:provider.xml”)來代替@EnableDubbo即可。
此種方式支援方法級別的配置。
③ 使用註解API
使用@Configuration來配置,使用@EnableDubbo開啟dubbo,使用@Service暴露介面,使用@Reference來引用介面。
每個標籤對應一個config類。如dubbo:application 對應ApplicationConfig
@Configuration
public class DubboConfiguration {
@Bean
public ApplicationConfig applicationConfig() {
ApplicationConfig applicationConfig = new ApplicationConfig();
applicationConfig.setName("springboot-dubbo-provider");
return applicationConfig;
}
@Bean
public RegistryConfig registryConfig() {
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setProtocol("zookeeper");
registryConfig.setAddress("127.0.0.1");
return registryConfig;
}
@Bean
public ProtocolConfig protocolConfig() {
ProtocolConfig protocolConfig = new ProtocolConfig();
protocolConfig.setName("dubbo");
protocolConfig.setPort(20882);
return protocolConfig;
}
@Bean
public ServiceConfig<DemoService> demoServiceServiceConfig(DemoService demoService) {
ServiceConfig<DemoService> serviceConfig = new ServiceConfig<>();
serviceConfig.setInterface(DemoService.class);
serviceConfig.setRef(demoService);
MethodConfig methodConfig = new MethodConfig();
methodConfig.setName("sayHello");
methodConfig.setTimeout(2000);
serviceConfig.setMethods(Arrays.asList(methodConfig));
return serviceConfig;
}
}
註冊中心和監控不是必須的,當註冊中心宕機了,仍不影響服務的呼叫,可以通過@Reference中的url屬性直接指定服務提供者對應的ip和埠 @Reference(url = “127.0.0.1:20880”) , 這就是 Dubbo直連 方式。
負載均衡:Dubbo預設使用隨機的RandomLoadBanlance,可以在多個地方來配置複雜均衡策略,如在消費放配置 @Reference(loadbalance = “roundrobin”)
Dubbo可以與Hystrix整合,使用@EnableHystrix來開啟,使用@HystrixCommand來標註服務提供者方法和使用@HystrixCommand(fallbackMethod=“xxx”)來標註消費方方法
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.3.1.RELEASE</version>
</dependency>