【开发技巧/经验分享】使用zuul构建服务网关ApiGetaway

1. 什么是服务网关?

服务网关就好比是一个请求的转发者,它能够根据相关的请求规则调用对应的服务提供者,它有点像nginx起到了一个代理的作用,使用服务网关可以实现限流、服务鉴权、请求处理、请求参数验证等操作。
在这里插入图片描述

2. 什么是zuul?

zuul是服务网关的实现之一,zuul作为一个边界性质的应用程序,它提供了动态路由、监控、弹性负载和安全功能。Zuul底层利用各种filter实现如下功能:

  • 认证和安全 识别每个需要认证的资源,拒绝不符合要求的请求。
  • 性能监测 在服务边界追踪并统计数据,提供精确的生产视图。
  • 动态路由 根据需要将请求动态路由到后端集群。
  • 压力测试 逐渐增加对集群的流量以了解其性能。
  • 负载卸载 预先为每种类型的请求分配容量,当请求超过容量时自动丢弃。
  • 静态资源处理 直接在边界返回某些响应。

在这里插入图片描述

3. 为什么选择zuul?

zuul提供了许多过滤器对请求进行处理,它能够实现认证安全、动态路由、以及性能监测,zuul的生命周期如下图所示
在这里插入图片描述

4. 如何使用zuul构建APIGetaway?

4.1 创建一个工程,导入相关maven依赖
<dependencies>
     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
     </dependency>
     <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-config</artifactId>
     </dependency>
     <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
     </dependency>
     <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
     </dependency>

     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
     </dependency>
 </dependencies>
4.2 在启动类上添加注解@EnableZullProxy
package com.qingyun.apigetaway;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@SpringBootApplication
@EnableZuulProxy
public class ApiGetawayApplication {

    public static void main(String[] args) {
        SpringApplication.run(ApiGetawayApplication.class, args);
    }

}
4.3 这时我们就可以通过服务名(小写)/uri访问我们的相关资源了在这里插入图片描述
4.4 定制路由名称,将服务名映射成指定名称

要实现路由映射名称定制只需要添加配置信息就好了,如下有三种配置方式

zuul:
  routes:
    orderService: #第一种方式 zuul.服务名.path: /定制化路径/**
      path: /myOrder1/**
    productService: /myProduct/** #第二种方式 直接 zuul.服务名: /定制化路径/**
    hello:
     path: /myHello/**
     serviceId: configService #第三种方式 zuul.随便填.path: /定制化路径/** serviceId: 指定的服务名称

我们开启所有端点查看所有的zuul路由映射

management:
  endpoints:
    web:
      exposure:
        include: "*"

访问/actuator/router
在这里插入图片描述
可以看到里边有我们写的映射,第三种方式没有显示是因为这是我在程序启动之后添加的。

虽然现在实现了路由映射,但是这个配置不够灵活,每次配置的更改都需要进行项目重新启动,不过这个问题也是有解决方案的,那就是通过SpringCloudBus来动态更新配置信息,如果对于动态配置更新不够理解可以看我的另一篇博客(下面部分实现在该博文中可以找到比如服务端):通过SpringCloudBus实现配置更新

5. 使用SpringCloudBus+Zuul实现动态路由

5.1 在工程中引入SpringCloudBus相关maven依赖
<dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-bus-amqp</artifactId>
 </dependency>
5.1 编写相关配置信息
spring:
  cloud:
    config:
      discovery:
        enabled: true #开启配置中心发现
        service-id: config-server #配置中心的名称
      profile: dev
    bus:
      id: ${spring.application.name}:${spring.cloud.config.profile}:${random.value}
  profiles:
    active: dev
5.2 在远程git仓库中添加配置文件,比如apiGetaway-dev.yml
server:
  port: 8002
zuul:
  routes:
    orderService:
      path: /myOrder1/**
      sensitiveHeaders:
    productService: /myProduct/**
spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
5.3 编写一个配置类,用于动态刷新zuul配置
package com.qingyun.apigetaway.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
import org.springframework.context.annotation.Configuration;

/**
 * Created with IntelliJ IDEA.
 * User: 李敷斌.
 * Date: 2020-02-17
 * Time: 19:23
 * Explain: Zuul配置类
 */
@Configuration
public class ZuulConfig {

    //实现动态配置
    @ConfigurationProperties(prefix = "zuul")
    @RefreshScope
    public ZuulProperties zuulProperties(){
        return new ZuulProperties();
    }
}

编写完毕后就可以实现动态路由更新了,只要我们在远程git中修改了配置,本地配置都会实时更新。

6. 解决zuul中cookie无法传递的问题

在zuul中之所以cookie不可以传递是因为zuul将cookie视为敏感头,如下源码所示

/**
	 * List of sensitive headers that are not passed to downstream requests. Defaults to a
	 * "safe" set of headers that commonly contain user credentials. It's OK to remove
	 * those from the list if the downstream service is part of the same system as the
	 * proxy, so they are sharing authentication data. If using a physical URL outside
	 * your own domain, then generally it would be a bad idea to leak user credentials.
	 */
private Set<String> sensitiveHeaders = new LinkedHashSet<>(
		Arrays.asList("Cookie", "Set-Cookie", "Authorization"));

所以我们只需要将sensitiveHeaders设置为空就好了,配置如下所示

zuul:
  routes:
    orderService:
      path: /myOrder1/**
      sensitiveHeaders:

7. 如何实现zuul高可用?

高可用是为了保障我们程序运行的可靠性,因为服务网关用于连接其他服务,要是服务网关都宕机了那么整个程序也就不可用了,也就是出现了我们常说的单点故障。为了解决这个问题我们可以通过nginx映射多个zuul服务网关实例的方式保证程序的可用性。

众所周知,nginx是一个高性能的反向代理、负载均衡服务器,它相对而言是比较可靠的,nginx+zuul的架构图如下所示。
在这里插入图片描述

发布了97 篇原创文章 · 获赞 36 · 访问量 1万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章