区块链技术博客
www.b2bchain.cn

Spring Cloud Alibaba微服务架构实战教程—15最全面的Gateway统一网关求职学习资料

本文介绍了Spring Cloud Alibaba微服务架构实战教程—15最全面的Gateway统一网关求职学习资料,有助于帮助完成毕业设计以及求职,是一篇很好的资料。

对技术面试,学习经验等有一些体会,在此分享。

前言

在分布式微服务架构中,会将服务进行拆分,不同的服务负责各自的业务功能,拆分后也有一个问题?每一个服务都有自己的服务名、ip、端口等,服务越多数量越多时,这样怎么记忆这么多的URL呢? 此外,一些公共性的功能(如认证、鉴权、服务流控等)需要重复在各子模块中自身实现,造成的代码冗余怎么办?
Spring Cloud Alibaba微服务架构实战教程—15最全面的Gateway统一网关

网关图

如图,诞生了一个统一网关,它将所有子服务封装起来,外部请求服务时,由网关统一调配URL和转发各个请求到不同的微服务去,并且可以在网关层针对所有公共性的功能作统一的处理,避免冗余。

一、网关简介

网关介绍:

  • 网关:流量请求的入口
  • 功能:服务网关 = 路由转发+过滤器。
  • 路由转发:接受一切外界的请求,转发到后端的微服务上去。
  • 过滤器:在网关中可以完成一系列的横切功能,如权限校验,限流,及监控等。(其实路由转发也是个过滤器)

本案例项目中,网关的作用:

  • Smartcat-project 项目中,后台请求会先访问到API网关,然后网关通过注册中心实时感知各个微服务的状态及路由地址,最后准确地将请求路由到具体的服务中去处理。
    如图:
    Spring Cloud Alibaba微服务架构实战教程—15最全面的Gateway统一网关
    API网关工作图

既然网关作用这么大,我们该怎么实现它呢?就可以借用一下开源组件了。

  • 第一代网关Zuul,阻塞式,不支持websockets长连接,是netflix公司项目。(底层是servlet,Zuul处理的是http请求)
  • 第二代网关Gateway 是基于Netty,由Cloud官方提供,使用的是异步IO,非阻塞式,性能较Zuul提升1.6倍不止。

二、Gateway网关组件

注意:GateWay跟 Servlet 不兼容,不能打成war包,工程中不能出现Servlet的组件。

根据 官方的原理图:
Spring Cloud Alibaba微服务架构实战教程—15最全面的Gateway统一网关

在这里插入图片描述

可知,网关原理大致如下:

  • 请求到达网关后,先经过断言Predicate(主要用来判断一个参数是否符合要求);

  • 判断是否符合某个路由的规则?如果符合,则按规则路由到指定地址,如不符合,则退回请求;

  • 请求和响应可以通过过滤器Filter进行配置,过滤I一些不正常的请求和异常返回。

使用gateway之后,客户端只需要记住一个gateway的地址即可,类似于java变量的作用,用来标识内存地址。不用记录地址,只需要记录变量名称,也好比学校的传达室,从此由他来传达请求。

三、项目集成gateway网关

由于geateway是一个相对独立的个体,而且作用和其安全性不言而喻,因此在我们当前的项目中,集成gateway网关,我们采用再建立一个单独的子模块,实现网关功能。

3.1.创建Gateway子模块

创建Gateway 微服务,取名smartcar-gateway,如下所示:
Spring Cloud Alibaba微服务架构实战教程—15最全面的Gateway统一网关

创建网关微服务

3.2.引入Gateway依赖

在其pom.xml中,引入Gateway依赖,与父类关联。

<parent>     <groupId>com.smart.car.root</groupId>     <artifactId>smartcar-project</artifactId>     <version>0.0.1-SNAPSHOT</version> </parent> <!--引入gateway--> <dependency>     <groupId>org.springframework.cloud</groupId>     <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>

注意:记得如果自动生成的项目中,存在web依赖,请删除掉。因为Gateway跟 Servlet 不兼容。(你知道为什么吗?)

3.3.在父类中聚合Gateway模块

在父类的pom.xml中,增加聚会服务的标识。
Spring Cloud Alibaba微服务架构实战教程—15最全面的Gateway统一网关

聚合网关服务

这样打包的时候,会起到聚合作用。

3.4.添加配置文件

Gateway网关的路由过滤器有两种配置方式:

  • 1.在配置文件yml中配置
  • 2.代码中注入RouteLocator的Bean(用编码的方式实现路由映射)

这种用编码方式实现gateway进行路由映射的配置方法,自行百度即可,具体不表述。 但是有一点需要记住,这两种方式都是不支持动态配置的。(在本案例中,采用第一种配置方案)

将application.properties改为application.yml。

server:   port: 8008 spring:   application:     name: samrtcar-geteway   cloud:     #gateway config     gateway:       discovery:         locator:           enabled: true  #开启网关映射           lower-case-service-id: true #将请求路径上的服务名配置为小写           filters:  #去掉path的前缀             - StripPrefix=1       #配置路由数组       routes:         #member子服务         - id: member_service      #自定义唯一名称-限流时用到           uri: http://localhost:8003  #映射提供服务的uri           predicates:             - Path= /member/**   #断言,映射路径 #          filters:             #去掉前缀,视自身URL而定 #            - StripPrefix=1         #路由实例         - id: route_baidu           uri: http://www.baidu.com           predicates:             - Query= url,baidu

