书接上回,这个接的有点久(手动滑稽)。。。
上次说道使用Nginx对coap接入做负载均衡,让协议服务器可以横向扩展,但我们的设备管理系统在访问时还是访问的我们服务器的地址,如果现在有其它服务要调用我们的设备管理系统如果直接使用其ip地址会有服务地址暴露的风险,并且后期如果做鉴权,都不好做,所以这里我们引出了spring cloud另外一个组件,zuul网关。
Zuul是什么
zuul是netfilx开源的一个api gateway服务器,记住是api 服务器,它只能做api请求网关,或者说是http请求的网关。像上面我们用Nginx做udp路由,使用的是端口监听,它是做不了的。
为啥要用zuul 它能干啥
为啥要用zuul,因为统一入口呀,统一入口能干啥,那可就多了哦
- 审查与监控
- 动态路由,负载均衡
- 静态响应处理
- 验证与安全保障
为啥它能干这么多事呢?
上面说zuul是一个api服务器,它本质上是一个web servlet服务器,或者说是个filter应用,专干拦截过滤的勾当((^o^)/~)。
zuul核心原理
zuul的工作流程是一系列的filters,和servlet的filter,spring中的aop是一样一样儿的。
一个http请求要走的路
http请求->zuul servlet->zuulFilter Runner -> filter1->filter2->.... ->业务服务器-> filter2->filter1->http response
这有点向什么,Status2的拦截器,也是请求的时候一个关卡一个关卡的过去,回来的时候在从后面的关卡一个一个的回来。
知道工作流程,突然发现一个问题,filter之间是如何传递数据的,一般这种问题就两种解决方案,一是我自己走哪儿带哪儿,这个好理解,就想我们带钱一样,就揣我兜里,想用的时候就用,二是放在一个地方我用的时候在去拿,这就比如钱太多了拿不动,咋办,放银行,用的时候我再去取。
zuul采用的是第二种方式,filter之前通过一个requestContext的静态类对进行数据的传递,那我把数据放进去了我取得时候咋知道是我的呢,钱存银行,银行会给你发张卡,你凭卡取钱,requestContext可没有卡,但它有另一个东西,ThreadLocal线程数据缓存器,这数据是A线程存的,那只有你A线程才能取出来,其它线程只能瞅着,错,连瞅都瞅不了。
刚才我们说网关是一个服务的入口,或者说是一个服务集群的入口,它的核心是filter,但我们又时候需要加一些新的filter,来满足我们新的需求,但是我们又不能把网关给停的,网关停了不整个服务就干瞪眼了么,所以我们需要它能动态地加载filter。
zuul的过滤器是由groovy写成的,这些过滤器被放在了zull server上特定的目录下面,zuul会定期轮训这些目录,修改过的过滤器会动态地加载到zuul server中以便过滤请求使用。这就满足了我们动态增过滤器的需求。
zuul过滤器类型
- zuul定义了四种过滤器类型,这些过滤器类型对应请求的处于什么周期
- pre:请求路由之间调用,可以做权限检测
- routing:这种过滤器将请求,这种过滤器用于构建发送到微服务的请求,并使用Apache httpClient或ribbon请求微服务
- post:这种过滤器在路由到微服务以后执行,可以用来添加标准的http header,收集统计信息和指标,将响应从微服务发送给客户端
- error:在其它阶段发生错误是执行
这就有点想aop的请求前,请求后,发生错误执行了。
zuul还内置了两个特殊的过滤器
staticResponseFilter:允许从zull本身生成响应,而不是将请求转发,网关不是做转发么,它自己响应请求是个什么鬼,看名字静态?是噻,像那种百年不变的js,css,图片这种静态资源完全可以由网关自己响应。
surgicalDebugFilter:允许将特定请求路由到分隔的调试集群和主机上
关于zuul就简单介绍一下,下面开始编写代码。
创建protocol-zuul
maven配置
org.springframework.cloud
spring-cloud-starter-netflix-zuul
2.1.1.RELEASE
cn.le
consul-discovery-client
0.0.1-SNAPSHOT
#application配置
spring.application.name=protocol-zuul
server.port=8888
#健康检查路径
spring.cloud.consul.discovery.health-check-path=/actuator/health
#eureka.client.service-url.defaultZone=http://127.0.0.1:1111/eureka/
spring.cloud.consul.discovery.prefer-ip-address=true
spring.cloud.consul.discovery.instance-id=${spring.application.name}:${server.port}
spring.cloud.consul.discovery.hostname=${spring.application.name}
spring.cloud.consul.discovery.service-name=${spring.application.name}
#配置路由到此服务器
zuul.routes.api-a.service-id=iot-manage
#配置路由规则
zuul.routes.api-a.path=/manage/**
zuul.routes.api-a.stripPrefix=false
zuul关于路由映射的方式两种,一种是使用ip映射,一种是现在使用的这种zuul.routes.api-a.service-id的方法,ip映射的方式可以在独立使用zuul的时候使用,我们这里使用了注册中心,所以使用id名称映射的方式,这种方式对动态扩容,服务发现、注册友好。
而ip映射,电脑的IP地址有时候是会变动的,一旦变动,懂了赛。
启动zuul服务
zuul启动后,在consul的管理页面就可以看到zuul的服务了。
前面我们直接访问一下http://127.0.0.1:8081/manage/swagger-ui.html 可以正常打开设备管理系统的swagger的界面,但是现在我们有的服务网关,需要从服务网关去访问, http://127.0.0.1:8888/manage/swagger-ui.html 8888是zuul服务的端口,利用访问zuul的方式去访问设备管理系统看看能不能成功打开swagger。
一样能正常打开,这就表示zuul成功了。
自定义过滤器
刚才我们只用利用zuul去访问manager系统,但是没做任何处理,如果我们需要在访问之前对请求做处理,比如验证是否登录。
创建AuthFilter类,并继承ZuulFilter,作用是声明AuthFilter是一个ZuulFilter,并且可以让ZuulFilter Runner调用。
package cn.le.pre;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
[@Component](https://my.oschina.net/u/3907912)
/**
* 自定义过滤器,继承zuulFilter即可
*/
public class AuthFilter extends ZuulFilter {
//pre类型,请求路由之前调用
[@Override](https://my.oschina.net/u/1162528)
public String filterType() {
return "pre";
}
//过滤器的执行顺序,数字越小表示越先执行
[@Override](https://my.oschina.net/u/1162528)
public int filterOrder() {
return 0;
}
//判断此过滤器是否执行,true执行,false不执行
[@Override](https://my.oschina.net/u/1162528)
public boolean shouldFilter() {
return true;
}
//过滤器执行逻辑
[@Override](https://my.oschina.net/u/1162528)
public Object run() throws ZuulException {
RequestContext context = RequestContext.getCurrentContext();
HttpServletRequest request = context.getRequest();
System.out.println("AuthFilter----"+request);
return null;
}
}
这里只打印了请求信息,并没有写关于登录的逻辑,因为登录是一个综合组件配套的逻辑,这里篇幅有限就不实现了。
重新访问一下http://192.168.0.105:8888/manage/swagger-ui.html
从控制台日志我们可以看出对请求进行的过滤。
zuul 1.0与zuul 2.0对比
这个就看一下程序员DD大牛写的,我就不献丑了,zuul 1.0与2.0从设计结构与流程上都发生了变化,区别还是蛮大的。
http://blog.didispace.com/api-gateway-Zuul-1-zuul-2-how-to-choose/
结束语
https://gitee.com/distant/cloud-work.git
https://gitee.com/distant/iot-pt.git