路由是微服务架构不可或缺的一部分。 它可能映射到您的Web应用程序,列如,/ api / users映射到用户服务,/ api / shop映射到商店服务。 Zuul是Netflix的基于JVM的路由器和服务器端负载均衡器。
Netflix使用Zuul进行以下操作:
- Authentication 认证
- Insights 洞见
- Stress Testing 压力测试
- Canary Testing 金丝雀测试
- Dynamic Routing 动态路由
- Service Migration 服务迁移
- Load Shedding 负载脱落
- Security 安全
- Static Response handling 静态响应处理
- Active/Active traffic management 主动/主动流量管理
首先在xml里加入:
<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>
然后在application加入@EnableZuulProxy,开启zuul的功能:
@EnableZuulProxy
@EnableEurekaClient
@SpringBootApplication
public class ServiceZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceZuulApplication.class, args);
}
@Bean
public MyFilter myFilter(){//在主类中添加过滤器
return new MyFilter();
}
}
接下来就是配置yml的时候了
eureka:
client:
serviceUrl:
defaultZone: http://localhost:1122/eureka/
server:
port: 1188
spring:
application:
name: service-zuul
zuul:
routes:
api-a:
path: /api-a/**
serviceId: service-ribbon
api-b:
path: /api-b/**
serviceId: service-feign
这意味着对“/ api-a”的http呼叫转发到“service-ribbon”服务,这意味着对“/ api-b”的http呼叫转发到“service-feign”服务。路由必须有一个“路径”,可以指定为蚂蚁样式模式,所以“/api-a / *”只匹配一个级别,但“/api-a/ **”分层匹配。
zuul编写预过滤
PRE:这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
ROUTING:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用Apache HttpClient或Netfilx Ribbon请求微服务。
POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
ERROR:在其他阶段发生错误时执行该过滤器
@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;
}
}