簡單的來說,我們把zuul這個項目啓動起來,註冊到eurake上,那麼他就可以代理eurake上面的服務(默認),各種玩法聽我細細道來。
源碼下載路徑在:https://download.csdn.net/download/qq_22075041/10869452,代碼參考microservice-gateway-zuul模塊。
首先加入zuul的依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
<!--需要eurake的client依賴,因爲要註冊到eurake上-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
啓動類上加一個註解@EnableZuulProxy,配置文件只需要把註冊到eurake的配置做一下就可以了:
server:
port: 8040
spring:
application:
name: microservice-gateway-zuul
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
以上配置zuul默認代理eurake的所有服務,調用的時候以註冊到eurake上的服務名。
但是我覺得服務名太長了不好記,我要自定義,配置如下:
zuul:
routes:
# 服務名 訪問路徑 注意/*和/**的區別:適配一層和適配多層
microservice-provider-user: /user/**
如果我要忽略某幾個微服務的代理呢?這樣配(多個用逗號分開):
zuul:
ignored-services: microservice-provider-user,microservice-consumer-movie
如果我只想代理指定的微服務呢?
zuul:
ignored-services: '*' # 使用'*'可忽略所有微服務
routes:
microservice-provider-user: /user/**
還可以這樣玩:同時指定微服務的serviceId和對應路徑path:
zuul:
routes:
abc: # 該配置方式中,abc只是給路由一個名稱,可以任意起名。
service-id: microservice-provider-user
path: /user/** # service-id對應的路徑
玩法2:同時指定path和url
zuul:
routes:
user-route: # 該配置方式中,user-route只是給路由一個名稱,可以任意起名。
url: http://localhost:8000/ # 指定的url
path: /user/** # url對應的路徑。
玩法2升級:同時指定path和URL,並且不破壞Zuul的Hystrix、Ribbon特性
zuul:
routes:
user-route:
path: /user/**
service-id: microservice-provider-user
ribbon:
eureka:
enabled: false # 禁用掉ribbon的eureka使用。詳見:http://cloud.spring.io/spring-cloud-static/Camden.SR3/#_example_disable_eureka_use_in_ribbon
microservice-provider-user:
ribbon:
listOfServers: localhost:8000,localhost:8001
爲Zuul添加全局映射前綴: 應用場景比如項目根目錄不是/ 而是/abc之類的
zuul:
prefix: /api
strip-prefix: false # 默認爲ture
routes:
microservice-provider-user: /user/**
logging:
level:
com.netflix: DEBUG
# 訪問Zuul的/api/microservice-provider-user/1路徑,請求將會被轉發到microservice-provider-user的/api/1,,可以查看日誌打印,有助於理解。
爲Zuul添加局部映射前綴,就是給某個服務添加:
zuul:
routes:
microservice-provider-user:
path: /user/**
strip-prefix: false
logging:
level:
com.netflix: DEBUG
# 這樣訪問Zuul的/user/1路徑,請求將會被轉發到microservice-provider-user的/user/1,可以查看日誌打印,有助於理解。
我要忽略某些敏感路徑,這樣配:
zuul:
ignoredPatterns: /**/admin/** # 忽略所有包括/admin/的路徑
routes:
microservice-provider-user: /user/**
還有基於正則的玩法,削微有點不同,代碼參考microservice-gateway-zuul-reg-exp模塊:
@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication {
@Bean
public PatternServiceRouteMapper serviceRouteMapper() {
// 調用構造函數PatternServiceRouteMapper(String servicePattern, String routePattern)
// servicePattern指定微服務的正則
// routePattern指定路由正則
return new PatternServiceRouteMapper("(?<name>^.+)-(?<version>v.+$)", "${version}/${name}");
}
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}
====================================
1.zuul現在使用的是HttpClient,可以使用其他的
2.zuul還支持把一些敏感請求頭文件不傳到代理的服務上
3.zuul服務自身轉發,也可以配置。
4.訪問zuul的/route,可以看到zuul所有代理的情況
5.@EnableZuulServer是一個zuul的輕量級自由註解,不帶有負載,斷路等功能
=========================================
接下里聊一下大文件上傳,參考代碼microservice-gateway-zuul-file-upload模塊:
# 上傳大文件得將超時時間設置長一些,否則會報超時異常。以下幾行超時設置來自http://cloud.spring.io/spring-cloud-static/Camden.SR3/#_uploading_files_through_zuul
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 60000
ribbon:
ConnectTimeout: 3000
ReadTimeout: 60000
還有一個小技巧,我們上傳一般使用的是springMVC,當我們使用zuul代理的時候,可以在代理路徑前加上/zuul/*,則不會被springMVC上傳的時候限制大小。
=============================================
zuul的fallback,參考代碼microservice-gateway-zuul-fallback模塊,其實就是自定義一個response
package com.itmuch.cloud.study.fallback;
import org.springframework.cloud.netflix.zuul.filters.route.ZuulFallbackProvider;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
@Component
public class UserFallbackProvider implements ZuulFallbackProvider {
@Override
public String getRoute() {
// 表明是爲哪個微服務提供回退
return "microservice-provider-user";
}
@Override
public ClientHttpResponse fallbackResponse() {
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() throws IOException {
// fallback時的狀態碼
return HttpStatus.OK;
}
@Override
public int getRawStatusCode() throws IOException {
// 數字類型的狀態碼,本例返回的其實就是200,詳見HttpStatus
return this.getStatusCode().value();
}
@Override
public String getStatusText() throws IOException {
// 狀態文本,本例返回的其實就是OK,詳見HttpStatus
return this.getStatusCode().getReasonPhrase();
}
@Override
public void close() {
}
@Override
public InputStream getBody() throws IOException {
// 響應體
return new ByteArrayInputStream("用戶微服務不可用,請稍後再試。".getBytes());
}
@Override
public HttpHeaders getHeaders() {
// headers設定
HttpHeaders headers = new HttpHeaders();
MediaType mt = new MediaType("application","json", Charset.forName("UTF-8"));
headers.setContentType(mt);
return headers;
}
};
}
}
==================================
定義zuul的過濾器:
package com.itmuch.cloud.study.filters.pre;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
public class PreRequestLogFilter extends ZuulFilter {
private static final Logger LOGGER = LoggerFactory.getLogger(PreRequestLogFilter.class);
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
PreRequestLogFilter.LOGGER.info(String.format("send %s request to %s", request.getMethod(), request.getRequestURL().toString()));
return null;
}
}
然後注入這個bean
package com.itmuch.cloud.study;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.context.annotation.Bean;
import com.itmuch.cloud.study.filters.pre.PreRequestLogFilter;
@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
@Bean
public PreRequestLogFilter preRequestLogFilter() {
return new PreRequestLogFilter();
}
}
zuul支持自定義Fifter,也有很多實現好的Fifter(在org.springframework.cloud.netflix.zuul.filters包下)。
如果想禁用某一個Fifter,只需設置zuul.<SimpleClassName>.<filterType> .disable = true。例如,要禁用org.springframework.cloud.netflix.zuul.filters.post.SendResponseFilter 需設置 zuul.SendResponseFilter.post.disable = true。