前言

我们接着上一节。在许多场景下,外部请求需要查询Zuul后端的多个微服务。比如一个电影售票手机APP,在购票订单页上,既需要查询“电影微服务”获得电影相关信息,又需要查询“用户微服务”获得当前用户信息。如果让手机端直接请求各个微服务(即使使用Zuul进行转发),那么网络开销,流量耗费,耗费时长可能都无法令人满意。那么对于这种场景,可使用Zuul聚合微服务请求——手机APP发送一次请求给Zuul,由Zuul请求用户微服务以及电影微服务,并组织好数据给手机APP。

使用这种方式,在手机端只需发送一次请求即可,简化了客户端侧的开发;不仅如此,由于Zuul,用户微服务,电影微服务一般都在同一个局域网中,因此速度会非常快,效率会非常高。

编码

1.复制项目microservice-gateway-zuul,将ArtifactId修改为microservice-gateway-zuul-aggregation.

2.修改启动类。

@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication { public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
} }

3.创建实体类。

public class User {
private Long id;
private String username;
private String name;
private Integer age;
private BigDecimal balance; // getters and setters... }

4.创建java类。

@Service
public class AggregationService {
@Autowired
private RestTemplate restTemplate; @HystrixCommand(fallbackMethod = "fallback")
public Observable<User> getUserById(Long id){ // 创建一个被发现者
return Observable.create(observer -> {
User user = restTemplate.getForObject(
"http://microservice-provider-user/{id}",User.class,id);
observer.onNext(user);
observer.onCompleted();
});
}
@HystrixCommand(fallbackMethod = "fallback")
public Observable<User> getMovieUserByUserId(Long id){
return Observable.create(observer -> {
User movieUser = restTemplate.getForObject(
"http://microservice-consumer-movie/user/{id}",User.class,id);
observer.onNext(movieUser);
observer.onCompleted();
});
} public User fallback(Long id) {
User user = new User();
user.setId(-1L);
return user;
} }

5.创建Controller,在Controller中聚合多个微服务请求。

@RestController
public class AggregationController {
public static final Logger LOGGER = LoggerFactory.getLogger(ZuulApplication.class); @Autowired
private AggregationService aggregationService;
@GetMapping("/aggregate/{id}")
public DeferredResult<HashMap<String,User>> aggregate(@PathVariable Long id){ Observable<HashMap<String,User>> result = this.aggregateObservable(id);
return this.toDeferredResult(result); } public Observable<HashMap<String,User>> aggregateObservable(Long id){ // 合并两个或者多个Observeables发射出的数据项,根据指定的函数变换它们
return Observable.zip(
this.aggregationService.getUserById(id),
this.aggregationService.getMovieUserByUserId(id),
(user,movieUser) -> {
HashMap<String,User> map = Maps.newHashMap(); map.put("user",user);
map.put("movieUser",movieUser);
return map;
}
);
}
public DeferredResult<HashMap<String,User>> toDeferredResult(Observable<HashMap<String,User>> details){ DeferredResult<HashMap<String,User>> result = new DeferredResult<>();
// 订阅
details.subscribe(new Observer<HashMap<String,User>>(){
@Override
public void onCompleted() {
LOGGER.info("完成...");
} @Override
public void onError(Throwable throwable) {
LOGGER.error("发生错误...",throwable);
}
@Override
public void onNext(HashMap<String,User> movieDetails) {
result.setResult(movieDetails);
} });
return result;
} }

这样,代码就编写完了。当然,这里是用RxJava写的。也可以不用这种方式。只要实现调用多个微服务请求,然后将结果数据组织好返回出去就行。

测试1

启动项目microservice-discovery-eureka.

启动项目microservice-provider-user.

启动项目microservice-consumer-movie.

启动项目microservice-gateway-zuul-aggregation.

访问http://localhost:8040/aggregate/1,获得结果。

<HashMap>
<movieUser>
<id>1</id>
<username>account1</username>
<name>张三</name>
<age>20</age>
<balance>98.23</balance>
</movieUser>
<user>
<id>1</id>
<username>account1</username>
<name>张三</name>
<age>20</age>
<balance>98.23</balance>
</user>
</HashMap>

说明已成功用Zuul聚合了用户微服务以及电影微服务的RESTful API.

测试2

1.在测试1基础上停止项目microservice-provider-user以及microservice-consumer-movie.

2.访问http://localhost:8040/aggregate/1

<HashMap>
<movieUser>
<id>-1</id>
<username/>
<name/>
<age/>
<balance/>
</movieUser>
<user>
<id>-1</id>
<username/>
<name/>
<age/>
<balance/>
</user>
</HashMap>

我们看到,Zuul聚合微服务也实现了容错机制。

代码下载地址:https://gitee.com/fengyuduke/my_open_resources/blob/master/microservice-gateway-zuul-aggregation.zip

springcloud(十一)-Zuul聚合微服务的更多相关文章

  1. springcloud使用Zuul构建微服务网关入门

    为什么要使用微服务网关 不同的微服务一般会经过不同的网络地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求. 如果让客户端直接与各个微服务通信,会有以下的问题: 客户端会多次请求不同的微 ...

