目录
1 为什么需要网关
对外提供服务需要有统一的入口,否则微服务的服务那么多,全部开放给外部,一方面ip和端口暴露给外部不安全,另一方面外部调用服务会杂乱无章,非常复杂。网关是服务的门户,所有外部的调用都需要通过网关再到后端的服务,那么使用网关都有哪些好处呢?
- 提供统一接口口,方便接入。
- 收拢公共模块,比如参数校验,加签验签等,减少重复工作。
- 隐藏应用配置,增加安全性。
Zuul是Netflix提供的实现网关的组件,我们只需要引入相关的依赖就可以创建高效可用的网关服务。
2 创建网关实例
2.1 网关实例
创建项目springcloud-zuul,引入zuul依赖,pom.xml配置文件如下所示:
<?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>springcloud-zuul-demo</artifactId>
<groupId>com.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.springcloud</groupId>
<artifactId>springcloud-zuul</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.3.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
<version>1.3.5.RELEASE</version>
</dependency>
</dependencies>
</project>
创建application.yml配置文件,如下所示:
server:
port: 9999
spring:
application:
name: api-geteway
zuul:
routes:
#标识你服务的名字,这里可以自己定义,一般方便和规范来讲还是跟自己服务的名字一样
hello-service:
#服务映射的路径,通过这路径就可以从外部访问你的服务了,目的是为了不爆露你机器的IP,面向服务的路由了,给你选一个可用的出来,
#这里zuul是自动依赖hystrix,ribbon的,不是面向单机
path: /hello-service/**
#这里一定要是你Eureka注册中心的服务的名称,是所以这里配置serviceId因为跟eureka结合了,如果单独使用zuul,那么就必须写自己机器的IP了,
#如url:http://localhost:8080/ 这样的不好就是写死IP了,万一这IP挂了,这高可用性,服务注册那套东西就用不起来了
serviceId: hello-service
eureka:
#客户端
client:
#注册中心地址
service-url:
defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/
创建启动类ZuulApplication.java,引入zuul注解@EnableZuulProxy:
@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}
启动服务注册中心springcloud-eureka1,springcloud-eureka2;启动服务提供者springcloud-provider1,springcloud-provider2;启动网关springcloud-zuul。浏览器访问:
http://localhost:9999/hello-service/hello
一次得到如下结果:
其中hello-service是服务提供者的服务名,可以看出zuul网关把请求分发了,实现了反向代理的能力。
2.2 请求过滤
zuul还提供了请求过滤的能力,以token校验为例来演示一下。创建过滤器类TokenFilter.java
public class TokenFilter extends ZuulFilter {
@Override
public String filterType() {
return "pre";
}
//自定义过滤器执行的顺序,数值越大越靠后执行,越小就越先执行
@Override
public int filterOrder() {
return 0;
}
//控制过滤器生效不生效,可以在里面写一串逻辑来控制
@Override
public boolean shouldFilter() {
return true;
}
//执行过滤逻辑
@Override
public Object run() {
RequestContext context = RequestContext.getCurrentContext();
HttpServletRequest request = context.getRequest();
String token = request.getParameter("token");
if (token == null){
context.setSendZuulResponse(false);
context.setResponseStatusCode(401);
context.setResponseBody("unAuthrized");
return null;
}
return null;
}
}
把过滤器加入spring容器中,启动类修改为
@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
@Bean
public TokenFilter tokenFilter(){
return new TokenFilter();
}
}
重启zuul网关,不带token访问,浏览器访问
http://localhost:9999/hello-service/hello
得到如下所示的结果:
加上token访问,浏览器访问
http://localhost:9999/hello-service/hello?token=boy
依次得到如下结果:
filterType返回一个字符串代表过滤器的类型,在zuul中定义了四种不同生命周期的过滤器类型,具体如下:
pre
:可以在请求被路由之前调用,用在路由映射的阶段是寻找路由映射表的route
:在路由请求时候被调用,具体的路由转发过滤器是在routing路由器具体的请求转发的时候会调用error
:处理请求时发生错误时被调用post
:当routing,error运行完后才会调用该过滤器,是在最后阶段的
3 总结
本文介绍了zuul的作用以及使用方法,感兴趣的小伙伴可以自己搭建zuul网关来做实验,本文源码下载地址:https://github.com/xiaoyususu/springcloud-zuul-demo.git