Dubbo学习笔记

一、发展演变

image-20191026210017355

单一应用架构

当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。此时,用于简化增删改查工作量的数据访问框架(ORM)是关键。

img

适用于小型网站,小型管理系统,将所有功能都部署到一个功能里,简单易用。

缺点: 1、性能扩展比较难

​ 2、协同开发问题

​ 3、不利于升级维护

垂直应用架构

当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个应用,以提升效率。此时,用于加速前端页面开发的Web框架(MVC)是关键。

img

通过切分业务来实现各个模块独立部署,降低了维护和部署的难度,团队各司其职更易管理,性能扩展也更方便,更有针对性。

缺点: 公用模块无法重复利用,开发性的浪费

分布式服务架构

当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复用及整合的****分布式服务框架(RPC)****是关键。

img

流动计算架构

当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。此时,用于提高机器利用率的资源调度和治理中心(SOA)[ Service Oriented Architecture]是关键

img

二、RPC的概念

1、RPC概念

RPC【Remote Procedure Call】是指远程过程调用,是一种进程间通信方式,他是一种技术的思想,而不是规范。它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,而不用程序员显式编码这个远程调用的细节。即程序员无论是调用本地的还是远程的函数,本质上编写的调用代码基本相同。

2、RPC基本原理

img

img

RPC两个核心模块:通讯序列化

三、Dubbo核心概念

1、简介

Apache Dubbo (incubating) |ˈdʌbəʊ| 是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用智能容错和负载均衡,以及服务自动注册和发现

官网:

http://dubbo.apache.org/

2、基本概念

img

  • 组件角色

服务提供者(Provider):暴露服务的服务提供方,服务提供者在启动时,向注册中心注册自己提供的服务。

服务消费者(Consumer): 调用远程服务的服务消费方,服务消费者在启动时,向注册中心订阅自己所需的服务,服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。

注册中心(Registry):注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者

监控中心(Monitor):服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心

  • 调用关系说明

l 服务容器负责启动,加载,运行服务提供者。

l 服务提供者在启动时,向注册中心注册自己提供的服务。

l 服务消费者在启动时,向注册中心订阅自己所需的服务。

l 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。

l 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。

l 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

四、Dubbo环境搭建

1、安装注册中心Zookeeper(windows)

1.1 下载zookeeper

官网下载网址 https://archive.apache.org/dist/zookeeper/zookeeper-3.4.13/

1.2 解压zookeeper

解压后运行zkServer.cmd,初次运行会报错,原因是没有zoo.cfg配置文件。

1.3 修改zoo.cfg配置文件

conf下的zoo_sample.cfg复制一份改名为zoo.cfg即可。

注意几个重要位置:

1
2
dataDir=../data       #临时数据存储的目录(可写相对路径)
clientPort=2181 #zookeeper的端口号

修改完成后再次启动zkServer.cmd

1.4 测试是否搭建完成

点击运行zkCli.cmd

1
2
3
ls /                      #列出zookeeper根下保存的所有节点
create -e /qcmoke 123456 #创建一个qcmoke节点,值为123456
get /qcmoke #获取/qcmoke节点的值,如果出来数据就表示搭建完成

Zookeeper是一个树型的目录服务,支持变更推送,可作为 Dubbo 服务的注册中心。

zookeeper.jpg

2、安装管理控制台dubbo-admin

2.1下载dubbo-admin

下载地址:https://github.com/apache/incubator-dubbo-ops

2.2 进入dubbo-admin目录,修改dubbo-admin配置

修改src\main\resources\application.properties 指定zookeeper地址。

1
2
3
spring.guest.password=guest

dubbo.registry.address=zookeeper://127.0.0.1:2181

2.3 运行打包

dubbo-admin/目录里执行命令运行打包dubbo-admin

1
mvn clean package -Dmaven.test.skip=true

2.4 运行dubbo-admin

dubbo-admin/target目录里执行命令运行dubbo-admin

1
java -jar dubbo-admin-0.0.1-SNAPSHOT.jar #注意要先启动zookeeper

2.5 访问监控管理控制台

http://localhost:7001

默认使用root/root登陆

image-20191026221745695

五、Spring中使用Dubbo

某个电商系统,订单服务需要调用用户服务获取某个用户的所有地址;

我们现在 需要创建两个服务模块进行测试

模块 功能
订单服务web模块 创建订单等
用户服务service模块 查询用户地址等

测试预期结果:

​ 订单服务web模块在A服务器,用户服务模块在B服务器,A可以远程调用B的功能。

1. 创建如下三个maven工程

1
2
3
4
.
├── gmall-interface #公共模块,多服务之间的公共接口和实体类
├── order-service-consumer #服务提供者,订单服务web模块
└── user-service-provider #服务消费者,用户服务service模块

1.1 gmall-interface模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.
├── pom.xml
└── src
└── main
├── java
│   └── com
│   └── qcmoke
│   └── gmall
│   ├── bean
│   │   └── UserAddress.java
│   └── service
│   ├── OrderService.java
│   └── UserService.java
└── resources

pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?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.qcmoke.gmall</groupId>
<artifactId>gmall-interface</artifactId>
<version>1.0-SNAPSHOT</version>


<dependencies>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.20</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

com.qcmoke.gmall.bean.UserAddress.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.qcmoke.gmall.bean;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
* 用户地址
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserAddress implements Serializable {

private Integer id;
private String userAddress; //用户地址
private String userId; //用户id
private String consignee; //收货人
private String phoneNum; //电话号码
private String isDefault; //是否为默认地址 Y-是 N-否
}

com.qcmoke.gmall.service.OrderService.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.qcmoke.gmall.service;

import com.qcmoke.gmall.bean.UserAddress;

import java.util.List;

public interface OrderService {
/**
* 初始化订单
*
* @param userId
*/
public List<UserAddress> initOrder(String userId);
}

com.qcmoke.gmall.service.UserService.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.qcmoke.gmall.service;

import com.qcmoke.gmall.bean.UserAddress;

import java.util.List;

/**
* 用户服务
*/
public interface UserService {

/**
* 按照用户id返回所有的收货地址
*
* @param userId
* @return
*/
public List<UserAddress> getUserAddressList(String userId);

}

1.2 order-service-consumer模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.
├── pom.xml
└── src
└── main
├── java
│   └── com
│   └── qcmoke
│   └── gmall
│   ├── MainApplication.java
│   └── service
│   └── impl
│   ├── UserServiceImpl.java
└── resources
└── provider.xml

pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?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.qcmoke.gmall</groupId>
<artifactId>order-service-consumer</artifactId>
<version>0.0.1-SNAPSHOT</version>

<dependencies>
<dependency>
<groupId>com.qcmoke.gmall</groupId>
<artifactId>gmall-interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

<!-- 引入dubbo -->
<!-- https://mvnrepository.com/artifact/com.alibaba/dubbo -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</version>
</dependency>
<!-- 注册中心使用的是zookeeper,引入操作zookeeper的客户端端 -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.12.0</version>
</dependency>

</dependencies>

</project>

com.qcmoke.gmall.service.impl.UserServiceImpl.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.qcmoke.gmall.service.impl;

import com.qcmoke.gmall.bean.UserAddress;
import com.qcmoke.gmall.service.UserService;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;

@Service("userServiceImpl01")
public class UserServiceImpl implements UserService {

@Override
public List<UserAddress> getUserAddressList(String userId) {
System.out.println("UserServiceImpl.....old...");
// TODO Auto-generated method stub
UserAddress address1 = new UserAddress(1, "北京市昌平区宏福科技园综合楼3层", "1", "李老师", "010-56253825", "Y");
UserAddress address2 = new UserAddress(2, "深圳市宝安区西部硅谷大厦B座3层(深圳分校)", "1", "王老师", "010-56253825", "N");
/*try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
return Arrays.asList(address1, address2);
}

}

provider.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

<context:component-scan base-package="com.qcmoke.gmall.service.impl"/>

<!-- 1、指定当前服务/应用的名字(同样的服务名字相同,不要和别的服务同名) ==》只要服务已启动就会注册到zookeeper注册中心了-->
<dubbo:application name="user-service-provider"/>

<!-- 2、指定注册中心的位置 -->
<!-- <dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry> -->
<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"/>

<!-- 3、指定通信规则 ===》用于服务提供者和消费者之间的通信
name:通信协议(有规定要求)
port:通信端口(可自定义)
-->
<dubbo:protocol name="dubbo" port="20882"/>

<!-- 4、暴露服务 ===》用于给服务消费者提供服务
<dubbo:service>
interface:暴露的接口
ref:指向服务的真正的实现对象
-->
<dubbo:service interface="com.qcmoke.gmall.service.UserService" ref="userServiceImpl01"/>
</beans>

com.qcmoke.gmall.MainApplication.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.qcmoke.gmall;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;

public class MainApplication {

public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("provider.xml");//加载配合文件
ioc.start();//启动ioc容器
System.in.read();//读取一个字符用于阻塞,防止ioc容器运行终止
}
}

1.3 user-service-provider模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.
├── pom.xml
├── src
│   └── main
│   ├── java
│   │   └── com
│   │   └── qcmoke
│   │   └── gmall
│   │   ├── MainApplication.java
│   │   └── service
│   │   └── impl
│   │   └── OrderServiceImpl.java
│   └── resources
│   └── consumer.xml

pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?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.qcmoke.gmall</groupId>
<artifactId>user-service-provider</artifactId>
<version>1.0-SNAPSHOT</version>


<dependencies>
<dependency>
<groupId>com.qcmoke.gmall</groupId>
<artifactId>gmall-interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

<!-- 引入dubbo -->
<!-- https://mvnrepository.com/artifact/com.alibaba/dubbo -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</version>
</dependency>
<!-- 注册中心使用的是zookeeper,引入操作zookeeper的客户端端 -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.12.0</version>
</dependency>

</dependencies>

</project>

com.qcmoke.gmall.service.impl.OrderServiceImpl.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.qcmoke.gmall.service.impl;


import com.qcmoke.gmall.bean.UserAddress;
import com.qcmoke.gmall.service.OrderService;
import com.qcmoke.gmall.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class OrderServiceImpl implements OrderService {

@Autowired
UserService userService;

@Override
public List<UserAddress> initOrder(String userId) {
System.out.println("用户id:" + userId);
//远程调用user-service-provider服务的UserServiceImpl.getUserAddressList(String userId)
List<UserAddress> addressList = userService.getUserAddressList(userId);
for (UserAddress userAddress : addressList) {
System.out.println(userAddress.getUserAddress());
}
return addressList;
}
}

consumer.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<context:component-scan base-package="com.qcmoke.gmall.service.impl"/>

<!-- 1、指定当前服务/应用的名字-->
<dubbo:application name="order-service-consumer"/>
<!-- 2、指定注册中心的位置 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<!--3、指定要调用的远程服务;声明需要调用的远程服务的接口;生成远程服务代理
interface: 调用的远程服务接口
id: 远程服务接口的名称
-->
<dubbo:reference interface="com.qcmoke.gmall.service.UserService" id="userService"/>
</beans>

com.qcmoke.gmall.MainApplication.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.qcmoke.gmall;

import com.qcmoke.gmall.service.OrderService;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;


public class MainApplication {

@SuppressWarnings("resource")
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("consumer.xml");
OrderService orderService = ioc.getBean(OrderService.class);
orderService.initOrder("1");
System.out.println("调用完成....");
System.in.read();
}

}

1.4 测试

启动zookeeper,然后启动dubbo-admin,再启动user-service-provider,最后启动order-service-consumer。

查看order-service-consumer的输出结果。

image-20191027061734536

image-20191027061351371

2. 安装监控中心

1、下载 dubbo-ops

https://github.com/apache/incubator-dubbo-ops

2、打包dubbo-monitor-simple

进入incubator-dubbo-ops-master/dubbo-monitor-simple下运行以下命令

1
2
$ mvn package
#mvn clean package -Dmaven.test.skip=true

3. 进入target/目录

解压dubbo-monitor-simple-2.0.0-assembly.tar.gz得到dubbo-monitor-simple-2.0.0,并将之移动到非target的目录去。

修改dubbo-monitor-simple-2.0.0/conf/dubbo.properties的以下三处必要配置:

1
2
3
4
5
6
# 注册中心的地址
dubbo.registry.address=zookeeper://127.0.0.1:2181
# 其他服务与监控中心的通信端口
dubbo.protocol.port=7070
# 监控中心的web访问端口
dubbo.jetty.port=8080

4、运行启动监控中心monitor

运行dubbo-monitor-simple-2.0.0/assembly.bin/start.bat

注意:前提要先启动zookeeper和dubbo-admin

5、启动访问monitor管理页面

访问 http://localhost:8080

image-20191027153609047

6、服务中配置monitor

在服务的ioc容器中配置如下已能够和监控中心建立连接关系。

1
2
3
4
5
<!-- 连接监控中心
protocol="registry":表示当前服务从注册中心发现监控中心的地址。
address="127.0.0.1:7070":表示当前服务是直连监控中心,而不是从注册中心发现的。
-->
<dubbo:monitor protocol="registry"/> <!--<dubbo:monitor address="127.0.0.1:7070"/>-->

修改order-service-consumer模块的consumer.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<context:component-scan base-package="com.qcmoke.gmall.service.impl"/>

<!-- 1、指定当前服务/应用的名字-->
<dubbo:application name="order-service-consumer"/>
<!-- 2、指定注册中心的位置 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<!--3、指定要调用的远程服务;声明需要调用的远程服务的接口;生成远程服务代理
interface: 调用的远程服务接口
id: 远程服务接口的名称
-->
<dubbo:reference interface="com.qcmoke.gmall.service.UserService" id="userService"/>


<!-- 连接监控中心
protocol="registry":表示当前服务从注册中心发现监控中心的地址。
address="127.0.0.1:7070":表示当前服务是直连监控中心,而不是从注册中心发现的。
-->
<dubbo:monitor protocol="registry"/> <!--<dubbo:monitor address="127.0.0.1:7070"/>-->
</beans>

修改user-service-provider的provider.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

<context:component-scan base-package="com.qcmoke.gmall.service.impl"/>

<!-- 1、指定当前服务/应用的名字(同样的服务名字相同,不要和别的服务同名) ==》只要服务已启动就会注册到zookeeper注册中心了-->
<dubbo:application name="user-service-provider"/>

<!-- 2、指定注册中心的位置 -->
<!-- <dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry> -->
<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"/>

<!-- 3、指定通信规则 ===》用于服务提供者和消费者之间的通信
name:通信协议(有规定要求)
port:通信端口(可自定义)
-->
<dubbo:protocol name="dubbo" port="20882"/>

<!-- 4、暴露服务 ===》用于给服务消费者提供服务
<dubbo:service>
interface:暴露的接口
ref:指向服务的真正的实现对象
-->
<dubbo:service interface="com.qcmoke.gmall.service.UserService" ref="userServiceImpl01"/>


<!-- 连接监控中心
protocol="registry":表示当前服务从注册中心发现监控中心的地址。
address="127.0.0.1:7070":表示当前服务是直连监控中心,而不是从注册中心发现的。
-->
<dubbo:monitor protocol="registry"/> <!--<dubbo:monitor address="127.0.0.1:7070"/>-->
</beans>

7、测试monitor

启动顺序:zookeepe—>dubbo-admin—>monitor—>user-service-provider—>order-service-consumer

image-20191027155804297

六、SpringBoot中使用Dubbo

1、概述

对于服务提供者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1.引入依赖
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>

2.配置文件
# 服务唯一名称
dubbo.application.name=user-service-provider
# 注册中心协议和地址
dubbo.registry.protocol=zookeeper
dubbo.registry.address=127.0.0.1:2181
# 通信协议和端口
dubbo.protocol.name=dubbo
#dubbo.protocol.port=20881
# 监控中心
dubbo.monitor.protocol=registry

3.注解
在启动类上加@EnableDubbo
在需要暴露的服务上使用@com.alibaba.dubbo.config.annotation.Service

对于服务消费者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1.引入依赖
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>

2.配置文件
server.port=8081
dubbo.application.name=boot-order-service-consumer
dubbo.registry.protocol=zookeeper
dubbo.registry.address=127.0.0.1:2181
dubbo.monitor.protocol=registry

3.注解
在启动类上加@EnableDubbo
在注入远程服务对象时使用的是@Reference

3、三个maven模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
.
├── boot-order-service-consumer
│   ├── pom.xml
│   └── src
│   └── main
│   ├── java
│   │   └── com
│   │   └── qcmoke
│   │   └── gmall
│   │   ├── ConsumerBootApplication.java
│   │   ├── controller
│   │   │   └── OrderController.java
│   │   └── service
│   │   └── impl
│   │   └── OrderServiceImpl.java
│   └── resources
│   └── application.properties
├── boot-user-service-provider
│   ├── pom.xml
│   └── src
│   └── main
│   ├── java
│   │   └── com
│   │   └── qcmoke
│   │   └── gmall
│   │   ├── ProviderBootApplication.java
│   │   └── service
│   │   └── impl
│   │   └── UserServiceImpl.java
│   └── resources
│   └── application.properties
├── gmall-interface
│   ├── pom.xml
│   └── src
│   └── main
│   ├── java
│   │   └── com
│   │   └── qcmoke
│   │   └── gmall
│   │   ├── bean
│   │   │   └── UserAddress.java
│   │   └── service
│   │   ├── OrderService.java
│   │   └── UserService.java
│   └── resources

1.1 gmall-interface

和“SpringBoot中使用Dubbo”中的内容一样,这里不再阐述。

1.2 boot-user-service-provider模块

pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.qcmoke.gmall</groupId>
<artifactId>boot-user-service-provider</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>boot-user-service-provider</name>
<description>Demo project for Spring Boot</description>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>


<dependencies>
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>

<dependency>
<groupId>com.qcmoke.gmall</groupId>
<artifactId>gmall-interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>

com.qcmoke.gmall.ProviderBootApplication.java

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.qcmoke.gmall;

import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@EnableDubbo
@SpringBootApplication
public class ProviderBootApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderBootApplication.class, args);
}
}

com.qcmoke.gmall.service.impl.UserServiceImpl.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.qcmoke.gmall.service.impl;

import com.qcmoke.gmall.bean.UserAddress;
import com.qcmoke.gmall.service.UserService;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;

@com.alibaba.dubbo.config.annotation.Service//暴露服务,并注册到注册中心
@Service
public class UserServiceImpl implements UserService {

@Override
public List<UserAddress> getUserAddressList(String userId) {
System.out.println("UserServiceImpl..服务1.....");
UserAddress address1 = new UserAddress(1, "北京东路", "1", "李老师", "010-123456", "Y");
UserAddress address2 = new UserAddress(2, "深圳宝安", "1", "王老师", "010-123457", "N");

/*
//模拟异常报错
if (Math.random() > 0.5) {
throw new RuntimeException();
}
*/

return Arrays.asList(address1, address2);
}
}

