目錄
- 一站式微服務架構SpringCloud-Netflix網關路由Zuul
-
- 項目中使用Zuul
- 自定義路由規則
- 禁用服務名通路項目和添加項目字首
- 過濾器
-
- 自定義過濾器
- 禁用過濾器
- 網關異常處理
- zuul的熔斷降級
一站式微服務架構SpringCloud-Netflix網關路由Zuul
項目中使用Zuul
建立zuul項目
添加依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
配置檔案
server.port=90
spring.application.name=springcloud-zuul
#每2秒向服務端發送一次心跳,證明自己存活
eureka.instance.lease-renewal-interval-in-seconds=2
#告訴服務端,10秒之内沒有發送心跳,就代表故障了
eureka.instance.lease-expiration-duration-in-seconds=10
#以IP作為連結
eureka.instance.prefer-ip-address=true
#執行個體名稱
eureka.instance.instance-id=springcloud-zuul
#Eureka連結位址
eureka.client.service-url.defaultZone=http://47.110.157.82:8761/eureka,http://47.110.157.82:8762/eureka,http://47.110.157.82:8763/eureka
#設定zuul逾時時間
zuul.host.connect-timeout-millis=5000
啟動類添加@EnableZuulProxy
@EnableZuulProxy
@SpringBootApplication
public class SpringcloudDomeZuulApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudDomeZuulApplication.class, args);
}
}
測試:
通過Eureka的spring.application.name通路項目
自定義路由規則
配置檔案中添加
#路由規則,producer是自己随便定義的
zuul.routes.producer.service-id=springcloud-producer
#?:比對多個字元。*:比對單層路徑。 **:比對:多層路徑,/producer/**自己随便定義
zuul.routes.producer.path=/producer/**
測試:
将springcloud-producer替換成producer
禁用服務名通路項目和添加項目字首
#忽略服務,禁止使用該服務名通路
#zuul.ignored-services=springcloud-producer
#忽略所有服務
zuul.ignored-services=*
#路徑中存在save不能通路
zuul.ignored-patterns=/**/save/**
#添加字首
zuul.prefix=/api
測試:
服務名無法通路
過濾器
自定義過濾器
@Component
public class MyFilter extends ZuulFilter {
/**
* 過濾器類型
* ERROR_TYPE = "error"; 過濾出錯
* POST_TYPE = "post"; 過濾後
* PRE_TYPE = "pre"; 過濾前
* ROUTE_TYPE = "route"; 過濾時
* @return
*/
@Override
public String filterType() {
return FilterConstants.ROUTE_TYPE;
}
/**
* 過濾器優先級
* DEBUG_FILTER_ORDER = 1;
* FORM_BODY_WRAPPER_FILTER_ORDER = -1;
* PRE_DECORATION_FILTER_ORDER = 5;
* RIBBON_ROUTING_FILTER_ORDER = 10;
* SEND_ERROR_FILTER_ORDER = 0;
* SEND_FORWARD_FILTER_ORDER = 500;
* SEND_RESPONSE_FILTER_ORDER = 1000;
* SIMPLE_HOST_ROUTING_FILTER_ORDER = 100;
* SERVLET_30_WRAPPER_FILTER_ORDER = -2;
* SERVLET_DETECTION_FILTER_ORDER = -3;
* @return
*/
@Override
public int filterOrder() {
return FilterConstants.SEND_ERROR_FILTER_ORDER;
}
/**
* 是否開啟過濾器
* @return
*/
@Override
public boolean shouldFilter() {
return true;
}
/**
* 執行方法
* @return
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
HttpServletRequest request = RequestContext.getCurrentContext().getRequest();
String serverName = request.getServerName();
System.out.println("通路位址"+serverName+request.getRequestURI());
return null; //傳回值無意義
}
}
測試
通路路由URL:http://localhost:90/api/producer/get
禁用過濾器
配置檔案添加
#禁用過濾器。Myfilter過濾器類,route過濾器類型
zuul.Myfilter.route.disable=true
網關異常處理
關閉zuul自帶異常處理
自定義異常處理類
@Component
public class ErrorFilter extends ZuulFilter {
@Override
public String filterType() {
return FilterConstants.ERROR_TYPE;
}
@Override
public int filterOrder() {
return 1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
try {
RequestContext currentContext = RequestContext.getCurrentContext();
ZuulException exception=(ZuulException) currentContext.getThrowable();
System.out.println("進入系統異常攔截"+exception.getMessage());
HttpServletResponse response = currentContext.getResponse();
response.setContentType("application/json; charset=utf8");
response.setStatus(exception.nStatusCode);
PrintWriter writer=null;
try{
writer=response.getWriter();
writer.print("{code:"+exception.nStatusCode+",message:\""+exception.getMessage()+"\"}");
}catch (IOException e){
e.printStackTrace();
}finally {
if(writer!=null){
writer.close();
}
}
}catch (Exception e){
ReflectionUtils.rethrowRuntimeException(e);
}
return null;
}
}
在自定義過濾器MyFilter中制造異常
/**
* 執行方法
* @return
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
HttpServletRequest request = RequestContext.getCurrentContext().getRequest();
String serverName = request.getServerName();
System.out.println("通路位址"+serverName+request.getRequestURI());
int a=10/0; //制造異常
return null; //傳回值無意義
}
測試
zuul的熔斷降級
建立zuul的降級類
@Component
public class ZuulFallBack implements FallbackProvider {
/**
* 配置需要降級的路由規則
* @return
*/
@Override
public String getRoute() {
return "*";
}
@Override
public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
return new ClientHttpResponse() {
/**
* 響應頭
* @return
*/
@Override
public HttpHeaders getHeaders() {
HttpHeaders headers = new HttpHeaders();
headers.set("Content-Type", "text/html;charset=UTF-8");
return headers;
}
/**
* 響應體
* @return
* @throws IOException
*/
@Override
public InputStream getBody() throws IOException {
// 當出現服務調用錯誤之後傳回的内容
// 服務端死掉,會自動找zuul的失敗回退服務降級
return new ByteArrayInputStream("系統正在維護,請稍後再試!".getBytes());
}
/**
* 狀态碼
* @return
* @throws IOException
*/
@Override
public HttpStatus getStatusCode() throws IOException {
return HttpStatus.BAD_REQUEST;
}
/**
* 狀态碼值
* @return
* @throws IOException
*/
@Override
public int getRawStatusCode() throws IOException {
return HttpStatus.BAD_REQUEST.value();
}
/**
* 狀态碼值文本
* @return
* @throws IOException
*/
@Override
public String getStatusText() throws IOException {
return HttpStatus.BAD_REQUEST.getReasonPhrase();
}
@Override
public void close() {
// TODO Auto-generated method stub
}
};
}
}
測試:
關閉zuul中的服務,然後通過zuul來通路服務