1. 程式人生 > >Spring Boot入門教程(四十九): Dubbo

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>