application.properties

1
2
3
4
5
6
7
8
9
10
11
12
# 服务唯一名称
dubbo.application.name=boot-user-service-provider
# 注册中心协议和地址
dubbo.registry.address=zookeeper://127.0.0.1:2181
# 通信协议和端口
dubbo.protocol.name=dubbo
dubbo.protocol.port=20881
# 监控中心
dubbo.monitor.protocol=registry

#配置Dubbo缓存文件。如果在本地同时启动同一个项目的多个实例,那么server.port、dubbo.protocol.port、dubbo.registry.file都不能相同。否则报错。
#dubbo.registry.file=F:/Code/dubbo/cache/boot-user-service-provider8081.cache

1.3 boot-order-service-consumer模块

pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.qcmoke.gmall</groupId>
<artifactId>boot-order-service-consumer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>boot-order-service-consumer</name>
<description>Demo project for Spring Boot</description>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>

<dependencies>
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>

<dependency>
<groupId>com.qcmoke.gmall</groupId>
<artifactId>gmall-interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>

com.qcmoke.gmall.ConsumerBootApplication.java

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.qcmoke.gmall;

import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@EnableDubbo
@SpringBootApplication
public class ConsumerBootApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerBootApplication.class, args);
}
}

com.qcmoke.gmall.service.impl.OrderServiceImpl.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.qcmoke.gmall.service.impl;