注意,写的是URI不是URL,你知道两者区别么?我们在配置中,指定当Path中含有member/路径时候,就会路由到localhost:8003的微服务去,也就是member项目的接口去。这样就实现了路由的转发。

参数说明:

  • StripPrefix=1,是去掉URL的前缀,如果你发现你访问地址老是404,请检查是否需要开启去前缀。

  • Predicates(断言):一个Java 8的定义。 作用:符合 Predicate 条件的,就使用该路由配置,否则就不管。(用来判断是否符合规范的)。

3.5.启动项目测试

启动member项目和gateway项目,访问URL。

目前有两种方式可以访问接口,一种是直接访问原服务的URL,一种是访问网关,网关再路由到对应服务URL去。

访问效果:
Spring Cloud Alibaba微服务架构实战教程—15最全面的Gateway统一网关

网关访问

其次,只要当请求中包含 url=baidu的就会进行匹配和路由到baidu网站了。

测试效果:
Spring Cloud Alibaba微服务架构实战教程—15最全面的Gateway统一网关

CURL测试

上面这种做法是直接在配置文件中配置了路由地址, 但是有个问题?到此,依然可以直接访问其目标服务的接口,那以后别人绕开网关直接访问URL怎么办? 所以就不让直接请求具体的服务,请求都走网关,就是只开放网关的端口,其它微服务的端口都不对外开放-需要直接隐藏起来。

微服务开发,各种服务都是用nacos注册中心来统一管理的,nacos中通过服务名也有映射,那现在我们应该让 gateway 直接去 nacos 中发现服务 ,然后再自动转发到对应的服务去。

四、Gateway结合Nacos

4.1.引入Nacos组件

因common模块引入了nacos注册中心组件,所以我们可以直接引用common模块。

<!--引入公共工具微服务--> <dependency>     <groupId>com.smart.car.common</groupId>     <artifactId>smartcar-common</artifactId>     <version>0.0.1-SNAPSHOT</version>    <exclusions>        <!--排出servlet容器-->        <exclusion>            <groupId>org.apache.tomcat.embed</groupId>            <artifactId>tomcat-embed-core</artifactId>        </exclusion>    </exclusions> </dependency>

注意:Gateway跟 Servlet 不兼容,所以网关服务中不能出现spring-web类的依赖。(你知道为什么吗?)

4.2.添加开启nacos注解

启动类上添加开启nacos的@EnableDiscoveryClient注解

@RefreshScope @EnableDiscoveryClient @SpringBootApplication public class SmartGatewayApplication {     public static void main(String[] args) {         SpringApplication.run(SmartGatewayApplication.class, args);     } }

4.3.配置路由方式

在yml中配置nacos地址,还需要配置新的路由方式。

在gateway中配置uri配置有三种方式,包括

  • 第一种:websocket方式: uri: ws://localhost:9000
  • 第二种:http方式: uri: http://localhost:8130/
  • 第三种:lb(注册中心中服务名字)方式: uri: lb://brilliance-consumer

其中ws和http方式不容易出错,因为http格式比较固定,但是lb方式比较灵活自由,且使用 uri: lb:// 方式配置时,服务名有特殊要求(见文末)。

  • lb: //后面的是其他服务注册在nacos上的名称,也就是spring.applicaiton.name属性。

我们采用lb的方式配置,如下:

server:   port: 8008 spring:   application:     name: samrtcar-geteway   cloud:     #nacos config     nacos:       discovery:         server-addr: 127.0.0.1:8848         register-enabled: true     #gateway config     gateway:       discovery:         locator:           enabled: true  #开启网关映射           lower-case-service-id: true #将请求路径上的服务名配置为小写           filters:            #去掉path的前缀             - StripPrefix=1       #配置路由数组       routes:         #member子服务         - id: member_route      #自定义唯一名称           uri: lb://smartcar-member  # 映射提供服务的uri           predicates:             - Path= /member/**   #断言,映射路径 #          filters:             #去掉前缀,视URL而定 #            - StripPrefix=1

当选择了nacos做服务的映射,则不需要考虑前缀问题,会自动处理。

4.4.测试lb路由方式

启动member8003和80013两个服务和gateway8008一个服务,如图:
Spring Cloud Alibaba微服务架构实战教程—15最全面的Gateway统一网关

启动项目测试

然后查看naocs注册列表:
Spring Cloud Alibaba微服务架构实战教程—15最全面的Gateway统一网关

nacos注册列表

通过网关访问接口:http://localhost:8008/member//list ,

你会发现在,接口在 轮询 请求8003和8004端口的member服务,不光证明了可以通过网关调用服务,还证明了相同服务的负载均衡成功。
Spring Cloud Alibaba微服务架构实战教程—15最全面的Gateway统一网关

网关调用

这样以后,前端直接访问网关,不必再关心子服务的服务名、服务端口,路由地址等情况,即使是我们修改了其他服务的端口号,也不影响前端的调用。

