6.閘道器/服務端負載均衡器/服務過濾器(Zuul)
阿新 • • 發佈:2019-02-11
1.Zuul介紹
zuul是一個閘道器和負載均衡器,在通過ribbon或者feign實現了客戶端負載均衡之後,zuul在服務端實現負載均衡。zuul支援用任何JVM語言來編寫規則和過濾條件。zuul充當了一個代理伺服器承擔內部網路的閘道器的角色。如圖:
2.cmd下啟動四個工程(eureka註冊工程/ribbon消費者工程/feign消費者工程/服務提供者工程)
3.建立一個Zuul工程(zuul_test)
(1)pom.xml
<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> <groupId>com.tyf</groupId> <artifactId>zuul_test</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>zuul_test</name> <url>http://maven.apache.org</url> <!-- 1 --> <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> </properties> <!-- 2 --> <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> <!-- 3 --> <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> <!-- 4 --> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <!-- 5 --> <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>
(2)resources/application.yml
這裡test-a字首負責將所有的這類請求路由給feign-consumer-test 所以這裡訪問feign-consumer-test的控制器不會直接請求feign-consumer-test的地址,而是通過zuul這個閘道器 不使用zuul訪問feign-consumer-test:http://localhost:8766/feignConsumer/test?name=xxx 使用zuul訪問feign-consumer-test:http://localhost:8770/test-a/test?name=xxxeureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/ server: port: 8770 spring: application: name: zuul-test zuul: routes: api-a: path: /test-a/** serviceId: feign-consumer-test api-b: path: /test-b/** serviceId: ribbon-consumer-test
(3)啟動類
package com.tyf.zuul_test; 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; /** * Hello world! * */ @EnableZuulProxy @EnableEurekaClient @SpringBootApplication public class App { public static void main( String[] args ) { SpringApplication.run(App.class, args); } }
(4)啟動zuul工程
通過zuul訪問feign-consumer-test的控制器:http://localhost:8770/test-a/feignConsumer/test?name=xxx 通過zuul訪問ribbon-consumer-test的控制器:http://localhost:8770/test-b/modelController/test4.zuul做過濾器
直接繼承zuul的過濾器,四個方法說明見註釋(別忘了注入ioc中)
package com.tyf.zuul_test;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Component;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
/*
*
* 基礎zuul過濾器:
* 1.String filterType():返回一個字串代表這個過濾器在路由的那個階段進行
* pre:路由之前
* routing:路由之時
* post: 路由之後
* error:傳送錯誤呼叫
* 2.int filterOrder():返回一個int整數用來排序(從0開始),請求在多個過濾器之間傳遞,傳遞的順序就是這個值
* 3.boolean shouldFilter():獲取到請求,如果請求不符合要求可以不讓請求通過,這裡可以實現很多邏輯:
*
* 4.run():具體的過濾邏輯,這裡檢查請求引數是否有token,這裡訪問url變成如下形式:
* feign-consumer-test的控制器:http://localhost:8770/test-a/feignConsumer/test?name=xxx&token=xxx
* ribbon-consumer-test的控制器:http://localhost:8770/test-b/modelController/test?token=xxx
*
*
*/
@Component
public class myFiler extends ZuulFilter {
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
Object accessToken = request.getParameter("token");
System.out.println(accessToken);
try {
if(accessToken == null) {
//ctx設定response,直接在這裡進行response
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(401);
ctx.getResponse().getWriter().write("token is empty");
System.out.println("token is null !");
return null;
}
} catch (Exception e) {e.printStackTrace();}
//如果一切正常,request會被路由到消費者/服務提供者那裡由他們做出response
return null;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public int filterOrder() {
//filterOrder:過濾的順序
return 0;
}
@Override
public String filterType() {
//過濾器在路由之前起作用
return "pre";
}
}
run方法中如果request沒有token引數,則zuul伺服器直接response告訴瀏覽器。如果一切正常則request會通過過濾器再通過路由器傳播
正確的訪問引數:
feign-consumer-test的控制器:http://localhost:8770/test-a/feignConsumer/test?name=xxx&token=xxxribbon-consumer-test的控制器:http://localhost:8770/test-b/modelController/test?token=xxx