前言

我们接着上一节。在许多场景下,外部请求需要查询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. mysql密码忘记更改

    忘记mysql的密码是一件不好的事,通常我们会把密码记住,或者是存在文档中,避免忘记,如果忘记了密码可以参照下方方法来更改,这个操作需要重启mysql. 首先我们在my.cnf文件中的[mysqld] ...

  2. For 循环 kotlin(10)

    For 循环 for 循环可以对任何提供迭代器(iterator) 的对象进行遍历,语法如下: for (item in collection) print(item) 循环体可以是一个代码块. fo ...

  3. 非监督的降维算法--PCA

    PCA是一种非监督学习算法,它能够在保留大多数有用信息的情况下,有效降低数据纬度. 它主要应用在以下三个方面: 1. 提升算法速度 2. 压缩数据,减小内存.硬盘空间的消耗 3. 图示化数据,将高纬数 ...

  4. python web开发flask框架 安装与环境

    # encoding:utf-8 # 从flask这个框架中导入Flask这个类 from flask import Flask # 初始化一个Flask对象 # Flasks() # 需要传递一个参 ...

  5. python programming作业10(仍有一点点小bug)

    # -*- coding: utf-8 -*- import os import platform import sys from PyQt5.QtCore import * from PyQt5.Q ...

  6. C基础知识(5):指针--传递指针给函数&返回指针的函数

    下面从3个代码例子分别讲述以下2个知识点: (1) 传递指针给函数(参数类型为指针) (2) 返回指针的函数(返回类型为指针) #include <stdio.h> // 传递指针给函数& ...

  7. java:JQuery(Ajax,JSON)

    1.遍历ajax返回的json: 第一种: <%@ page language="java" import="java.util.*" pageEncod ...

  8. React-Native传值方式之 :DeviceEventEmitter添加监听控制并传值到其他页面

    在 native 开发中,我们可以使用广播实现事件的订阅和事件的触发,从而实现不在该页面但是可以调用该页面的方法. 在 React Native 中,我们也可以使用 DeviceEventEmitte ...

  9. Python面试简介及并行并发

    今天的分享内容大体如下: 一. 面试 1. 什么是面试 2. 优秀的面试 二. Python综述 1. Python设计哲学及版本变迁 2. Python发展现状及其他语言使用场景 3. GIL 4. ...

  10. mysql命令行备份方法

    一.mysql备份 1.备份命令 格式:mysqldump -h主机IP -P端口 -u用户名 -p密码 --database 数据库名 > 文件名.sql # 本地备份可以不添加端口和主机IP ...