zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    转: js中的getYear()函数的问题(推荐用 getFullYear())
    document.compatMode简介
    javascript的isPrototypeOf函数的理解
    javascript Error对象详解
    jQuery事件函数bind,live,delegate的区别
    js运算符(运算符的结合性)
    字符串的正则方法 数值的扩展
    字符串的扩展
    jsp 中href链接有前缀
    变量的结构赋值
  • 原文地址:https://www.cnblogs.com/fengyuduke/p/10998225.html
Copyright © 2011-2022 走看看