Java必知必会系列:微服务治理与网关

作者:禅与计算机程序设计艺术

1.简介

随着互联网的蓬勃发展、应用的日益复杂化、用户数量的不断增加,单体架构已经越来越难以满足需求了。面对如此庞大的系统,如何才能让它变得更加可靠、安全、可伸缩?如何通过一种“多点”架构,让各个服务相互独立而又协同工作?在这种情况下,微服务架构应运而生。微服务架构的出现,给开发者提供了很多便利。比如一个功能模块可以作为一个独立的服务部署到集群中;也可以按需扩容,提高系统的处理能力;还可以根据业务情况灵活调整服务之间的通信方式,实现资源的共享和分配;还有就是不同微服务之间需要松耦合、隔离、安全等方面的考虑。因此,在实际应用中,微服务架构也经历过各种形式的改进和优化,而其治理机制,则成为企业级微服务架构不可或缺的一环。其中最重要的一环就是网关。所谓网关,简单来说就是一个专门用于承接请求并将请求转发至后台微服务集群的服务。网关的作用主要有以下几方面:

  1. 身份认证与鉴权:网关可以提供身份认证、授权、限流、熔断等功能,使得微服务集群内部的服务只对合法的请求进行响应,避免非法请求导致的负载过高或者服务雪崩效应。同时,网关还可以通过不同协议(HTTP/HTTPS、gRPC)、不同入口域名、不同请求头等信息,选择性地将请求路由至不同的微服务集群,实现微服务集群之间的透明通信。
  2. 服务发现与负载均衡:由于微服务集群可能分布在不同的服务器上,网关需要能够感知到这些服务的存在,并且能够按照一定策略将请求分发至对应的微服务节点。当某些微服务节点故障时,网关可以自动将相应的请求转发至其他正常的节点,从而保证整体服务的可用性。
  3. 请求协议转换:网关可以根据微服务集群的内部协议进行请求转换,比如将HTTP协议的请求转换成Dubbo协议,从而允许不同语言的客户端与微服务集群进行通信。
  4. API网关:由于微服务架构的服务无状态、无共享,因此API网关的核心任务就是将API请求转发至具体的微服务上执行。这样做的好处是降低了微服务集群内部的耦合性,简化了微服务架构中的调用逻辑,并提升了API的一致性。
  5. 流量控制与防护:网关除了具备身份认证、鉴权、服务发现、负载均衡等功能外,还可以进行流量控制、数据缓存、限流、熔断、监控等功能,帮助微服务集群管理者保障微服务集群的稳定运行。
  6. 其它功能扩展:除了上面提到的功能外,网关还可以进行灰度发布、AB测试、跨域访问控制等功能,满足更多的业务场景。 本文将通过浅显易懂的语言和示例,向读者介绍什么是微服务架构,微服务架构中存在哪些问题以及如何解决它们,为什么需要网关以及网关的作用,以及如何基于Spring Cloud Gateway构建一个简单的网关。最后,本文也会分享一些网关相关的常见问题和解答,希望能够对读者有所帮助。

    2.微服务架构概述

    2.1 微服务架构简介

    微服务架构(Microservices Architecture),也被称作面向服务的架构(SOA)、面向服务架构(Service-Oriented Architecture),是一种应用架构模式。它提倡将单一应用程序划分成一组小型服务,每个服务负责单一的功能领域,服务间采用轻量级通信机制互通。一个微服务架构下的软件通常由多个小型服务组成,每个服务运行在自己的进程中,进程之间通过轻量级通信协议互相沟通。每个服务都足够简单,只有自己的数据存储、自己的业务逻辑,并保持独立的开发水平,因此单个服务的修改不会影响到其他服务,系统中每个服务的代码库也是相互独立的。

微服务架构的特点包括:

  1. 组件化:微服务架构下每个服务都是可以独立部署的,具有很强的弹性、适应性和可扩展性,在某些场景下甚至可以重用已有的服务。例如,可以把两个相同的服务部署在两个不同的容器中,让它们共用某些基础设施资源,实现资源共享和分配。
  2. 松耦合:微服务架构下服务间互相独立,消息机制采用轻量级通信协议,可以有效地解耦服务。
  3. 容错性:一个失败的服务只影响该服务的某个实例,不会影响整个系统。
  4. 可伸缩性:单个服务的性能瓶颈可以在水平方向上通过增加机器来解决,而垂直方向上的服务拆分需要调整服务之间的关系,比如引入消息队列来削峰填谷。
  5. 统一部署:所有的服务都可以通过统一的脚本部署到测试环境、预生产环境、生产环境。

2.2 微服务架构存在的问题

但是,如果仅依靠微服务架构无法彻底解决所有问题。由于微服务架构没有统一的服务注册中心,因此服务之间无法直接通信,只能通过网关(Gateway)来实现服务间的通信,而网关的另一个作用就是作为流量控制、熔断器、负载均衡器、权限验证等的角色。下面我们看一下微服务架构存在的几个问题。

2.2.1 单点失效

单体架构下,如果某个服务出故障,整个系统就会失效。为了保证系统的高可用性,微服务架构往往会使用集群部署多个服务,即使某个服务出现问题,也只影响该服务的某个实例。为了提高可用性,微服务架构通常会设置多个服务副本,但单点失效仍然是一个隐患。

