咱們接着上一節。在許多場景下,外部請求須要查詢Zuul後端的多個微服務。好比一個電影售票手機APP,在購票訂單頁上,既須要查詢「電影微服務」得到電影相關信息,又須要查詢「用戶微服務」得到當前用戶信息。若是讓手機端直接請求各個微服務(即便使用Zuul進行轉發),那麼網絡開銷,流量耗費,耗費時長可能都沒法使人滿意。那麼對於這種場景,可以使用Zuul聚合微服務請求——手機APP發送一次請求給Zuul,由Zuul請求用戶微服務以及電影微服務,並組織好數據給手機APP。java
使用這種方式,在手機端只需發送一次請求便可,簡化了客戶端側的開發;不只如此,因爲Zuul,用戶微服務,電影微服務通常都在同一個局域網中,所以速度會很是快,效率會很是高。git
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.建立實體類。app
public class User { private Long id; private String username; private String name; private Integer age; private BigDecimal balance; // getters and setters... }
4.建立java類。ide
@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寫的。也能夠不用這種方式。只要實現調用多個微服務請求,而後將結果數據組織好返回出去就行。微服務
啓動項目microservice-discovery-eureka.測試
啓動項目microservice-provider-user.this
啓動項目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.
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