本文首要介绍微服务中网关的效果,并比较了几种干流网关的差异,要点介绍了网关gateway。
一、布景介绍
在微服务架构中,一个体系会被拆封成多个微服务,每个微服务能够单独对外提供服务,假如需求统一的对外服务进口则需求网关来完成,网关记载事务微服务的服务名和地址,每次调用能够正确的映射到正确的实在地址上。总的来说网关的效果有:
- 路由转发:外部接口对微服务的调用转发到对应的实在地址上。
- 鉴权认证:网关作为体系的进口,能够在进入体系前进行鉴权和认证。
- 流控:对于进入的流量进行控制,假如流量过大能够进行限流。
- 监控:针对进入的流量进行监控和告警,也能够设置黑白名单等。
常见的网关对比:
- Zuul 1.0 : Netflix开源的网关,运用Java开发,依据Servlet架构构建,便于二次开发。因为依据Servlet内部推迟严峻,并发场景不友好,一个线程只能处理一次连接恳求。
- Zuul 2.0 : 选用Netty完成异步非堵塞编程模型,一个CPU一个线程,能够处理一切的恳求和呼应,恳求呼应的生命周期通过事情和回调进行处理,削减线程数量,开销较小。相比于zuul 1.0,zuul 2.0完成的异步非堵塞的特性,在功能上有较大提升。
- Gateway:是springcloud的全新API网关项目,旨在替换zuul的网关服务,依据spring framework5.0+springboot 2.0+webFlux开发,其也完成了异步非堵塞的特性,有较高的功能,其有丰厚的过滤器类型,能够依据自身需求来自界说过滤器。
- Nginx : 运用Nginx的反向署理和负载均衡完成对API服务器的负载均衡以及高可用,一般放在整个体系的前端,进行静态资源的负载均衡。
- Kong : 依据OpenResty(Nginx + Lua模块)编写的高可用、易扩展的,功能高效且稳定,支撑多个可用插件(限流、鉴权)等,开箱即可用,只支撑HTTP协议,且二次开发扩展难,缺少更易用的管理和装备方法
二、Gateway介绍
1.基本概念
- Route(路由) :路由是构建网关的基本模块,它是由ID,方针URI,一系列的断语和过滤器组成,假如断语为true则匹配该路由。
- Predicate(断语) :开发人员能够匹配HTTP恳求中的一切内容(例如恳求头或者恳求参数),假如恳求和断语相匹配则进行路由。
- Filter(过滤器) :指的是spring框架中GatewayFiletr实例,运用过滤器,能够在恳求被路由前或者后对恳求进行修正。
2.首要流程
流程说明:
-
Gateway Client
向Spring Cloud Gateway
发送恳求。 - 恳求首要会被
HttpWebHandlerAdapter
进行提取组装成网关上下文。 - 然后网关的上下文会传递到
DispatcherHandler
,它负责将恳求分发给RoutePredicateHandlerMapping
。 -
RoutePredicateHandlerMapping
负责路由查找,并依据路由断语判断路由是否可用。 - 假如过断语成功,由
FilteringWebHandler
创建过滤器链并调用。 - 通过特定于恳求的
Fliter
链运转恳求,Filter
被虚线分隔的原因是Filter能够在发送署理恳求之前(pre)和之后(post)运转逻辑。 - 执行一切pre过滤器逻辑。然后进行署理恳求。发出署理恳求后,将运转“post”过滤器逻辑。
- 处理完毕之后将
Response
返回到Gateway
客户端。
3.过滤器
todo
4.核心思维
用户发送的恳求到达Gateway后,依据恳求的匹配条件来匹配真正地址,这个匹配条件能够是URL也能够是服务名,这个匹配条件便是断语(Predicate),匹配后的恳求会通过一系列的过滤,这个便是过滤器起效果的时分。
三、代码实践
利用Gateway作为微服务网关,需求注册中心进行服务注册,在本次实践中,我们选用nacos作为注册中心。
1.装备pom文件
<!--Gateway网关-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- Maven整个生命周期内扫除内置容器,扫除内置容器导出成war包能够让外部容器运转spring-boot项目-->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--nacos服务发现依靠-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
pom文件首要引进spring-cloud-starter-gateway
网关和spring-cloud-starter-loadbalancer
负债均衡,其间可能存在以下问题:
(1)由于spring-cloud-starter-gateway选用的是呼应式的WebFlux web容器,这和spring-boot-starter-web默认的web容器会冲突,所以需求扫除。一般的报错信息如下:
Parameter 0 of method modifyRequestBodyGatewayFilterFactory in org.springframework.cloud.gateway.config.GatewayAutoConfiguration required a bean of type 'org.springframework.http.codec.ServerCodecConfigurer' that could not be found.
(2)引进负债均衡spring-cloud-starter-loadbalancer需求配扫除nacos中的spring-cloud-starter-netflix-ribbon,这两者会包冲突,到时无法运用服务名来进行路由转发。
2.装备文件
server:
port: 9010
spring:
application:
name: test-gateway
cloud:
nacos:
discovery:
server-addr: x.x.x.x:8848
enabled: true
gateway:
routes: # 网关路由装备
- id: my-test # 路由id,自界说,只要仅有即可
# uri: http://127.0.0.1:8081 # 路由的方针地址 http便是固定地址
uri: lb://my-test # 路由的方针地址 lb便是负载均衡,后面跟服务名称
predicates: # 路由断语,也便是判断恳求是否符合路由规则的条件
- Path=/my-test/** # 这个是按照路径匹配,只要以/user/最初就符合要求
装备文件中首要在 spring.gateway.gateway中,其间{spring.gateway.gateway} 中,其间 {routes.uri} 表示需求转发到的URL或者服务名。
3.过滤器
@Slf4j
@Component
public class MyFilter implements Ordered, GlobalFilter {
/**
* @param exchange 能够拿到对应的request和response
* @param chain 过滤器链
* @return 是否放行
*/
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String name = exchange.getRequest().getQueryParams().get("name").get(0);
log.info("用户:{} 开始进入体系", name);
if (!StringUtils.isEmpty(name)) {
if (name.equals("noName")) {
log.info("用户没有访问权限");
exchange.getResponse().setStatusCode(HttpStatus.PROXY_AUTHENTICATION_REQUIRED);
return exchange.getResponse().setComplete();
}
}
return chain.filter(exchange);
}
/**
* 设定过滤器的优先级,值越小则优先级越高
* @return
*/
@Override
public int getOrder() {
return 0;
}
}
假如需求在Gateway中完成过滤器,能够完成GlobalFilter接口,以上Filter是用来进行鉴权的,假如进入网关的恳求没有权限就会被拦截。
TODO
- 把过滤器的类别和效果写的更详细。
参考资料
- 这篇SpringCloud GateWay 详解,你用的到:/post/710791…
- Spring Cloud Gateway:docs.spring.io/spring-clou… (官方文档)
- 14.服务网关Zuul和Gateway:www.cnblogs.com/wmd-l/p/163…
- Spring Cloud Gateway过滤器装备:/post/713874…