springcloud(十一)-Zuul聚合微服务

前言

我们接着上一节。在许多场景下,外部请求需要查询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

原文地址:https://www.cnblogs.com/fengyuduke/p/10998225.html