2.2.2 数据一致性

微服务架构下,服务的分布式特性会导致数据不一致的问题。由于不同服务之间可能存在数据同步问题,例如两个服务分别插入一条记录,但由于网络延迟或其他原因,两条记录的插入顺序可能不一样。为了保证数据的一致性,微服务架构往往会使用事件发布/订阅(Event Publishing/Subscribing)模式,在服务间传递数据变更通知。

2.2.3 性能瓶颈

虽然微服务架构可以有效地解决单点失效、数据一致性等问题,但它依然存在一些性能瓶颈。例如,由于每个服务都是独立部署的,因此它占用的内存空间较大。另外,如果某个服务出现性能问题,可能会导致整个系统的整体性能下降。

2.2.4 新技术适配

对于刚刚接触微服务架构的人来说,最让人头疼的是要适配新技术。每个服务都应该尽可能地依赖于最小化外部依赖,保证最大的内聚性,避免因为引入新的技术而牵一发动全身。

2.3 微服务架构解决方案——网关

为了解决微服务架构存在的以上问题,就有必要引入网关(Gateway)这一架构模式。网关的主要职责就是作为调度者,接收客户端的请求,并将请求转发至后端的微服务集群。

为什么要引入网关呢?假设有一个微服务架构,其中有三个服务A、B、C,每个服务部署在不同服务器上,客户端通过网关访问微服务集群。如果没有网关,服务A发送了一个请求,需要经过三次网络传输才能到达服务C,如下图所示:

客户端要发送请求至服务A、B、C,需要经过三次网络传输。那么如果服务A出现故障,那么整个请求就会超时。为了提高系统的可用性,客户端需要对失败的服务重新进行请求,直到成功。如此一来,客户端需要维护很多状态,不仅需要管理服务A的请求,还需要管理服务B和服务C的请求,并且需要在多台服务器上部署客户端。网关就像是一个集中式的请求入口,它可以屏蔽掉微服务集群,仅保留客户端的请求,减少了客户端的状态管理负担,提高了系统的吞吐率。如下图所示:

由于微服务架构没有统一的服务注册中心,因此服务A、B、C并不能直接通信,需要通过网关来实现服务间的通信。客户端向网关发送请求,网关再将请求转发至相应的微服务集群。对于客户端来说,不需要管理多个服务集群,只需要管理一个网关就可以了。

2.4 Spring Cloud Gateway介绍

Spring Cloud Gateway 是 Spring Cloud 的一个子项目,它是基于 Spring Framework 之上构建的网关框架。基于 Spring WebFlux 和 Project Reactor 提供的非阻塞异步特性,Spring Cloud Gateway 可以支撑高性能的路由、过滤及流量管理。

Spring Cloud Gateway 作为 Spring Cloud 的网关模块,具有以下优势:

  1. 使用简单:Spring Cloud Gateway 基于 Spring Boot Starter 及 Spring WebFlux ,可以使用简单、灵活的方式来搭建自定义的 API GateWay 。它支持众多的路由 Predicate 及 Filter Handler ,同时提供了额外的 Gateway 整合模式如 Zuul 、Apigee 等,用户可以自由选择。
  2. 高性能:Spring Cloud Gateway 使用 Netty 框架作为网络通信引擎,充分利用多核 CPU 及异步 IO,提高处理能力和请求响应速度。
  3. 动态路由:Spring Cloud Gateway 提供动态路由 Predicate 及 Filter Handler ,允许用户通过编写代码来配置路由规则,灵活的匹配和修改请求参数。
  4. 插件支持:Spring Cloud Gateway 支持插件化开发模型,可以方便的集成 Zuul 插件及自定义插件,实现功能扩展及自定义配置。
  5. 集成 Spring Security:Spring Cloud Gateway 集成了 Spring Security 安全框架,可以对微服务集群的请求进行安全保护,包括认证、授权、熔断、限流等。
  6. 开放接口:Spring Cloud Gateway 除了作为服务网关外,还提供了完整的 RESTful API 接口定义规范,允许第三方系统集成到 API 网关中,实现开放接口能力。

2.5 Spring Cloud Gateway 基本使用

下面我们通过一个简单实例来演示 Spring Cloud Gateway 的基本使用。首先,创建一个 Spring Cloud 工程,并添加 Spring Cloud Gateway 模块:

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

然后,在启动类上添加 @EnableGateway 注解开启网关:

@SpringBootApplication
@EnableDiscoveryClient // Spring Eureka Discovery Client enables discovery of services in a specific zone
@EnableCircuitBreaker // Hystrix Circuit Breaker to prevent cascading failures and enable fallback
public class GatewayApplication {

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

    @Bean
    public RouteLocator routeLocator(RouteLocatorBuilder builder) {
        return builder.routes()
           .route(r -> r
               .path("/api/**")
               .uri("http://localhost:8080"))
           .build();
    }

}

以上,我们配置了一个路由规则,将 /api/** 路径下的请求转发至 http://localhost:8080。接着,启动 Spring Cloud 应用,启动成功之后,打开浏览器输入 http://localhost:8080,即可看到 Hello World! 输出。

到这里,我们已经成功启动了一个 Spring Cloud Gateway 实例,并将请求转发至一个微服务集群。

猜你喜欢

转载自blog.csdn.net/universsky2015/article/details/133446433