五、网关服务熔断

网关虽然仅仅是转发路由到对应服务,但是也是请求的入口处,如果对应的服务宕机了,请求就会一致堆积在网关处,为了不引起网关的阻塞,我们需要在网关处,配置熔断机制。

本实例降级方案,就采用hystrix来快速熔断吧。在前文中我说过,真正的业务开发上,很多都是多组件相互协助,并不是仅仅靠谁就可以独立完成。

5.1.采用hystrix快速熔断

因此,网关的熔断,我们用hystrix来快速完成工作。

1.引入hystrix依赖。

<dependency>     <groupId>org.springframework.cloud</groupId>     <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency>

2.设置熔断超时时间设置

#hystrix超时时间,默认时间为1000ms hystrix:   command:     default:       execution:         isolation:           thread:             timeoutInMilliseconds: 2000

3.新增降级兜底方法

熔断后,会由gateway层提供一个快速失败的方法返回给请求的调用方,我们也可称为降级过滤器

@Slf4j @RestController @RequestMapping("error") public class FallbackController {      @RequestMapping("/fallback")     public ResponseResult<String> fallback() {         ResponseResult<String> result = new ResponseResult<>();         log.error("Invoke service failed...");         result.setCode(429);         result.setMsg("对应的服务调用失败,快速熔断,进入fallback降级方法。");         return result;     } }

4.配置指定的过滤器

并在yml配置文件中指向该降级过滤器

#member子服务 - id: member-service      #自定义唯一名称-限流时用到   uri: lb://smartcar-member  # 映射提供服务的uri   predicates:     - Path= /member/**   #断言,映射路径   filters:     #结合Hystrix对服务宕机做fallback机制(降级过滤器)     - name: Hystrix       args:         name: fallback         fallbackUri: forward:/error/fallback

还有一种情况,假如服务是暂时的不可用,发起重试之后又能调用正常返回结果,则可以设置重试次数,来确保服务的可用性,我们称为重试过滤器

配置如下:

fallbackUri: forward:/error/fallback  #重试次数(重试过滤器)(若两者都配置了,降级过滤器需要配在重试过滤器之前) - name: Retry   args:     #重试3次,加上初次访问,正确执行应当是4次访问     retries: 3     statuses:       - OK     methods:       - GET       - POST

这就需要你在对应的调用方法上,人为增加一个异常,才会触发。本案例不详说。

最终给出完整的yml内容:

“`yml
server:
port: 8008
servlet:
context-path: /gateway

logback配置

logging:
level:
root: info
#关闭nacos心跳日志
com.alibaba.nacos.client.*: WARN
#org.springframework:cloud.gateway: debug
file:
name: ./tmp/gateway.log

spring:
application:
name: samrtcar-geteway
cloud:
#nacos config
nacos:
discovery:
server-addr: 127.0.0.1:8848
register-enabled: true
#gateway config
gateway:
#开启网关映射
discovery:
locator:
enabled: true
lower-case-service-id: true #将请求路径上的服务名配置为小写
filters: #去掉path的前缀,视自身URL而定
– StripPrefix=1
#配置路由数组
routes:
#member子服务
– id: member-service #自定义唯一名称-限流时用到
uri: lb://smartcar-member # 映射提供服务的uri
predicates:
– Path= /member/** #断言,映射路径
filters:
#结合Hystrix对服务宕机做fallback机制(降级过滤器)
– name: Hystrix
args:
name: fallback
fallbackUri: forward:/error/fallback
#重试次数(重试过滤器)(若两者都配置了,位置不可变)
– name: Retry
args:
#重试3次,加上初次访问,正确执行应当是4次访问
retries: 3

前言

在分布式微服务架构中,会将服务进行拆分,不同的服务负责各自的业务功能,拆分后也有一个问题?每一个服务都有自己的服务名、ip、端口等,服务越多数量越多时,这样怎么记忆这么多的URL呢? 此外,一些公共性的功能(如认证、鉴权、服务流控等)需要重复在各子模块中自身实现,造成的代码冗余怎么办?
Spring Cloud Alibaba微服务架构实战教程—15最全面的Gateway统一网关

网关图

如图,诞生了一个统一网关,它将所有子服务封装起来,外部请求服务时,由网关统一调配URL和转发各个请求到不同的微服务去,并且可以在网关层针对所有公共性的功能作统一的处理,避免冗余。

一、网关简介

网关介绍:

  • 网关:流量请求的入口
  • 功能:服务网关 = 路由转发+过滤器。
  • 路由转发:接受一切外界的请求,转发到后端的微服务上去。
  • 过滤器:在网关中可以完成一系列的横切功能,如权限校验,限流,及监控等。(其实路由转发也是个过滤器)

本案例项目中,网关的作用:

  • Smartcat-project 项目中,后台请求会先访问到API网关,然后网关通过注册中心实时感知各个微服务的状态及路由地址,最后准确地将请求路由到具体的服务中去处理。
    如图:
    Spring Cloud Alibaba微服务架构实战教程—15最全面的Gateway统一网关
    API网关工作图

既然网关作用这么大,我们该怎么实现它呢?就可以借用一下开源组件了。

  • 第一代网关Zuul,阻塞式,不支持websockets长连接,是netflix公司项目。(底层是servlet,Zuul处理的是http请求)
  • 第二代网关Gateway 是基于Netty,由Cloud官方提供,使用的是异步IO,非阻塞式,性能较Zuul提升1.6倍不止。

二、Gateway网关组件

注意:GateWay跟 Servlet 不兼容,不能打成war包,工程中不能出现Servlet的组件。

根据 官方的原理图:
Spring Cloud Alibaba微服务架构实战教程—15最全面的Gateway统一网关

在这里插入图片描述

可知,网关原理大致如下:

  • 请求到达网关后,先经过断言Predicate(主要用来判断一个参数是否符合要求);

  • 判断是否符合某个路由的规则?如果符合,则按规则路由到指定地址,如不符合,则退回请求;

  • 请求和响应可以通过过滤器Filter进行配置,过滤I一些不正常的请求和异常返回。

使用gateway之后,客户端只需要记住一个gateway的地址即可,类似于java变量的作用,用来标识内存地址。不用记录地址,只需要记录变量名称,也好比学校的传达室,从此由他来传达请求。

三、项目集成gateway网关

由于geateway是一个相对独立的个体,而且作用和其安全性不言而喻,因此在我们当前的项目中,集成gateway网关,我们采用再建立一个单独的子模块,实现网关功能。

3.1.创建Gateway子模块

创建Gateway 微服务,取名smartcar-gateway,如下所示:
Spring Cloud Alibaba微服务架构实战教程—15最全面的Gateway统一网关

创建网关微服务

3.2.引入Gateway依赖

在其pom.xml中,引入Gateway依赖,与父类关联。

<parent>     <groupId>com.smart.car.root</groupId>     <artifactId>smartcar-project</artifactId>     <version>0.0.1-SNAPSHOT</version> </parent> <!--引入gateway--> <dependency>     <groupId>org.springframework.cloud</groupId>     <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>

注意:记得如果自动生成的项目中,存在web依赖,请删除掉。因为Gateway跟 Servlet 不兼容。(你知道为什么吗?)

3.3.在父类中聚合Gateway模块

在父类的pom.xml中,增加聚会服务的标识。
Spring Cloud Alibaba微服务架构实战教程—15最全面的Gateway统一网关

聚合网关服务

这样打包的时候,会起到聚合作用。

3.4.添加配置文件

Gateway网关的路由过滤器有两种配置方式:

  • 1.在配置文件yml中配置
  • 2.代码中注入RouteLocator的Bean(用编码的方式实现路由映射)

这种用编码方式实现gateway进行路由映射的配置方法,自行百度即可,具体不表述。 但是有一点需要记住,这两种方式都是不支持动态配置的。(在本案例中,采用第一种配置方案)

将application.properties改为application.yml。

server:   port: 8008 spring:   application:     name: samrtcar-geteway   cloud:     #gateway config     gateway:       discovery:         locator:           enabled: true  #开启网关映射           lower-case-service-id: true #将请求路径上的服务名配置为小写           filters:  #去掉path的前缀             - StripPrefix=1       #配置路由数组       routes:         #member子服务         - id: member_service      #自定义唯一名称-限流时用到           uri: http://localhost:8003  #映射提供服务的uri           predicates:             - Path= /member/**   #断言,映射路径 #          filters:             #去掉前缀,视自身URL而定 #            - StripPrefix=1         #路由实例         - id: route_baidu           uri: http://www.baidu.com           predicates:             - Query= url,baidu

注意,写的是URI不是URL,你知道两者区别么?我们在配置中,指定当Path中含有member/路径时候,就会路由到localhost:8003的微服务去,也就是member项目的接口去。这样就实现了路由的转发。

参数说明:

  • StripPrefix=1,是去掉URL的前缀,如果你发现你访问地址老是404,请检查是否需要开启去前缀。

  • Predicates(断言):一个Java 8的定义。 作用:符合 Predicate 条件的,就使用该路由配置,否则就不管。(用来判断是否符合规范的)。

3.5.启动项目测试

启动member项目和gateway项目,访问URL。

目前有两种方式可以访问接口,一种是直接访问原服务的URL,一种是访问网关,网关再路由到对应服务URL去。

访问效果:
Spring Cloud Alibaba微服务架构实战教程—15最全面的Gateway统一网关

网关访问

其次,只要当请求中包含 url=baidu的就会进行匹配和路由到baidu网站了。

测试效果:
Spring Cloud Alibaba微服务架构实战教程—15最全面的Gateway统一网关

CURL测试

上面这种做法是直接在配置文件中配置了路由地址, 但是有个问题?到此,依然可以直接访问其目标服务的接口,那以后别人绕开网关直接访问URL怎么办? 所以就不让直接请求具体的服务,请求都走网关,就是只开放网关的端口,其它微服务的端口都不对外开放-需要直接隐藏起来。

微服务开发,各种服务都是用nacos注册中心来统一管理的,nacos中通过服务名也有映射,那现在我们应该让 gateway 直接去 nacos 中发现服务 ,然后再自动转发到对应的服务去。

四、Gateway结合Nacos

4.1.引入Nacos组件

因common模块引入了nacos注册中心组件,所以我们可以直接引用common模块。

<!--引入公共工具微服务--> <dependency>     <groupId>com.smart.car.common</groupId>     <artifactId>smartcar-common</artifactId>     <version>0.0.1-SNAPSHOT</version>    <exclusions>        <!--排出servlet容器-->        <exclusion>            <groupId>org.apache.tomcat.embed</groupId>            <artifactId>tomcat-embed-core</artifactId>        </exclusion>    </exclusions> </dependency>

注意:Gateway跟 Servlet 不兼容,所以网关服务中不能出现spring-web类的依赖。(你知道为什么吗?)

4.2.添加开启nacos注解

启动类上添加开启nacos的@EnableDiscoveryClient注解

@RefreshScope @EnableDiscoveryClient @SpringBootApplication public class SmartGatewayApplication {     public static void main(String[] args) {         SpringApplication.run(SmartGatewayApplication.class, args);     } }

4.3.配置路由方式

在yml中配置nacos地址,还需要配置新的路由方式。

在gateway中配置uri配置有三种方式,包括

  • 第一种:websocket方式: uri: ws://localhost:9000
  • 第二种:http方式: uri: http://localhost:8130/
  • 第三种:lb(注册中心中服务名字)方式: uri: lb://brilliance-consumer

其中ws和http方式不容易出错,因为http格式比较固定,但是lb方式比较灵活自由,且使用 uri: lb:// 方式配置时,服务名有特殊要求(见文末)。

  • lb: //后面的是其他服务注册在nacos上的名称,也就是spring.applicaiton.name属性。

我们采用lb的方式配置,如下:

server:   port: 8008 spring:   application:     name: samrtcar-geteway   cloud:     #nacos config     nacos:       discovery:         server-addr: 127.0.0.1:8848         register-enabled: true     #gateway config     gateway:       discovery:         locator:           enabled: true  #开启网关映射           lower-case-service-id: true #将请求路径上的服务名配置为小写           filters:            #去掉path的前缀             - StripPrefix=1       #配置路由数组       routes:         #member子服务         - id: member_route      #自定义唯一名称           uri: lb://smartcar-member  # 映射提供服务的uri           predicates:             - Path= /member/**   #断言,映射路径 #          filters:             #去掉前缀,视URL而定 #            - StripPrefix=1

当选择了nacos做服务的映射,则不需要考虑前缀问题,会自动处理。

4.4.测试lb路由方式

启动member8003和80013两个服务和gateway8008一个服务,如图:
Spring Cloud Alibaba微服务架构实战教程—15最全面的Gateway统一网关

启动项目测试

然后查看naocs注册列表:
Spring Cloud Alibaba微服务架构实战教程—15最全面的Gateway统一网关

nacos注册列表

通过网关访问接口:http://localhost:8008/member//list ,

你会发现在,接口在 轮询 请求8003和8004端口的member服务,不光证明了可以通过网关调用服务,还证明了相同服务的负载均衡成功。
Spring Cloud Alibaba微服务架构实战教程—15最全面的Gateway统一网关

网关调用

这样以后,前端直接访问网关,不必再关心子服务的服务名、服务端口,路由地址等情况,即使是我们修改了其他服务的端口号,也不影响前端的调用。

五、网关服务熔断

网关虽然仅仅是转发路由到对应服务,但是也是请求的入口处,如果对应的服务宕机了,请求就会一致堆积在网关处,为了不引起网关的阻塞,我们需要在网关处,配置熔断机制。

本实例降级方案,就采用hystrix来快速熔断吧。在前文中我说过,真正的业务开发上,很多都是多组件相互协助,并不是仅仅靠谁就可以独立完成。

5.1.采用hystrix快速熔断

因此,网关的熔断,我们用hystrix来快速完成工作。

1.引入hystrix依赖。

<dependency>     <groupId>org.springframework.cloud</groupId>     <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency>

2.设置熔断超时时间设置

#hystrix超时时间,默认时间为1000ms hystrix:   command:     default:       execution:         isolation:           thread:             timeoutInMilliseconds: 2000

3.新增降级兜底方法

熔断后,会由gateway层提供一个快速失败的方法返回给请求的调用方,我们也可称为降级过滤器

@Slf4j @RestController @RequestMapping("error") public class FallbackController {      @RequestMapping("/fallback")     public ResponseResult<String> fallback() {         ResponseResult<String> result = new ResponseResult<>();         log.error("Invoke service failed...");         result.setCode(429);         result.setMsg("对应的服务调用失败,快速熔断,进入fallback降级方法。");         return result;     } }

4.配置指定的过滤器

并在yml配置文件中指向该降级过滤器

#member子服务 - id: member-service      #自定义唯一名称-限流时用到   uri: lb://smartcar-member  # 映射提供服务的uri   predicates:     - Path= /member/**   #断言,映射路径   filters:     #结合Hystrix对服务宕机做fallback机制(降级过滤器)     - name: Hystrix       args:         name: fallback         fallbackUri: forward:/error/fallback

还有一种情况,假如服务是暂时的不可用,发起重试之后又能调用正常返回结果,则可以设置重试次数,来确保服务的可用性,我们称为重试过滤器

配置如下:

fallbackUri: forward:/error/fallback  #重试次数(重试过滤器)(若两者都配置了,降级过滤器需要配在重试过滤器之前) - name: Retry   args:     #重试3次,加上初次访问,正确执行应当是4次访问     retries: 3     statuses:       - OK     methods:       - GET       - POST

这就需要你在对应的调用方法上,人为增加一个异常,才会触发。本案例不详说。

最终给出完整的yml内容:

“`yml
server:
port: 8008
servlet:
context-path: /gateway

