照例附上項目github連接java
本項目實現的是將一個簡單的天氣預報系統一步一步改形成一個SpringCloud微服務系統的過程。本章主要講解API網關。git
在目前的項目中咱們構建了許多的API微服務,當第三方服務想要調用咱們的API微服務的時候是經過微服務的名稱進行調用的,沒有一個統一的入口。github
API網關就是爲了統一服務的入口,能夠方便地實現對平臺的衆多服務接口進行管控,對訪問服務的身份進行驗證,防止數據的篡改等。web
咱們的一個微服務可能須要依賴多個API微服務,API網關能夠在中間作一個api的彙集。spring
那麼咱們的微服務只須要統一地通過API網關就能夠了(只須要依賴於API網關就能夠了),不用關心各類API微服務的細節,須要調用的API微服務由API網關來進行轉發。後端
Zuul是Netflix開源的微服務網關,他能夠和Eureka,Ribbon,Hystrix等組件配合使用。Zuul組件的核心是一系列的過濾器,這些過濾器能夠完成如下功能:api
Spring Cloud對Zuul進行了整合和加強。目前,Zuul使用的默認是Apache的HTTP Client,也可使用Rest Client,能夠設置ribbon.restclient.enabled=true。跨域
在原來項目的基礎上,建立一個msa-weather-eureka-client-zuul做爲API網關。安全
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId> </dependency>
添加@EnableZuulProxy啓用Zuul的代理功能。架構
@SpringBootApplication @EnableDiscoveryClient @EnableZuulProxy public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
這裏配置的是設置路由的url。
當有人訪問 /city/ 路徑的時候,就對訪問這個路徑的請求作一個轉發,轉發到msa-weather-city-eureka服務中去,同理,當有人訪問 /data/ 路徑的時候,API網關也會將這個請求轉發到msa-weather-data-eureka服務中去。
zuul: routes: city: path: /city/** service-id: msa-weather-city-eureka data: path: /data/** service-id: msa-weather-data-eureka
原來天氣預報微服務依賴了城市數據API微服務,以及天氣數據API微服務,這裏咱們對其進行修改讓其依賴API網關,讓API網關處理天氣預報微服務其餘兩個微服務的調用。
首先刪去原來調用其餘兩個API微服務的Feign客戶端——CityClient以及WeatherDataClient,建立一個新的Feign客戶端——DataClient。
package com.demo.service; import java.util.List; import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import com.demo.vo.City; import com.demo.vo.WeatherResponse; @FeignClient("msa-weather-eureka-client-zuul") public interface DataClient { //獲取城市列表 @RequestMapping(value="/city/cities",method=RequestMethod.GET) List<City> listCity()throws Exception; //經過城市Id查詢對應城市的天氣數據 @RequestMapping(value="/data/weather/cityId",method=RequestMethod.GET) WeatherResponse getDataByCityId(@RequestParam("cityId")String cityId); }
在service中使用該客戶端對API網關進行調用,API網關根據咱們請求的路徑去調用相應的微服務。
@Service public class WeatherReportServiceImpl implements WeatherReportService{ //@Autowired //private WeatherDataClient weatherDataClient; @Autowired private DataClient dataClient; //根據城市Id獲取天氣預報的數據 @Override public Weather getDataByCityId(String cityId) { //由天氣數據API微服務來提供根據城市Id查詢對應城市的天氣的功能 WeatherResponse resp=dataClient.getDataByCityId(cityId); Weather data=resp.getData(); return data; } }
在controller也是同理。
//傳入城市Id獲得對應城市的天氣數據 @GetMapping("/cityId/{cityId}") public Weather getReportByCityId(@PathVariable("cityId")String cityId,Model model)throws Exception{ //獲取城市Id列表 //由城市數據API微服務來提供數據 List<City>cityList=null; try { cityList=dataClient.listCity(); }catch (Exception e) { logger.error("Exception!",e); } Weather weather=weatherReportService.getDataByCityId(cityId); return weather; }