  2. Spring Cloud(Dalston.SR5)--Zuul 网关-微服务集群

    通过 url 映射的方式来实现 zuul 的转发有局限性,比如每增加一个服务就需要配置一条内容,另外后端的服务如果是动态来提供,就不能采用这种方案来配置了.实际上在实现微服务架构时,服务名与服务实例地 ...

  3. 8. 使用Zuul构建微服务网关

                    使用Zuul构建微服务网关 8.1. 为什么要使用微服务网关 8.2. Zuul简介 8.3. 编写Zuul微服务网关 8.4. Zuul的路由端点 8.5. Zuul ...

  4. SpringCloud实战 | 第五篇:SpringCloud整合OpenFeign实现微服务之间的调用

    一. 前言 微服务实战系列是基于开源微服务项目 有来商城youlai-mall 版本升级为背景来开展的,本篇则是讲述SpringCloud整合OpenFeign实现微服务之间的相互调用,有兴趣的朋友可 ...

  5. SpringCloud微服务实战——搭建企业级开发框架(十九):Gateway使用knife4j聚合微服务文档

      本章介绍Spring Cloud Gateway网关如何集成knife4j,通过网关聚合所有的Swagger微服务文档 1.gitegg-gateway中引入knife4j依赖,如果没有后端代码编 ...

  6. springcloud系列11 整合微服务网关zuul

    这个模块是一个独立的模块所以需要建立一个模块, 首先引入: 依赖pom.xml <?xml version="1.0" encoding="UTF-8"? ...

  7. dubbo初认知(dubbo和springCloud关系,在微服务架构中的作用等)(持续更新中)

    一:dubbo是什么? dobbuo是阿里开源的一个高性能优秀的服务框架, 可通过高性能的 RPC 实现服务的输出和输入功能,使得应用可以和 高性能的rpc实现输入和输出的功能,可以了  Spring ...

  8. springcloud 项目源码 微服务 分布式 Activiti6 工作流 vue.js html 跨域 前后分离

    1.代码生成器: [正反双向](单表.主表.明细表.树形表,快速开发利器)freemaker模版技术 ,0个代码不用写,生成完整的一个模块,带页面.建表sql脚本.处理类.service等完整模块2. ...

  9. SpringCloud(1)---基于RestTemplate微服务项目案例

    基于RestTemplate微服务项目 在写SpringCloud搭建微服务之前,我想先搭建一个不通过springcloud只通过SpringBoot和Mybatis进行模块之间额通讯.然后在此基础上 ...

随机推荐

  1. QT的UDP组播技术

    一 UDP介绍 UDP是一种简单轻量级的传输层协议,提供无连接的,不可靠的报文传输.适合下面4种情况: 网络数据大多为短消息. 拥有大量客户端. 对数据安全性无特殊要求 网络负担非常重,但对响应速度要 ...

  2. python:将numpy数组写入csv文件

    import numpy as np np.savetxt('E:\\forpython\\featvector.csv',data_to_save,delimiter=',')

  3. 让SpringBoot工程支持热部署

    下载地址:https://files.cnblogs.com/files/xiandedanteng/SpringBootWeb-1_20190928.rar 修改Java文件后,每次要重启才好用,修 ...

  4. IDEA离线更新

    因为在hosts文件添加以下dns添加 0.0.0.0 account.jetbrains.com 0.0.0.0 www.jetbrains.com 导致IDEA自动更新失败.手工下载回更新文件IU ...

  5. Linux C/C++基础——Windows远程登录Linux

    首先介绍两个ubuntu系统管理命令,用来测试连通性,及获取IP地址. 1.ping ping命令用来测试远程主机的连通性 使用方法:ping [参数] 远程主机IP地址 参数 功能 -a 每次相应时 ...

  6. HTML笔记(三) 表格和列表

    本篇记录表格 (table) 和有序列表 (ordered list) \ 无序列表 (unordered list) 的部分用法 1.表格table 表格标签 使用 <table> 定义 ...

  7. [转] Python中的装饰器(decorator)

    想理解Python的decorator首先要知道在Python中函数也是一个对象,所以你可以 将函数复制给变量 将函数当做参数 返回一个函数 函数在Python中和变量的用法一样也是一等公民,也就是高 ...

  8. rtsp学习----海康RTSP客户端连接深入分析

    转载于:http://blog.csdn.net/zhouyongku/article/details/41546789 海康相机RTSP连接代码分析 最近在做海康相机rtsp连接获取音视频的工作,现 ...

  9. 【Python】【demo实验3】【显示素数,显示两个数范围内的所有素数】

    打印两个整数之间的所有素数: (使用平方根来判断  是否应停止验证该数值是否为素数) for i in range(956253526252,9956253526252): k = 1 if i == ...

  10. 【3.2】【mysql基本实验】mysql GTID复制(基于空数据的配置)

    概述:本质上和传统异步复制没什么区别,就是加了GTID参数. 且可以用传统的方式来配置主从,也可以用GTID的方式来自动配置主从. 这里使用GTID的方式来自动适配主从. 需要mysql5.6.5以上 ...