import com.alibaba.dubbo.config.annotation.Reference;
import com.qcmoke.gmall.bean.UserAddress;
import com.qcmoke.gmall.service.OrderService;
import com.qcmoke.gmall.service.UserService;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class OrderServiceImpl implements OrderService {
//@Autowired
@Reference
UserService userService;

@Override
public List<UserAddress> initOrder(String userId) {
List<UserAddress> addressList = userService.getUserAddressList(userId);
return addressList;
}
}

com.qcmoke.gmall.controller.OrderController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.qcmoke.gmall.controller;

import com.qcmoke.gmall.bean.UserAddress;
import com.qcmoke.gmall.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class OrderController {
@Autowired
OrderService orderService;

@RequestMapping("/initOrder")//http://127.0.0.1:8081/initOrder?uid=1
public List<UserAddress> initOrder(@RequestParam("uid") String userId) {
System.out.println("/initOrder");
return orderService.initOrder(userId);
}
}

application.properties

1
2
3
4
5
server.port=8081
dubbo.application.name=boot-order-service-consumer
dubbo.registry.protocol=zookeeper
dubbo.registry.address=127.0.0.1:2181
dubbo.monitor.protocol=registry

1.4 测试

启动顺序:zookeepe—>dubbo-admin—>monitor—>boot-user-service-providerr—>boot-order-service-consumer