logback配置

logging:
level:
root: info
#关闭nacos心跳日志
com.alibaba.nacos.client.*: WARN
#org.springframework:cloud.gateway: debug
file:
name: ./tmp/gateway.log

spring:
application:
name: samrtcar-geteway
cloud:
#nacos config
nacos:
discovery:
server-addr: 127.0.0.1:8848
register-enabled: true
#gateway config
gateway:
#开启网关映射
discovery:
locator:
enabled: true
lower-case-service-id: true #将请求路径上的服务名配置为小写
filters: #去掉path的前缀,视自身URL而定
– StripPrefix=1
#配置路由数组
routes:
#member子服务
– id: member-service #自定义唯一名称-限流时用到
uri: lb://smartcar-member # 映射提供服务的uri
predicates:
– Path= /member/** #断言,映射路径
filters:
#结合Hystrix对服务宕机做fallback机制(降级过滤器)
– name: Hystrix
args:
name: fallback
fallbackUri: forward:/error/fallback
#重试次数(重试过滤器)(若两者都配置了,位置不可变)
– name: Retry
args:
#重试3次,加上初次访问,正确执行应当是4次访问
retries: 3

前言

在分布式微服务架构中,会将服务进行拆分,不同的服务负责各自的业务功能,拆分后也有一个问题?每一个服务都有自己的服务名、ip、端口等,服务越多数量越多时,这样怎么记忆这么多的URL呢? 此外,一些公共性的功能(如认证、鉴权、服务流控等)需要重复在各子模块中自身实现,造成的代码冗余怎么办?
Spring Cloud Alibaba微服务架构实战教程—15最全面的Gateway统一网关

网关图

如图,诞生了一个统一网关,它将所有子服务封装起来,外部请求服务时,由网关统一调配URL和转发各个请求到不同的微服务去,并且可以在网关层针对所有公共性的功能作统一的处理,避免冗余。

一、网关简介

网关介绍:

  • 网关:流量请求的入口
  • 功能:服务网关 = 路由转发+过滤器。
  • 路由转发:接受一切外界的请求,转发到后端的微服务上去。
  • 过滤器:在网关中可以完成一系列的横切功能,如权限校验,限流,及监控等。(其实路由转发也是个过滤器)

本案例项目中,网关的作用:

  • Smartcat-project 项目中,后台请求会先访问到API网关,然后网关通过注册中心实时感知各个微服务的状态及路由地址,最后准确地将请求路由到具体的服务中去处理。
    如图:
    Spring Cloud Alibaba微服务架构实战教程—15最全面的Gateway统一网关
    API网关工作图

既然网关作用这么大,我们该怎么实现它呢?就可以借用一下开源组件了。

  • 第一代网关Zuul,阻塞式,不支持websockets长连接,是netflix公司项目。(底层是servlet,Zuul处理的是http请求)
  • 第二代网关Gateway 是基于Netty,由Cloud官方提供,使用的是异步IO,非阻塞式,性能较Zuul提升1.6倍不止。

二、Gateway网关组件

注意:GateWay跟 Servlet 不兼容,不能打成war包,工程中不能出现Servlet的组件。

根据 官方的原理图:
Spring Cloud Alibaba微服务架构实战教程—15最全面的Gateway统一网关

在这里插入图片描述

可知,网关原理大致如下:

  • 请求到达网关后,先经过断言Predicate(主要用来判断一个参数是否符合要求);

  • 判断是否符合某个路由的规则?如果符合,则按规则路由到指定地址,如不符合,则退回请求;

  • 请求和响应可以通过过滤器Filter进行配置,过滤I一些不正常的请求和异常返回。

使用gateway之后,客户端只需要记住一个gateway的地址即可,类似于java变量的作用,用来标识内存地址。不用记录地址,只需要记录变量名称,也好比学校的传达室,从此由他来传达请求。

三、项目集成gateway网关

由于geateway是一个相对独立的个体,而且作用和其安全性不言而喻,因此在我们当前的项目中,集成gateway网关,我们采用再建立一个单独的子模块,实现网关功能。

3.1.创建Gateway子模块

创建Gateway 微服务,取名smartcar-gateway,如下所示:
Spring Cloud Alibaba微服务架构实战教程—15最全面的Gateway统一网关

创建网关微服务

3.2.引入Gateway依赖

在其pom.xml中,引入Gateway依赖,与父类关联。

<parent>     <groupId>com.smart.car.root</groupId>     <artifactId>smartcar-project</artifactId>     <version>0.0.1-SNAPSHOT</version> </parent> <!--引入gateway--> <dependency>     <groupId>org.springframework.cloud</groupId>     <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>

注意:记得如果自动生成的项目中,存在web依赖,请删除掉。因为Gateway跟 Servlet 不兼容。(你知道为什么吗?)

3.3.在父类中聚合Gateway模块

在父类的pom.xml中,增加聚会服务的标识。
Spring Cloud Alibaba微服务架构实战教程—15最全面的Gateway统一网关

聚合网关服务

这样打包的时候,会起到聚合作用。

3.4.添加配置文件

Gateway网关的路由过滤器有两种配置方式:

  • 1.在配置文件yml中配置
  • 2.代码中注入RouteLocator的Bean(用编码的方式实现路由映射)

这种用编码方式实现gateway进行路由映射的配置方法,自行百度即可,具体不表述。 但是有一点需要记住,这两种方式都是不支持动态配置的。(在本案例中,采用第一种配置方案)

将application.properties改为application.yml。

server:   port: 8008 spring:   application:     name: samrtcar-geteway   cloud:     #gateway config     gateway:       discovery:         locator:           enabled: true  #开启网关映射           lower-case-service-id: true #将请求路径上的服务名配置为小写           filters:  #去掉path的前缀             - StripPrefix=1       #配置路由数组       routes:         #member子服务         - id: member_service      #自定义唯一名称-限流时用到           uri: http://localhost:8003  #映射提供服务的uri           predicates:             - Path= /member/**   #断言,映射路径 #          filters:             #去掉前缀,视自身URL而定 #            - StripPrefix=1         #路由实例         - id: route_baidu           uri: http://www.baidu.com           predicates:             - Query= url,baidu

注意,写的是URI不是URL,你知道两者区别么?我们在配置中,指定当Path中含有member/路径时候,就会路由到localhost:8003的微服务去,也就是member项目的接口去。这样就实现了路由的转发。

参数说明:

  • StripPrefix=1,是去掉URL的前缀,如果你发现你访问地址老是404,请检查是否需要开启去前缀。

  • Predicates(断言):一个Java 8的定义。 作用:符合 Predicate 条件的,就使用该路由配置,否则就不管。(用来判断是否符合规范的)。

3.5.启动项目测试

启动member项目和gateway项目,访问URL。

目前有两种方式可以访问接口,一种是直接访问原服务的URL,一种是访问网关,网关再路由到对应服务URL去。

访问效果:
Spring Cloud Alibaba微服务架构实战教程—15最全面的Gateway统一网关

网关访问

其次,只要当请求中包含 url=baidu的就会进行匹配和路由到baidu网站了。

测试效果:
Spring Cloud Alibaba微服务架构实战教程—15最全面的Gateway统一网关

CURL测试

上面这种做法是直接在配置文件中配置了路由地址, 但是有个问题?到此,依然可以直接访问其目标服务的接口,那以后别人绕开网关直接访问URL怎么办? 所以就不让直接请求具体的服务,请求都走网关,就是只开放网关的端口,其它微服务的端口都不对外开放-需要直接隐藏起来。

微服务开发,各种服务都是用nacos注册中心来统一管理的,nacos中通过服务名也有映射,那现在我们应该让 gateway 直接去 nacos 中发现服务 ,然后再自动转发到对应的服务去。

四、Gateway结合Nacos

4.1.引入Nacos组件

因common模块引入了nacos注册中心组件,所以我们可以直接引用common模块。

<!--引入公共工具微服务--> <dependency>     <groupId>com.smart.car.common</groupId>     <artifactId>smartcar-common</artifactId>     <version>0.0.1-SNAPSHOT</version>    <exclusions>        <!--排出servlet容器-->        <exclusion>            <groupId>org.apache.tomcat.embed</groupId>            <artifactId>tomcat-embed-core</artifactId>        </exclusion>    </exclusions> </dependency>

注意:Gateway跟 Servlet 不兼容,所以网关服务中不能出现spring-web类的依赖。(你知道为什么吗?)

4.2.添加开启nacos注解

启动类上添加开启nacos的@EnableDiscoveryClient注解

@RefreshScope @EnableDiscoveryClient @SpringBootApplication public class SmartGatewayApplication {     public static void main(String[] args) {         SpringApplication.run(SmartGatewayApplication.class, args);     } }

4.3.配置路由方式

在yml中配置nacos地址,还需要配置新的路由方式。

在gateway中配置uri配置有三种方式,包括

  • 第一种:websocket方式: uri: ws://localhost:9000
  • 第二种:http方式: uri: http://localhost:8130/
  • 第三种:lb(注册中心中服务名字)方式: uri: lb://brilliance-consumer

其中ws和http方式不容易出错,因为http格式比较固定,但是lb方式比较灵活自由,且使用 uri: lb:// 方式配置时,服务名有特殊要求(见文末)。

  • lb: //后面的是其他服务注册在nacos上的名称,也就是spring.applicaiton.name属性。

我们采用lb的方式配置,如下:

server:   port: 8008 spring:   application:     name: samrtcar-geteway   cloud:     #nacos config     nacos:       discovery:         server-addr: 127.0.0.1:8848         register-enabled: true     #gateway config     gateway:       discovery:         locator:           enabled: true  #开启网关映射           lower-case-service-id: true #将请求路径上的服务名配置为小写           filters:            #去掉path的前缀             - StripPrefix=1       #配置路由数组       routes:         #member子服务         - id: member_route      #自定义唯一名称           uri: lb://smartcar-member  # 映射提供服务的uri           predicates:             - Path= /member/**   #断言,映射路径 #          filters:             #去掉前缀,视URL而定 #            - StripPrefix=1

当选择了nacos做服务的映射,则不需要考虑前缀问题,会自动处理。

4.4.测试lb路由方式

启动member8003和80013两个服务和gateway8008一个服务,如图:
Spring Cloud Alibaba微服务架构实战教程—15最全面的Gateway统一网关

启动项目测试

然后查看naocs注册列表:
Spring Cloud Alibaba微服务架构实战教程—15最全面的Gateway统一网关

nacos注册列表

通过网关访问接口:http://localhost:8008/member//list ,

你会发现在,接口在 轮询 请求8003和8004端口的member服务,不光证明了可以通过网关调用服务,还证明了相同服务的负载均衡成功。
Spring Cloud Alibaba微服务架构实战教程—15最全面的Gateway统一网关

网关调用

这样以后,前端直接访问网关,不必再关心子服务的服务名、服务端口,路由地址等情况,即使是我们修改了其他服务的端口号,也不影响前端的调用。

五、网关服务熔断

网关虽然仅仅是转发路由到对应服务,但是也是请求的入口处,如果对应的服务宕机了,请求就会一致堆积在网关处,为了不引起网关的阻塞,我们需要在网关处,配置熔断机制。

本实例降级方案,就采用hystrix来快速熔断吧。在前文中我说过,真正的业务开发上,很多都是多组件相互协助,并不是仅仅靠谁就可以独立完成。

5.1.采用hystrix快速熔断

因此,网关的熔断,我们用hystrix来快速完成工作。

1.引入hystrix依赖。

<dependency>     <groupId>org.springframework.cloud</groupId>     <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency>

2.设置熔断超时时间设置

#hystrix超时时间,默认时间为1000ms hystrix:   command:     default:       execution:         isolation:           thread:             timeoutInMilliseconds: 2000

3.新增降级兜底方法

熔断后,会由gateway层提供一个快速失败的方法返回给请求的调用方,我们也可称为降级过滤器

@Slf4j @RestController @RequestMapping("error") public class FallbackController {      @RequestMapping("/fallback")     public ResponseResult<String> fallback() {         ResponseResult<String> result = new ResponseResult<>();         log.error("Invoke service failed...");         result.setCode(429);         result.setMsg("对应的服务调用失败,快速熔断,进入fallback降级方法。");         return result;     } }

4.配置指定的过滤器

并在yml配置文件中指向该降级过滤器

#member子服务 - id: member-service      #自定义唯一名称-限流时用到   uri: lb://smartcar-member  # 映射提供服务的uri   predicates:     - Path= /member/**   #断言,映射路径   filters:     #结合Hystrix对服务宕机做fallback机制(降级过滤器)     - name: Hystrix       args:         name: fallback         fallbackUri: forward:/error/fallback

还有一种情况,假如服务是暂时的不可用,发起重试之后又能调用正常返回结果,则可以设置重试次数,来确保服务的可用性,我们称为重试过滤器

配置如下:

fallbackUri: forward:/error/fallback  #重试次数(重试过滤器)(若两者都配置了,降级过滤器需要配在重试过滤器之前) - name: Retry   args:     #重试3次,加上初次访问,正确执行应当是4次访问     retries: 3     statuses:       - OK     methods:       - GET       - POST

这就需要你在对应的调用方法上,人为增加一个异常,才会触发。本案例不详说。

最终给出完整的yml内容:

“`yml
server:
port: 8008
servlet:
context-path: /gateway

logback配置

logging:
level:
root: info
#关闭nacos心跳日志
com.alibaba.nacos.client.*: WARN
#org.springframework:cloud.gateway: debug
file:
name: ./tmp/gateway.log

spring:
application:
name: samrtcar-geteway
cloud:
#nacos config
nacos:
discovery:
server-addr: 127.0.0.1:8848
register-enabled: true
#gateway config
gateway:
#开启网关映射
discovery:
locator:
enabled: true
lower-case-service-id: true #将请求路径上的服务名配置为小写
filters: #去掉path的前缀,视自身URL而定
– StripPrefix=1
#配置路由数组
routes:
#member子服务
– id: member-service #自定义唯一名称-限流时用到
uri: lb://smartcar-member # 映射提供服务的uri
predicates:
– Path= /member/** #断言,映射路径
filters:
#结合Hystrix对服务宕机做fallback机制(降级过滤器)
– name: Hystrix
args:
name: fallback
fallbackUri: forward:/error/fallback
#重试次数(重试过滤器)(若两者都配置了,位置不可变)
– name: Retry
args:
#重试3次,加上初次访问,正确执行应当是4次访问
retries: 3

部分转自互联网,侵权删除联系

赞(0) 打赏
部分文章转自网络,侵权联系删除b2bchain区块链学习技术社区 » Spring Cloud Alibaba微服务架构实战教程—15最全面的Gateway统一网关求职学习资料
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

b2b链

联系我们联系我们