1、gateway相关介绍

在微服务架构中,系统往往由多个微服务组成,而这些服务可能部署在不同机房、不同地区、不同域名下。这种情况下,客户端(例如浏览器、手机、软件工具等)想要直接请求这些服务,就需要知道它们具体的地址信息,例如 IP 地址、端口号等。这种客户端直接请求服务的方式存在很多的复杂问题。如:需要维护大量的服务地址、存在跨域请求的问题、每个微服务需要独立认证等。所以我们可以通过 API 网关(gateway)来解决这些问题。所有客户端请求都发生到网关,由网关统一转发到不同的地址。网关还可以 处理一些非业务功能的逻辑,例如权限验证、监控、缓存等。本篇主要讲解通过网关统一请求转发到不同微服务。

2、创建网关服务

首先创建maven项目新建网关模块:

spring cloud gateway网关(一)之网关路由-LMLPHP

pom导入网关相关依赖:

 <dependencies>
        <!--Eureka Client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--特别注意:在 gateway 网关服务中不能引入 spring-boot-starter-web 的依赖,否则会报错-->
        <!-- Spring cloud gateway 网关依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!-- LoadBalancer -->
<!-- 引入spring-cloud-loadbalancer -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<!--ribbon Spring Cloud Ribbon 在高版本移除了 -->
<!-- <dependency>-->
<!-- <groupId>org.springframework.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>-->
<!-- <version>2.2.5.RELEASE</version>-->
<!-- </dependency>-->
    </dependencies>

创建springboot启动类:

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

}

启动类创建成功后,在resources资源目录下创建application.yml文件,用来配置gateway。首先设置服务端口和服务名称:

server:
  port: 8081
spring:
  application:
    name: gateway-server-one

在把网关注册到注册中心:

#客户端注册
eureka:
  instance:
    instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port} #localhost
    hostname: localhost
  client:
    register-with-eureka: true #是否向注册中心注册自己 默认为true
    fetch-registry: true  #是否需要检索服务  默认为true
    service-url:
      defaultZone: http://eternity:1234qwer@localhost:4405/eureka/

配置好之后,可以启动网关。查看网关服务是否可以正常启动以及是否在注册中心注册成功,如果注册成功然后在开始配置网关参数。

spring cloud gateway网关(一)之网关路由-LMLPHP

可以看到服务启动成功,我们看看注册中心是否成功:

spring cloud gateway网关(一)之网关路由-LMLPHP

eureka中心已经有了,说明启动成功。

3、配置gateway路由

spring:
  application:
    name: gateway-server-one
  cloud:
    loadbalancer:
      ribbon:
        enabled: false #使用LoadBalancer, Ribbon 在高版本移除了 切换到ReactiveLoadBalancerClientFilter
    gateway:
      discovery: 
        locator: #路由访问方式:http://Gateway_HOST:Gateway_PORT/大写的serviceId/**,其中微服务应用名默认大写访问。
          enabled: true #开启通过名称找到服务器功能
          lower-case-service-id: true #使用小写service-id
      routes:
        - id: hibernate-server-one-route #路由的ID,没有固定规则,但要求唯一,建议与服务名对应
          uri: http://localhost:8800  #匹配后提供服务的路由地址
          predicates:
            #以下是断言条件,必选全部符合条件
            - Path=/admin/user/**   #断言,路径相匹配的进行路由
            - Method=GET #只能时 GET 请求时,才能访问
        - id: xxl-job-server-one-route
#          uri: http://localhost:8801 #可以设置为服务名
          uri: lb://XXL-JOB-SERVER-MODEL #可以设置为服务名
          predicates:
            - Path=/admin/user/**   #断言,路径相匹配的进行路由, 注意:Path 中 P 为大写
            - After=2022-06-06T03:29:37.318-07:00 # [Asia/Shanghai] # after来进行设置,后面添加一个时间,就是指在什么时间之后这个服务才可以被访问,否则将无法被访问到
#            - After=2030-01-20T17:42:47.789-07:00 # [America/Denver]

配置成功后再次启动网关,查看服务器是否转发成功。

通过网关gateway请求路径访问查找用户信息:

http://localhost:8081/admin/user/

spring cloud gateway网关(一)之网关路由-LMLPHP

通过postman测试接口,查询成功。

4、gateway负载均衡

通过在配置文件中配置路径的uri为注册中心服务器名称,可以实现gateway负载均衡。访问时通过服务名称去查找服务名下面的多个实例,根据配置的策略实现转发到不同实例服务。

 uri: lb://XXL-JOB-SERVER-MODEL #可以设置为服务名

在通过服务名称转发的过程中,有可能转发失败。报找不到服务,接口报错:

spring cloud gateway网关(一)之网关路由-LMLPHP

查看网关控制台发现也报错:

java.net.UnknownHostException: failed to resolve 'xxl-job-server-model' after 4 queries 
    at io.netty.resolver.dns.DnsResolveContext.finishResolve(DnsResolveContext.java:1013) ~[netty-resolver-dns-4.1.58.Final.jar:4.1.58.Final]
    Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
    |_ checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain]
    |_ checkpoint ⇢ HTTP POST "/admin/user/" [ExceptionHandlingWebHandler]
Stack trace:
        at io.netty.resolver.dns.DnsResolveContext.finishResolve(DnsResolveContext.java:1013) ~[netty-resolver-dns-4.1.58.Final.jar:4.1.58.Final]
        at io.netty.resolver.dns.DnsResolveContext.tryToFinishResolve(DnsResolveContext.java:966) ~[netty-resolver-dns-4.1.58.Final.jar:4.1.58.Final]
        at io.netty.resolver.dns.DnsResolveContext.query(DnsResolveContext.java:414) ~[netty-resolver-dns-4.1.58.Final.jar:4.1.58.Final]

没有找到服务名,刚开始以为是设置路由的服务名和注册中心的服务名不一致。经过查找发现是一致。最后查找发现是客户端微服务注册到注册中心的hostname配置错误,需要配置和注册中心一致的hostname。不然网关通过服务名找不到相关地址:

spring cloud gateway网关(一)之网关路由-LMLPHP

查看eureka服务注册地址:

spring cloud gateway网关(一)之网关路由-LMLPHP

所以需要配置客户端hostname:

hostname: localhost

再次重新运行系统,发现报错问题已经解决。

06-07 15:58