局域⽹中就有⽹关(翻译过来就叫作GateWay)这个概念,局域⽹接收或者发送数据出去经过这个⽹关,⽐如⽤Vmware虚拟机软件搭建虚拟机集群的时候,每每咱们须要选择IP段中的⼀个IP做为⽹关地址。
咱们学习的GateWay(Spring Cloud GateWay),它只是众多⽹关解决⽅案中的⼀种,是微服务架构中的重要组成部分java
Spring Cloud GateWay是Spring Cloud的⼀个全新项⽬,⽬标是取代Netflix Zuul,它基于
Spring5.0+SpringBoot2.0+WebFlux(基于⾼性能的Reactor模式响应式通讯框架Netty,异步⾮阻塞模型)等技术开发,性能⾼于Zuul,官⽅测试, GateWay是Zuul的1.6倍,旨在为微服务架构提供⼀种简单有效的统⼀的API路由管理⽅式。
Spring Cloud GateWay不只提供统⼀的路由⽅式(反向代理)而且基于 Filter(定义过滤器对请求过滤,完成⼀些功能) 链的⽅式提供了⽹关基本的功能,例如:鉴权、流量控制、熔断、路径重写、⽇志监控等。git
新建GateWay网关项目,因为gateway不须要引⼊starter-web模块,须要引⼊web-flux,而我们以前的父工程里面有web组件,因此咱们不能以lagou-parent为父工程创建gateway。web
<!--GateWay ⽹关--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!--引⼊webflux--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency>
application.yml中作一些关于路由规则的配置:spring
Spring: application: name: lagou-cloud-gateway cloud: gateway: routes: # 路由能够有多个 - id: service-autodeliver-router # 咱们⾃定义的路由 ID,保持惟⼀ uri: http://127.0.0.1:8090 # ⽬标服务地址 ⾃动投递微服务(部署多实例) #动态路由: uri配置的应该是⼀个服务名称,⽽不该该是⼀个具体的服务实例的地址 # gateway⽹关从服务注册中⼼获取实例信息而后负载后路由 predicates: # 断⾔:路由条件, Predicate 接受⼀个输⼊参数,返回⼀个布尔值结果。该接⼝包含多种默认⽅法来将 Predicate 组合成其余复杂的逻辑(⽐如:与,或,⾮)。 - Path=/autodeliver/** - id: service-resume-router # 咱们⾃定义的路由 ID,保持惟⼀ uri: http://127.0.0.1:8081 # ⽬标服务地址 #http://localhost:9002/resume/openstate/1545132 #http://127.0.0.1:8081/openstate/1545132 predicates: # 断⾔:路由条件, Predicate 接受⼀个输⼊参数,返回⼀个布尔值结果。该接⼝包含多种默 认⽅法来将Predicate 组合成其余复杂的逻辑(⽐如:与,或,⾮)。 - Path=/resume/** filters: - StripPrefix=1
正常访问服务消费者8090的地址是
http://localhost:8090/autodeliver/checkStateTimeoutFallBack/1545132
经过网关配置代理以后的地址:
http://localhost:9002/autodeliver/checkStateTimeoutFallBack/1545132
架构
上面咱们是直接写死了目标服务的请求地址,这样对于咱们集群部署多个服务是不行的,咱们应该改形成从eureka服务注册中心获取服务列表并进行访问,即所谓的动态路由。
动态路由配置方式:url: lb://在eureka注册的服务名称
lb表示从注册中心获取服务,后面是须要转发的服务名称。
例如:app
uri: lb://lagou-service-resume
由于须要从注册中心获取服务列表,因此须要在pom.xml中添加eureka的客户端依赖。
测试:负载均衡
能够看到网关分发请求到不一样的服务,实现了动态路由。框架
从过滤器⽣命周期(影响时机点)的⻆度来讲,主要有两个pre和post:异步
生命周期时机点 | 做用 |
---|---|
pre | 这种过滤器在请求被路由以前调⽤。咱们可利⽤这种过滤器实现身份验证、在集群中选择 请求的微服务、记录调试信息等 |
post | 这种过滤器在路由到微服务之后执⾏。这种过滤器可⽤来为响应添加标准的 HTTPHeader、收集统计信息和指标、将响应从微服务发送给客户端等。 |
从过滤器类型的⻆度, Spring Cloud GateWay的过滤器分为GateWayFilter和GlobalFilter两种:ide
过滤器类型 | 影响范围 |
---|---|
GateWayFilter | 应用到单个路由上 |
GlobalFilter | 应用到全部路由上 |
好比GateWayFilter能够去掉url中的占位后再转发路由,以下:
- id: service-resume-router # 咱们⾃定义的路由 ID,保持惟⼀ #uri: http://127.0.0.1:8081 # ⽬标服务地址 uri: lb://lagou-service-resume # ⽬标服务地址 #http://localhost:9002/resume/openstate/1545132 #http://127.0.0.1:8081/openstate/1545132 predicates: # 断⾔:路由条件, Predicate 接受⼀个输⼊参数,返回⼀个布尔值结果。该接⼝包含多种默 认⽅法来将Predicate 组合成其余复杂的逻辑(⽐如:与,或,⾮)。 - Path=/resume/** filters: - StripPrefix=1
和前面的动态路由相比,主要是添加了下面的参数:
filters: - StripPrefix=1
StripPrefix这个参数的意思是去掉访问url的第一个参数,再进行匹配。
好比http://localhost:9002/resume/openstate/1545132
这个请求,会匹配目标服务的http://127.0.0.1:8081/openstate/1545132
。
思路:请求过来时,判断发送请求的客户端的ip,若是在⿊名单中,拒绝访问.
⾃定义GateWay全局过滤器时,咱们实现Global Filter接⼝便可,经过全局过滤器能够实现⿊⽩名单、限流等功能。
在网关服务中自定义全局过滤器:
@Slf4j @Component public class BlackListFilter implements GlobalFilter, Ordered { private static List<String> blackList=new ArrayList<>(); static { blackList.add("0:0:0:0:0:0:0:1");//模拟本机地址 } /** * 过滤器核⼼⽅法 * @param exchange 封装了request和response对象的上下⽂ * @param chain ⽹关过滤器链(包含全局过滤器和单路由过滤器) * @return */ @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { // 思路:获取客户端ip,判断是否在⿊名单中,在的话就拒绝访问,不在的话就放⾏ // 从上下⽂中取出request和response对象 ServerHttpRequest request = exchange.getRequest(); ServerHttpResponse response = exchange.getResponse(); // 从request对象中获取客户端ip String clientIp = request.getRemoteAddress().getHostString(); // 拿着clientIp去⿊名单中查询,存在的话就拒绝访问 if(blackList.contains(clientIp)){ //// 拒绝访问,返回 response.setStatusCode(HttpStatus.UNAUTHORIZED); log.debug("------>Ip:"+clientIp+" 在黑名单中,被拒绝访问!"); String data="Request be denied!!"; DataBuffer wrap = response.bufferFactory().wrap(data.getBytes()); return response.writeWith(Mono.just(wrap)); } // 合法请求,放⾏,执⾏后续的过滤器 return chain.filter(exchange); } /** * 返回值表示当前过滤器的顺序(优先级),数值越⼩,优先级越⾼ * @return */ @Override public int getOrder() { return 0; } }
效果:
⽹关做为⾮常核⼼的⼀个部件,若是挂掉,那么全部请求均可能⽆法路由处理,所以咱们须要作
GateWay的⾼可⽤。
GateWay的⾼可⽤很简单: 能够启动多个GateWay实例来实现⾼可⽤,在GateWay的上游使⽤Nginx等负载均衡设备进⾏负载转发以达到⾼可⽤的⽬的。
举例:
启动多个GateWay实例(假如说两个,⼀个端⼝9002,⼀个端⼝9003),剩下的就是使⽤Nginx等完成负载代理便可。示例以下:
upstream gateway { server 127.0.0.1:9002; server 127.0.0.1:9003; } location / { proxy_pass http://gateway; }
gateway案例源码地址:gateway案例源码地址
欢迎访问个人博客:https://www.liuyj.top