参考:https://blog.csdn.net/forezp/article/details/81041012
Zuul
Zuul主要是路由转发和过滤。路由功能是微服务的一部分,比如/api/a转发到到a服务,/api/b转发到到b服务,转发到具体的服务后,再根据ribbon或者feign访问多实例中具体的某一个节点,实现负载均衡负载,zuul默认和Ribbon结合实现了负载均衡的功能。
实践
前期工作,建立在前面项目的基础上
创建zuul-serveice工程,导入依赖包:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| <?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>
<groupId>com.example</groupId> <artifactId>servicezuul</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging>
<name>servicezuul</name> <description>Demo project for Spring Boot</description>
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.5.RELEASE</version> <relativePath/> </parent>
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <spring-cloud.version>Finchley.SR1</spring-cloud.version> </properties>
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-zuul</artifactId> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</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> </project>
|
配置application.yml,将项目注册的eureka中,其中以/api-a/ 开头的请求都转发给service-ribbon服务;以/api-b/开头的请求都转发给service-feign服务;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/ server: port: 8080 spring: application: name: service-zuul zuul: routes: api-a: path: /api-a/** serviceId: service-ribbon api-b: path: /api-b/** serviceId: service-feign
|
启动类增加zuul,eurekaClient注解:
1 2
| @EnableZuulProxy @EnableEurekaClient
|
启动如下几个程序
5、访问
http://localhost:8080/api-a/sayHi?name=张三
或者
http://localhost:8080/api-b/sayHi?name=张三
可以开启Debug模式,查看服务所调用的模块。
zuul还有其他额外功能,如安全验证、过滤等
新建一个Filter类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| package com.example.servicezuul.filter;
import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; import com.netflix.zuul.exception.ZuulException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
@Component public class FilterTest extends ZuulFilter {
private Logger logger = LoggerFactory.getLogger(FilterTest.class);
@Override public String filterType() { return "pre"; }
@Override public int filterOrder() { return 0; }
@Override public boolean shouldFilter() { return true; }
@Override public Object run() throws ZuulException { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); logger.info(request.getMethod()+" >>> "+request.getRequestURL().toString()); Object accessToken = request.getParameter("token"); if (accessToken == null) { logger.warn("token is null!!!"); ctx.setSendZuulResponse(false); ctx.setResponseStatusCode(401); try { ctx.getResponse().getWriter().write("token is null!!!"); } catch (Exception e) { e.printStackTrace(); }
return null; } logger.info("token is ok!!!"); return null; } }
|
其中:
filterType:返回一个字符串代表过滤器的类型,在zuul中定义了四种不同生命周期的过滤器类型
pre:路由前
routing:路由时
post: 路由后
error:错误调用
filterOrder:过滤的顺序
shouldFilter:这里可以写逻辑判断,是否要过滤
run:过滤器的具体逻辑
访问:http://localhost:8080/api-a/sayHi?name=张三

后台日志:
访问:http://localhost:8080/api-a/sayHi?name=张三&token=abcd123
后台日志: