一、Zuul简介
Zuul的主要功能是路由转发和过滤器。路由功能是微服务的一部分,比如/api/user转发到到user服务,/api/shop转发到到shop服务。zuul默认和Ribbon结合实现了负载均衡的功能。
zuul有以下功能:
- Authentication
- Insights
- Stress Testing
- Canary Testing
- Dynamic Routing
- Service Migration
- Load Shedding
- Security
- Static Response handling
- Active/Active traffic management
二、准备工作
继续使用上一节的工程。在原有的工程上,创建一个新的工程。
三、创建microservicecloud-zuul-gateway工程
3.1 POM配置
<?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"> <parent> <artifactId>mall</artifactId> <groupId>com.linjia</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <groupId>com.linjia</groupId> <artifactId>microservicecloud-zuul-gateway</artifactId> <version>1.0-SNAPSHOT</version> <name>microservicecloud-zuul-gateway</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> </properties> <dependencies> <!-- zuul路由网关 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <!-- actuator监控 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- hystrix容错 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> <!-- 日常标配 --> <dependency> <groupId>com.linjia</groupId> <artifactId>microservicecloud-api</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</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> </dependency> <!-- 热部署插件 --> <dependency> <groupId>org.springframework</groupId> <artifactId>springloaded</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> </dependencies> </project>
3.2 yml文件配置
server: port: 9527 spring: application: name: microservicecloud-zuul-gateway eureka: client: service-url: # defaultZone: http://localhost:7001/eureka #将客户端注册进eureka服务列表内 defaultZone: http://localhost:7001/eureka,http://localhost:7002/eureka,http://localhost:7003/eureka instance: instance-id: ${spring.cloud.client.ipAddress}:${server.port} #自定义服务名称信息 启动多个服务做集群需要设置为不同的ID值 prefer-ip-address: true #访问路径可以显示IP地址 info: app.name: baidu-microcloud company.name: www.baidu.com build.artifactId: $project.artifactId$ build.version: $project.version$ #第一步:启动注册中心 #第二步:启动 microservicecloud-zuul-gateway #第三步:启动 microservicecloud-provider-dept 服务提供者 # 访问:http://localhost:8001/dept/get/1 # 访问:http://localhost:9527/microservicecloud-dept/dept/get/1 # 两个结果显示同样信息 # # 路由映射配置 zuul: # ignored-services: "*" #忽略多个服务方式"*"代替 ignored-services: microservicecloud-dept # 设置单个服务名称后真实URL无法访问:http://localhost:9527/microservicecloud-dept/dept/get/1 只可以虚拟URL访问 prefix: /willow #设置统一前缀路径 设置后访问:http://localhost:9527/willow/mydept/dept/get/1 routes: mydept.serviceId: microservicecloud-dept mydept.path: /mydept/** # 访问虚拟URl方式:http://localhost:9527/mydept/dept/get/1
3.3 启动类创建
package com.linjia; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; @SpringBootApplication @EnableZuulProxy public class ZuulGatewayApplication { public static void main( String[] args ) { SpringApplication.run(ZuulGatewayApplication.class, args); } }
配置完成;完成下面访问Zuul起到路由作用,yml配置文件中的zuul配置可有可无
#第一步:启动注册中心 #第二步:启动 microservicecloud-zuul-gateway #第三步:启动 microservicecloud-provider-dept 服务提供者 # 访问:http://localhost:8001/dept/get/1 # 访问:http://localhost:9527/microservicecloud-dept/dept/get/1 # 两个结果显示同样信息 # # 路由映射配置 zuul: # ignored-services: "*" #忽略多个服务方式"*"代替 ignored-services: microservicecloud-dept # 设置单个服务名称后真实URL无法访问:http://localhost:9527/microservicecloud-dept/dept/get/1 只可以虚拟URL访问 prefix: /willow #设置统一前缀路径 设置后访问:http://localhost:9527/willow/mydept/dept/get/1 routes: mydept.serviceId: microservicecloud-dept mydept.path: /mydept/** # 访问虚拟URl方式:http://localhost:9527/mydept/dept/get/1
启动后访问注册中心 :http://localhost:7001/ 查看zuul是否注册
四、服务过滤
zuul不仅只是路由,并且还能过滤,做一些安全验证。继续改造工程;
4.1创建过滤器
package com.linjia.com.linjia.springcloud.filter; import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; @Component public class MyFilter extends ZuulFilter { private static Logger log = LoggerFactory.getLogger(MyFilter.class); @Override public String filterType() { return "pre"; } @Override public int filterOrder() { return 0; } @Override public boolean shouldFilter() { return true; } @Override public Object run() { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); log.info(String.format("%s >>> %s", request.getMethod(), request.getRequestURL().toString())); Object accessToken = request.getParameter("token"); if(accessToken == null) { log.warn("token is empty"); ctx.setSendZuulResponse(false); ctx.setResponseStatusCode(401); try { ctx.getResponse().getWriter().write("token is empty"); }catch (Exception e){} return null; } log.info("ok"); return null; } }4.2过滤器方法说明
filterType:返回一个字符串代表过滤器的类型,在zuul中定义了四种不同生命周期的过滤器类型,具体如下:
- pre:路由之前
- routing:路由之时
- post: 路由之后
- error:发送错误调用
- filterOrder:过滤的顺序
- shouldFilter:这里可以写逻辑判断,是否要过滤,本文true,永远过滤。
- run:过滤器的具体逻辑。可用很复杂,包括查sql,nosql去判断该请求到底有没有权限访问。
访问:http://localhost:9527/willow/mydept/dept/get/1 未通过, 返回:token is empty 访问:http://localhost:9527/willow/mydept/dept/get/1?token=22 通过, 返回:{"deptno":1,"dname":"123","db_source":"123"}