访问http://127.0.0.1:8081/initOrder?uid=1

七、dubbo配置

1、配置优先原则

img

★ JVM 启动 -D 参数优先,这样可以使用户在部署和启动时进行参数重写,比如在启动时需改变协议的端口。

★ XML 次之,如果在 XML 中有配置,则 dubbo.properties 中的相应配置项无效。

★ Properties 最后,相当于缺省值,只有 XML 没有配置时,dubbo.properties 的相应配置项才会生效,通常用于共享公共配置,比如应用名。

对boot-user-service-provider模块做一下修改:

application.properties(想当于xml):

1
2
3
4
5
6
7
8
9
# 服务唯一名称
dubbo.application.name=boot-user-service-provider
# 注册中心协议和地址
dubbo.registry.address=zookeeper://127.0.0.1:2181
# 通信协议和端口
dubbo.protocol.name=dubbo
dubbo.protocol.port=20881
# 监控中心
dubbo.monitor.protocol=registry

dubbo.properties:

1
dubbo.protocol.port=20882

由于application.properties优先级更高,启动后会发现dubbo.properties的20882端口会被application.properties的20881端口覆盖。

2、重试次数

失败自动切换,当出现失败,重试其它服务器,但重试会带来更长延迟。可通过 retries=“2” 来设置重试次数(不含第一次)。

重试次数配置如下:

1
2
服务提供者:
<dubbo:service retries="2" />
1
2
3
4
5
6
7
服务消费者:
(1)全局重试次数配置
<dubbo:reference retries="2" />
(2)指定接口以及特定方法重试次数配置
<dubbo:reference>
<dubbo:method name="findFoo" retries="2" />
</dubbo:reference>

3、超时时间配置

由于网络或服务端不可靠,会导致调用出现一种不确定的中间状态(超时)。为了避免超时导致客户端资源(线程)挂起耗尽,必须设置超时时间。

1
2
3
4
5
6
7
8
9
10
消费端:
(1)全局超时配置
<dubbo:consumer timeout="5000" />

(2)指定接口以及特定方法超时配置
//设置消费者请求服务者某个服务所有方法的超时时间为2000ms
<dubbo:reference interface="com.foo.BarService" timeout="2000">
//明确指定某个方法的超时时间为3000ms
<dubbo:method name="sayHello" timeout="3000" />
</dubbo:reference>
1
2
3
4
5
6
7
8
服务端:
(1)全局超时配置
<dubbo:provider timeout="5000" />

(2)指定接口以及特定方法超时配置
<dubbo:provider interface="com.foo.BarService" timeout="2000">
<dubbo:method name="sayHello" timeout="3000" />
</dubbo:provider>

如果消费端和服务端都配置同样的超时配置,那么消费端的配置优于服务端配置

4、配置原则

配置的覆盖规则

  1. 方法级配置别优于接口级别,即小Scope优先

  2. Consumer端配置 优于 Provider配置 优于 全局配置,

  3. 最后是Dubbo Hard Code的配置值(见配置文档)

img

dubbo推荐在Provider上尽量多配置Consumer端属性:

(1)作服务的提供者,比服务使用方更清楚服务性能参数,如调用的超时时间,合理的重试次数,等等

(2)在Provider配置后,Consumer不配置则会使用Provider的配置值,即Provider配置可以作为Consumer的缺省值。否则,Consumer会使用Consumer端的全局设置,这对于Provider不可控的,并且往往是不合理的

5、版本号

当一个接口实现,出现不兼容升级时,可以用版本号过渡,版本号不同的服务相互间不引用。

可以按照以下的步骤进行版本迁移:

在低压力时间段,先升级一半提供者为新版本

再将所有消费者升级为新版本

然后将剩下的一半提供者升级为新版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
老版本服务提供者配置:
<dubbo:service interface="com.foo.BarService" version="1.0.0" />

新版本服务提供者配置:
<dubbo:service interface="com.foo.BarService" version="2.0.0" />

老版本服务消费者配置:
<dubbo:reference id="barService" interface="com.foo.BarService" version="1.0.0" />

新版本服务消费者配置:
<dubbo:reference id="barService" interface="com.foo.BarService" version="2.0.0" />

如果不需要区分版本,可以按照以下的方式配置:
<dubbo:reference id="barService" interface="com.foo.BarService" version="*" />

对user-service-provider模块做修改:

provider.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

<context:component-scan base-package="com.qcmoke.gmall.service.impl"/>

<!-- 1、指定当前服务/应用的名字(同样的服务名字相同,不要和别的服务同名) ==》只要服务已启动就会注册到zookeeper注册中心了-->
<dubbo:application name="user-service-provider"/>

<!-- 2、指定注册中心的位置 -->
<!-- <dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry> -->
<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"/>

<!-- 3、指定通信规则 ===》用于服务提供者和消费者之间的通信
name:通信协议(有规定要求)
port:通信端口(可自定义)
-->
<dubbo:protocol name="dubbo" port="20882"/>

<!-- 4、暴露服务 ===》用于给服务消费者提供服务
<dubbo:service>
interface:暴露的接口
ref:指向服务的真正的实现对象
version: 当有同接口的多个不同实现类时,可以使用ref和version共同确定版本以提供给消费者选择。
-->
<dubbo:service interface="com.qcmoke.gmall.service.UserService" ref="userServiceImpl01" version="0.0.1"/>
<dubbo:service interface="com.qcmoke.gmall.service.UserService" ref="userServiceImpl02" version="0.0.2"/>

<!-- 连接监控中心
protocol="registry":表示当前服务从注册中心发现监控中心的地址。
address="127.0.0.1:7070":表示当前服务是直连监控中心,而不是从注册中心发现的。
-->
<dubbo:monitor protocol="registry"/> <!--<dubbo:monitor address="127.0.0.1:7070"/>-->
</beans>

添加实现类com.qcmoke.gmall.service.impl.UserServiceImpl2.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.qcmoke.gmall.service.impl;

import com.qcmoke.gmall.bean.UserAddress;
import com.qcmoke.gmall.service.UserService;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;

@Service("userServiceImpl02")
public class UserServiceImpl2 implements UserService {

@Override
public List<UserAddress> getUserAddressList(String userId) {
System.out.println("UserServiceImpl.....new...");
UserAddress address1 = new UserAddress(1, "南京", "1", "李老师", "010-56253825", "Y");
UserAddress address2 = new UserAddress(2, "杭州", "1", "王老师", "010-56253825", "N");

return Arrays.asList(address1, address2);
}
}

对order-service-consumer模块做修改:

consumer.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<context:component-scan base-package="com.qcmoke.gmall.service.impl"/>

<!-- 1、指定当前服务/应用的名字-->
<dubbo:application name="order-service-consumer"/>
<!-- 2、指定注册中心的位置 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<!--3、指定要调用的远程服务;声明需要调用的远程服务的接口;生成远程服务代理
interface: 调用的远程服务接口
id: 远程服务接口的名称
check:设置启动时是否检查注册中心中有服务提供者(默认true,检查),如果想要配置当前所有的服务都启动不检查注册中心中有服务提供者那么可以统一配置:<dubbo:consumer check="false" timeout="5000"/>
retries:设置失败重试次数,0表示不重试(默认)。
是否使用重试?
幂等,就是多次执行方法得到的结果一样,比如查询、删除、修改,这种情况可以设置重试次数。
非幂等,就是多次执行方法得到的结果不一样,比如数据库新增操作,即使参数相同新增后数据库记录会变多,这种情况不能设置重试次数。
version:在服务提供者使用version指定版本的时候,可以在消费者上指定对应的版本来确定同一接口的具体实现类对象。
-->
<dubbo:reference interface="com.qcmoke.gmall.service.UserService" id="userService" retries="3" version="0.0.1"/>


<!-- 连接监控中心
protocol="registry":表示当前服务从注册中心发现监控中心的地址。
address="127.0.0.1:7070":表示当前服务是直连监控中心,而不是从注册中心发现的。
-->
<dubbo:monitor protocol="registry"/> <!--<dubbo:monitor address="127.0.0.1:7070"/>-->


<!--
(1)全局超时配置
<dubbo:consumer timeout="5000" />
(2)指定接口以及特定方法超时配置
<dubbo:reference interface="com.qcmoke.gmall.service.UserService" id="userService" timeout="5000"> 设置消费者请求服务者某个服务所有方法的超时时间为5000ms
<dubbo:method name="getUserAddressList" timeout="1000"/> 明确指定某个方法的超时时间为1000ms
</dubbo:reference>
-->
</beans>

运行两个服务后观察消费者的输出:

1
2
3
4
用户id:1
南京
杭州
调用完成....

八、熔断与降级

整合hystrix,可实现服务的熔断与降级。

Hystrix 旨在通过控制那些访问远程系统、服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。Hystrix具备拥有回退机制和断路器功能的线程和信号隔离,请求缓存和请求打包,以及监控和配置等功能。

1. 使用hystrix

1.1 创建提供者模块

  • boot-user-service-provider-hystrix

除了添加dubbo依赖和gmall-interface外,还有添加如下netflix依赖:

1
2
3
4
5
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>

完整pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?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.qcmoke.gmall</groupId>
<artifactId>boot-user-service-provider-hystrix</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<!--<version>2.1.7.RELEASE</version>-->
<relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>


<dependencies>
<dependency>
<groupId>com.qcmoke.gmall</groupId>
<artifactId>gmall-interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>

<!-- Dubbo Spring Boot Starter -->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>

</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>

创建启动类并在类上增加@EnableHystrix注解。

HystrixProviderBootApplication.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.qcmoke.gmall;

import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;

@EnableDubbo
@EnableHystrix
@SpringBootApplication
public class HystrixProviderBootApplication {
public static void main(String[] args) {
SpringApplication.run(HystrixProviderBootApplication.class, args);
}
}

配置application.properties

1
2
3
4
5
server.port=8081
dubbo.application.name=boot-user-service-provider-hystrix
dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.protocol.name=dubbo
dubbo.protocol.port=20881

UserServiceImpl.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.qcmoke.gmall.service.impl;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.qcmoke.gmall.bean.UserAddress;
import com.qcmoke.gmall.service.UserService;
import org.springframework.stereotype.Service;

import java.util.List;

@com.alibaba.dubbo.config.annotation.Service
@Service
public class UserServiceImpl implements UserService {

@HystrixCommand
@Override
public List<UserAddress> getUserAddressList(String userId) {
throw new RuntimeException("Exception to show hystrix enabled.");
}
}

1.2 创建消费者模块

  • boot-order-service-consumer-hystrix

pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.qcmoke.gmall</groupId>
<artifactId>boot-order-service-consumer-hystrix</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<!--<version>2.1.7.RELEASE</version>-->
<relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>


<dependencies>
<dependency>
<groupId>com.qcmoke.gmall</groupId>
<artifactId>gmall-interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- Dubbo Spring Boot Starter -->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>

</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>

application.properties

1
2
3
4
server.port=80
dubbo.application.name=boot-order-service-consumer-hystrix
dubbo.registry.protocol=zookeeper
dubbo.registry.address=127.0.0.1:2181

HystrixConsumerBootApplication.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.qcmoke.gmall;

import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;

@EnableDubbo
@EnableHystrix
@SpringBootApplication
public class HystrixConsumerBootApplication {
public static void main(String[] args) {
SpringApplication.run(HystrixConsumerBootApplication.class, args);
}
}

UserController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.qcmoke.gmall.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.qcmoke.gmall.bean.UserAddress;
import com.qcmoke.gmall.service.UserService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.Collections;
import java.util.List;


@RestController
public class UserController {
@Reference
private UserService userService;

@HystrixCommand(fallbackMethod = "getUserAddressListHystrix")
@RequestMapping("/getUserAddressList")
public List<UserAddress> getUserAddressList(@RequestParam("uid") String userId) {
System.out.println("/getUserAddressList");
return userService.getUserAddressList(userId);
}

public List<UserAddress> getUserAddressListHystrix(@RequestParam("uid") String userId) {
System.out.println("/getUserAddressListHystrix");
UserAddress address = new UserAddress(null, null, null, null, null, null);
return Collections.singletonList(address);
}
}

测试:

先启动提供者,然后启动消费者

访问http://127.0.0.1/getUserAddressList?uid=1

返回结果:

1
[{"id":null,"userAddress":null,"userId":null,"consignee":null,"phoneNum":null,"isDefault":null}]

九、负载均衡



----------- 本文结束 -----------




如果你觉得我的文章对你有帮助,你可以打赏我哦~
0%