聲明:本文來源於MLDN培訓視頻的課堂筆記,寫在這裏只是爲了方便查閱。html
一、概念:Zuul 路由訪問java
二、具體內容web
在如今爲止全部的微服務都是經過 Eureka 找到的,可是在不少的開發之中爲了規範微服務的使用,提供有一個路由的處理控制組件:Zuul,也就是說 Zuul 就做爲中間的一個代理層出現。spring
本次使用 Zuul 將訪問無安全認證的微服務信息,例如:公司信息就屬於無安全認證的微服務;安全
一、 爲了突出 zuul 的功能,創建一個新的主機映射:服務器
127.0.0.1 gateway-9501.com
之後全部的微服務的訪問再也不直接進行處理了,而是經過 Zuul 進行跳轉後得到app
二、 創建一個新的模塊:microcloud-zuul-gateway-9501;負載均衡
三、 【microcloud-zuul-gateway-9501】修改 pom.xml 文件,追加 zuul 相關依賴包:ide
· 注意:Zuul 服務最終仍是會註冊到 Eureka 之中,那麼千萬要將其配置好;spring-boot
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency>
四、 【microcloud-zuul-gateway-9501】修改 application.yml 配置文件:
server:
port: 9501
eureka:
client: # 客戶端進行Eureka註冊的配置
service-url:
defaultZone: http://edmin:studyjava@eureka-7001.com:7001/eureka,http://edmin:studyjava@eureka-7002.com:7002/eureka,http://edmin:studyjava@eureka-7003.com:7003/eureka
instance:
lease-renewal-interval-in-seconds: 2 # 設置心跳的時間間隔(默認是30秒)
lease-expiration-duration-in-seconds: 5 # 若是如今超過了5秒的間隔(默認是90秒)
instance-id: gateway-9501.com # 在信息列表時顯示主機名稱
prefer-ip-address: true # 訪問的路徑變爲IP地址
info:
app.name: study-microcloud
company.name: www.study.cn
build.artifactId: $project.artifactId$
build.version: $project.verson$
spring:
application:
name: microcloud-zuul-gateway
五、 【microcloud-zuul-gateway-9501】建立程序啓動的主類:
package cn.study.microcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; @SpringBootApplication @EnableZuulProxy public class Zuul_9501_StartSpringCloudApplication { public static void main(String[] args) { SpringApplication.run(Zuul_9501_StartSpringCloudApplication.class, args); } }
能夠看到【microcloud-zuul-gateway-9501】已經註冊到eureka中了
六、 訪問公司微服務信息:
· 原始訪問路徑:http://company-8101.com:8101/company/get/hello;
· Zuul 代理訪問:http://gateway-9501.com:9501/microcloud-provider-company/company/get/hello;
如今使用 Zuul 代理的只有 company,由於 dept 上有安全認證不能訪問。
總體的 Zuul 運行以後你會發現,zuul 所實現就是一個代理功能,那麼如今就會出現一個問題,例如:以以前訪問的路徑爲例:
http://gateway-9501.com:9501/microcloud-provider-company/company/get/hello
此時必需要知道應用程序的名稱,可是若是不知道這個名稱確定沒法訪問,但是若是讓用戶知道這個名稱,那麼使用 zuul 就 沒有任何的實際意義,直接調用便可。而 zuul 的主要功能是代理,那麼代理的功能就是不讓用戶看見真實的操做,因此在實際的使用之中就須要爲 zuul 設置一些路由規則。
一、 【microcloud-zuul-gateway-9501】爲指定的應用設置路徑,修改 application.yml 配置文件:
zuul: routes: microcloud-provider-company: /company-proxy/**
那麼此時就能夠經過「/company-proxy」來訪問「microcloud-provider-company」名稱。
http://gateway-9501.com:9501/company-proxy/company/get/hello
可是如今還會存在有一個實際的問題,雖然如今開啓了路由訪問支持,可是依然支持經過應用名稱進行訪問:
http://gateway-9501.com:9501/microcloud-provider-company/company/get/hello
二、 【microcloud-zuul-gateway-9501】修改 application.yml 配置文件忽略掉應用名稱訪問:
· 忽略掉「microcloud-provider-company」應用名稱;
zuul: ignored-services: microcloud-provider-company routes: microcloud-provider-company: /company-proxy/**
這個時候就能夠進行代理的安全使用,可是若是你一個系統之中存在有幾百個微服務,若是按照如上的方式進行配置就會非 常的麻煩,因此最簡單的作法是能夠採用一個通配符「*」的模式來完成:
zuul: ignored-services: "*" routes: microcloud-provider-company: /company-proxy/**
如今表示全部的 Eureka 中的服務名稱的信息訪問都要忽略掉,全部的訪問都須要配置一個映射路徑的模式來完成。
三、 【microcloud-zuul-gateway-9501】除了以上的模式進行服務定義以外,在 zuul 之中也能夠採用以下的方式進行處理:
zuul: ignored-services: "*" routes: mycompany.path: /company-proxy/** mycompany.serviceId: microcloud-provider-company
其中在代碼裏面出現的「mycompany」是一個邏輯名稱,該名稱的主要做用是將 path 與 serviceId 綁定在一塊兒。
四、 【microcloud-zuul-gateway-9501】若是說如今不想經過 Eureka 進行訪問,則也能夠直接鏈接到 company 微服務的地址
zuul: ignored-services: "*" routes: company.path: /company-proxy/** company.url: http://company-8101.com:8101/company
此時的地址上因爲已經存在有了「company」前綴,因此訪問地址爲:
http://gateway-9501.com:9501/company-proxy/get/hello
可是從實際的開發來說不建議採用此類模式處理,由於全部的服務若是直接綁定了指定的服務提供者的地址,那麼將不方便 進行負載均衡的配置處理,並且沒有 Eureka 全部微服務的管理也很是不方便。
五、 【microcloud-zuul-gateway-9501】設置公共前綴:
zuul: prefix: /study-proxy ignored-services: "*" routes: microcloud-provider-company: /company-proxy/**
一旦存在有前綴定義以後全部微服務的訪問上就必須追加有前綴名稱:
http://gateway-9501.com:9501/study-proxy/company-proxy/company/get/hello
以上的地址:
· 「/study-proxy」:整個 zuul 的前綴;
· 「/company-proxy」:是在 zuul 中定義的映射路徑;
· 「/company/get/hello」:是微服務提供者提供的操做路徑。
對於 zuul 的功能本質上就屬於一個代理操做,可是在實際的使用之中,全部的微服務必定都要有本身的認證信息,那麼在這 樣的狀態下,若是你當前所代理的微服務具備認證信息,那麼就必須在其訪問前追加認證的頭部操做,這樣的功能就須要經過 zuul的過濾操做完成。
一、 【microcloud-zuul-gateway-9501】修改 application.yml 配置,這個配置之中追加 dept 微服務的代理;
zuul: prefix: /study-proxy ignored-services: "*" routes: microcloud-provider-company: /company-proxy/** microcloud-provider-dept: /dept-proxy/**
此時的訪問路徑:http://studyjava:hello@gateway-9501.com:9501/study-proxy/dept-proxy/dept/get/1;如今的密碼只是設置給了 zuul,而 zuul 並不可以將認證的信息傳遞到部門微服務之中。
二、 【microcloud-zuul-gateway-9501】追加過濾處理操做:
package cn.study.microcloud.filter; import java.nio.charset.Charset; import java.util.Base64; import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; public class AuthorizedRequestFilter extends ZuulFilter { // 進行受權訪問處理 @Override public Object run() { // 表示具體的過濾執行操做 RequestContext currentContext = RequestContext.getCurrentContext() ; // 獲取當前請求的上下文 String auth = "studyjava:hello"; // 認證的原始信息 byte[] encodedAuth = Base64.getEncoder() .encode(auth.getBytes(Charset.forName("US-ASCII"))); // 進行一個加密的處理 // 在進行受權的頭信息內容配置的時候加密的信息必定要與「Basic」之間有一個空格 String authHeader = "Basic " + new String(encodedAuth); currentContext.addZuulRequestHeader("Authorization", authHeader); return null; } @Override public boolean shouldFilter() { // 該Filter是否要執行 return true ; } @Override public int filterOrder() { return 0; // 設置優先級,數字越大優先級越低 } @Override public String filterType() { // 在進行Zuul過濾的時候能夠設置其過濾執行的位置,那麼此時有以下幾種類型: // 一、pre:在請求發出以前執行過濾,若是要進行訪問,確定在請求前設置頭信息 // 二、route:在進行路由請求的時候被調用; // 三、post:在路由以後發送請求信息的時候被調用; // 四、error:出現錯誤以後進行調用 return "pre"; } }
三、 【microcloud-zuul-gateway-9501】創建一個配置程序類做爲認證請求的配置 Bean。
package cn.study.microcloud.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import cn.study.microcloud.filter.AuthorizedRequestFilter; @Configuration public class ZuulConfig { @Bean public AuthorizedRequestFilter getAuthorizedRequestFilter() { return new AuthorizedRequestFilter() ; } }
那麼這個時候就意味着你如今的程序能夠直接利用 zuul 的代理訪問全部加密的微服務。
四、 【microcloud-zuul-gateway-9501】考慮到 zuul 也須要進行安全訪問,因此應該修改項目中的 pom.xml 配置文件,追加 Spring 安全訪 問配置處理操做:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
五、 【microcloud-zuul-gateway-9501】修改 application.yml 配置文件,最佳有用戶信息配置:
security:
basic:
enabled: true
user:
name: zdmin
password: studyjava
那麼此時如今表示 zuul 的代理上有了認證信息,則訪問的地址上必須加上 zuul 的認證操做:
http://zdmin:studyjava@gateway-9501.com:9501/study-proxy/dept-proxy/dept/get/1
六、 【microcloud-service】如今全部的服務要經過 zuul 的代理來進行操做對於代理的配置若是要經過 feign 進行訪問,那麼在編寫 feign 的時候就必須設置代理的服務名稱;
package cn.study.service; import java.util.List; import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import cn.study.commons.config.FeignClientConfig; import cn.study.service.fallback.IDeptClientServiceFallbackFactory; import cn.study.vo.Dept; @FeignClient(value = "MICROCLOUD-ZUUL-GATEWAY", configuration = FeignClientConfig.class, fallbackFactory = IDeptClientServiceFallbackFactory.class) public interface IDeptClientService { @RequestMapping(method = RequestMethod.GET, value = "/study-proxy/dept-proxy/dept/get/{id}") public Dept get(@PathVariable("id") long id); @RequestMapping(method = RequestMethod.GET, value = "/study-proxy/dept-proxy/dept/list") public List<Dept> list(); @RequestMapping(method = RequestMethod.POST, value = "/study-proxy/dept-proxy/dept/add") public boolean add(Dept dept); }
七、 【microcloud-service】修改服務的配置類,測試訪問的應該是 zuul 的地址:
package cn.study.commons.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import feign.Logger; import feign.auth.BasicAuthRequestInterceptor; @Configuration public class FeignClientConfig { @Bean public Logger.Level getFeignLoggerLevel() { return feign.Logger.Level.FULL ; } @Bean public BasicAuthRequestInterceptor getBasicAuthRequestInterceptor() { return new BasicAuthRequestInterceptor("zdmin", "studyjava"); } }
八、 【microcloud-zuul-gateway-9501】默認狀況下只要配置了過濾器,就能夠進行一個正常的啓動,若是如今有些過濾器忽然不想讓它 用了,則也能夠經過修改 application.yml 配置文件讓其禁用:
zuul: AuthorizedRequestFilter: pre: disable: true
此時表示「AuthorizedRequestFilter」過濾器將被禁止使用。若是之後有多個過濾服務出現的話,能夠經過配置文件實現過濾 的啓用與禁用控制。
Zuul 是一個代理服務,那麼若是被代理的服務忽然斷掉了,那麼這個時候 zuul 上面必定會顯示出錯誤信息。例如:如今中止 掉「dept-8001:8001」端口上的微服務。
若是如今程序沒法使用,則 zuul 的代理執行時就會出現有 timeout 的信息。可是千萬要記住,因爲如今的客戶端已經提供有了 feign 中的服務降級的配置支持,因此客戶端沒有任何的問題,問題只出如今代理端。可是對於一個完善的 zuul 的代理應該更好的 實現服務降級的處理操做,因此若是有須要也能夠在 zuul 中進行服務降級配置。
一、 【microcloud-zuul-gateway-9501】創建一個 Fallback 的回退處理類。
package cn.study.microcloud.fallback; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import org.springframework.cloud.netflix.zuul.filters.route.ZuulFallbackProvider; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.client.ClientHttpResponse; import org.springframework.stereotype.Component; @Component public class DeptProviderFallback implements ZuulFallbackProvider { @Override public String getRoute() { return "microcloud-provider-dept"; // 設置好處理的失敗路由 } @Override public ClientHttpResponse fallbackResponse() { return new ClientHttpResponse() { @Override public InputStream getBody() throws IOException { return new ByteArrayInputStream( "{\"deptno\":777777,\"dname\":\"【ERROR】Zuul-Fallback\",\"loc\":\"Gateway客戶端提供\"}" .getBytes()); // 當出現服務調用錯誤以後返回的數據內容 } @Override public HttpHeaders getHeaders() { HttpHeaders headers = new HttpHeaders() ; headers.set("Content-Type", "text/html; charset=UTF-8"); return headers; } @Override public HttpStatus getStatusCode() throws IOException { return HttpStatus.BAD_REQUEST; } @Override public int getRawStatusCode() throws IOException { return HttpStatus.BAD_REQUEST.value(); } @Override public String getStatusText() throws IOException { return HttpStatus.BAD_REQUEST.getReasonPhrase(); } @Override public void close() { }}; } }
二、 【microcloud-zuul-gateway-9501】直接訪問地址:
http://zdmin:studyjava@gateway-9501.com:9501/study-proxy/dept-proxy/dept/get/1
因爲此時你返回的都是錯誤的代碼,則客戶端接收到此代碼以後會認爲服務器端已經死掉了。