1. zuul
在微服務系統中,一個客戶端需要調用各種各樣的服務,就好比在一堆電線插頭中找到自己的充電器,十分複雜,且不利於統一的對這些服務調用進行管理,於是zuul就充當了中間人這麼一個角色
這樣客戶端只需要和網關交互,而無需直接調用特定微服務的接口,而且方便監控,易於認證,減少客戶端和各個微服務之間的交互次數
zuul的主要功能
身份認證和安全: 識別每一個資源的驗證要求,並拒絕那些不符的請求
審查與監控:
動態路由:動態將請求路由到不同後端集羣
壓力測試:逐漸增加指向集羣的流量,以瞭解性能
負載分配:爲每一種負載類型分配對應容量,並棄用超出限定值的請求
靜態響應處理:邊緣位置進行響應,避免轉發到內部集羣
多區域彈性:跨域AWS Region進行請求路由,旨在實現ELB(ElasticLoad Balancing)使用多樣化
2. 創建一個service-zuul工程
當然這個工程也是在之前的項目的基礎上創建,可以直接拷貝service-feign,改吧改吧就好了
依賴:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<artifactId>service-zuul</artifactId>
<name>service-zuul</name>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.RC1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
同樣的,我們需要在啓動類上打上註解開啓zuul功能
package com.zgd.springcloud.eurekaClient;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
/**
* eureka client 客戶端
*/
@EnableZuulProxy
@EnableEurekaClient
@SpringBootApplication
public class ZuulApp {
public static void main(String[] args) {
SpringApplication.run(ZuulApp.class, args);
}
}
然後修改配置文件
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
spring:
application:
name: service-zuul
server:
port: 8087
#分配兩個服務器的路由
zuul:
routes:
api-a:
path: /ribbon/**
serviceId: service-ribbon
api-b:
path: /feign/**
serviceId: service-feign
這裏api-a和/ribbon/**都是自己定義的,目的是區分routes下面的多個路由
最終以/api-a/ 開頭的請求都轉發給service-ribbon服務;以/api-b/開頭的請求都轉發給service-feign服務
現在我們依次啓動
- eurekaServer
- eureka-client-01
- service-feign
- service-ribbon
- serivce-zuul
然後我們訪問
http://localhost:8087/ribbon/getHi?name=zgd
和
http://localhost:8087/feign/getHi?name=zgd
注意這裏的端口是8087,所以訪問的是service-zuul的服務,並且根據ribbon
和feign
來分別調用service-ribbon和service-feign
3. zuul過濾器
上面說的zuul的路由功能,zuul還有一個功能就是可以過濾從客戶端到服務端的請求
首先我們需要寫一個類,繼承ZuulFilter
注意要使用@component註解將實例交給spring 管理
package com.zgd.springcloud.eurekaClient.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 通過繼承ZuulFilter來自定義過濾器
* @author zgd
* @time 2018年8月1日14:18:06
*/
@Component
public class ZuulDemoFilter extends ZuulFilter {
/**
* 過濾類型,可以選"pre,routing,post"
* @return
*/
@Override
public String filterType() {
return "pre";
}
/**
* 過濾順序
* @return
*/
@Override
public int filterOrder() {
return 0;
}
/**
* 是否進行過濾
* @return
*/
@Override
public boolean shouldFilter() {
RequestContext rc = RequestContext.getCurrentContext();
HttpServletRequest request = rc.getRequest();
String flag = request.getParameter("flag");
Boolean f = true;
if (flag != null){
f = Boolean.valueOf(flag);
}
System.out.println("是否過濾 = " + f);
return f;
}
/**
* 攔截的具體業務代碼
* @return
*/
@Override
public Object run() {
RequestContext rc = RequestContext.getCurrentContext();
HttpServletRequest request = rc.getRequest();
HttpServletResponse response = rc.getResponse();
System.out.println("調用了過濾器");
String money = request.getParameter("money");
if (money == null){
try {
rc.setSendZuulResponse(false);
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("沒有錢不給過");
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
}
1.filterType方法
可以返回
pre : 在通過路由之前過濾
routing:路由之時過濾
error:報錯的時候調用
post:如有之後調用
2. filterOrder方法
可以給過濾指定調用的順序
3. shouldFilter方法
是否進行過濾,這裏進行邏輯判斷
4. run
過濾要做的具體的業務邏輯
5. rc.setSendZuulResponse(false);
表示是否通過該請求
然後我們運行service-zuul
首先訪問
http://localhost:8087/ribbon/getHi?name=zgd&flag=true
頁面顯示: 說明攔截成功
控制檯打印: 說明先調用shouldFilter方法,判斷是否過濾以後,再調用run方法
再訪問http://localhost:8087/ribbon/getHi?name=zgd&flag=false
可以正常訪問
再訪問http://localhost:8087/ribbon/getHi?name=zgd&flag=true&money=1
可以正常訪問