前言
在微服务架构中,需要几个基础的服务治理组件,包括服务注册与发现、服务消费、负载均衡、断路器、智能路由、配置管理等,由这几个基础组件相互协作,共同组建了一个简单的微服务系统。一个简答的微服务系统如下图:
在Spring Cloud微服务系统中,一种常见的负载均衡方式是,客户端的请求首先经过负载均衡(Ngnix),到达服务网关(zuul集群),然后再到具体的服务。服务统一注册到高可用的服务注册中心集群,服务的所有的配置文件由配置服务管理(下一篇文章讲述),配置服务的配置文件放在git仓库,实现了配置的统一管理,方便开发人员随时改配置。
一、Zuul简介
Zuul的主要功能是路由转发和过滤器。路由功能是微服务的一部分,zuul默认和Ribbon结合实现了负载均衡的功能。从而客户端只需要统一的调用zuul网关的IP地址,再由网关进行路由转发,而不用因为各个服务不同而更改IP。比如/api/a转发到到a服务,/api/b转发到到b服务。
二、创建zuul工程
继续使用上一章节的工程,再原有工程中新建一个子module工程。创建过程不再赘述,创建好的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>spring-cloud-demo</artifactId>
<groupId>com.cxlsky.www</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>zuul</artifactId>
<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>
</dependencies>
</project>
在其入口主类加上注解@EnableZuulProxy,开启zuul的功能:
@SpringBootApplication(scanBasePackages = {"com.cxlsky"})
@EnableDiscoveryClient
@EnableZuulProxy
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}
增加springboot配置文件application.yml,内容如下:
server:
port: 7000
spring:
application:
name: zuul
eureka:
client:
serviceUrl:
defaultZone: http://10.1.81.33:8000/eureka/
zuul:
routes:
eureka-client-a:
path: /client-a/**
serviceId: eureka-client-a
eureka-client-b:
path: /client-b/**
serviceId: eureka-client-b
以上的配置文件配置了两个路由,以/client-a/**开始的url转发到eureka-client-a服务,以/client-b/**开始的url转发到eureka-client-b服务。
现在我们把所有服务启动,然后用postman调用localhost:7000/client-b/hello/from/a可以得到以下结果:
this is eureka-client-b, port: 8002 and receive hello from: applicationName is: eureka-client-a, port is: 8001
用postman调用localhost:7000/client-a/hello可以得到以下结果:
applicationName is: eureka-client-a, port is: 8001
从上面的结果可以看出,zuul会根据我们配置的规则进行路由转发。
三、服务过滤
zuul不仅只是路由,并且还能过滤,做一些安全验证。如下:
package com.cxlsky;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
/**
* className ZuulFilter
* description ZuulFilter
*
* @author Toby
* @date 2019-6-12
*/
@Component
public class MyZuulFilter extends ZuulFilter {
@Autowired
private HttpServletRequest request;
@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();
ctx.addZuulRequestHeader("X-DOMAIN", request.getRemoteAddr());
ctx.addZuulRequestHeader("USER-INFO", "{\"username\":\"cxl\"}");
return null;
}
}
1、filterType:返回一个字符串代表过滤器的类型,在zuul中定义了四种不同生命周期的过滤器类型,具体如下:
pre:路由之前
routing:路由之时
post: 路由之后
error:发送错误调用
2、filterOrder:过滤的顺序
3、shouldFilter:这里可以写逻辑判断,是否要过滤,本文true,永远过滤。
4、run:过滤器的具体逻辑。可以增加自己需要的业务,这里增加了请求头信息,为后面的服务提供必要信息。