微服务6:通信之网关

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
云原生网关 MSE Higress,422元/月
注册配置 MSE Nacos/ZooKeeper,118元/月
简介: 微服务6:通信之网关

1 概述

回顾下前面几篇关于微服务的介绍,我们可以了解到从当单体系统到微服务,再到服务网格的演进过程。那单体系统和微服务相比,有哪些区别呢,下面是对功能性的对比?

单体系统

微服务系统

程序、数据、配置集中管理

按照功能拆分、微服务化、松耦合

开发效率低下

分模块快速迭代

发布全量,启动慢

平滑发布,快速启动

可靠性差

熔断、限流、降级,超时重试,异常离群

服务内直接调用

轻量级通信

技术单一

跨语言

微服务有诸多的有利条件,但是如果微服务的粒度比较细(按照业务功能拆分),则他们之间服务调用就会比较复杂,链路会比较长。

 

image.png

比如上图中,我们按照职能将服务进行了拆分,这时候从不同的客户端(如Web、App、3rd)访问,就有可能访问不同的服务。而服务与服务之间又有上下游的协作,调用就变得错综复杂。

因此,在微服务架构体系下,服务间的通讯就显得非常重要。

你可能需要关注很多问题,包括不同的技术栈不同的开发语言之间的上下游交互,服务之间的注册与发现,请求认证,接入授权。

下游对上游进行调用的时候,上游怎么做负载均衡、故障注入、超时重复、熔断、降级、限流、ABTesting等,端到端之间如何实现监控和trace,这些都是微服务体系下需要去思考的问题。

要解决上面这些问题,微服务通信可以从三个方面进行讨论

细化服务颗粒:按照功能拆分、微服务化、松耦合

分模块快速迭代:可以将应用程序拆分为核心和非核心模块。非核心模块出现问题的时候,核心模块不会受到影响。

参考这篇《微服务3:微服务拆分策略

流量管理:金丝雀发布,ABTesting

实现服务的高可用治理:熔断、限流、降级,超时重试,异常离群

轻量级通信,使用 RESTful API 或者 RPC 进行接口访问

跨语言,语言有特定的应用场景,比如go和Java、c++适合不同的业务方向,开发语言不同,但是遵循同一套标准,

使用轻量级的API进行通信,实现服务语言上的解耦。

2 服务之间的通信方式

而微服务的通信,是在服务之间增加一个间接的中间层来完成服务间的通信过程。目前微服务的通信方式有以下三种:

1、基于网关的通信

2、基于RPC的通信

3、基于ServiceMesh的数据面(SideCar)的通信

接下来逐一介绍这三种通信方式的具体实现,本文先介绍基于网关的通信方式。

2.1 基于网关的通信

我们先看看,在没有网关的情况下,服务是怎么通信的?

 

image.png

如上图有3个客户端,在调用4个服务的接口。这种直连调用的方式有很多问题:客户端需要保存所有服务的地址,同时也需要实现一些系统级的容错策略。

比如负载均衡、超时重试、服务熔断等,非常复杂,并且难以维护。因为是在各客户端保存的服务地址,一旦某个服务端出现问题或者发生迁移,所有的客户端都需要修改并且升级。

另外如果再增加一个E svc,所有的客户端也需要升级。而且在某些场景下存在跨域请求的问题,每个服务都需要实现独立的身份和权限认证等等。

这些问题导致 服务间的通信过于复杂,对于开发和维护都不优化。

如果我们在客户端和服务端增加一层网关,所有请求都经过网关转发到对应的下游服务,客户端只需要保存网关的地址并且只和网关进行交互,这样就大大简化了客户端的开发。

 

image.png

如果需要访问用户服务,只需要构造右边这个请求发给网关,然后由网关将请求转发给对应的下游服务。

可以将网关简单理解为:路由转发+治理策略,治理策略是指和业务无关的一些通用策略,包括:负载均衡,安全认证,身份验证,系统容错等等

网关作为一个 API 架构层,用来保护、增强和控制对服务的访问。

2.1.1 网关的主要功能

请求接入

1、为各种应用提供统一的服务接入

2、管理所有的接入请求:提供流量分流、代理转发、延迟、故障注入等能力

安全防护

用户认证、权限校验、黑白名单、请求过滤、防web攻击

治理策略

负载均衡、接口限流、超时重试、服务熔断、灰度发布、协议适配、流量监控、日志统计等

统一管理

1、提供配置管理工具

2、对所有服务进行统一管理

3、对中介策略进行统一管理

2.1.2 网关使用场景

蓝绿部署

 

image.png

我们前面看到,在单体应用中,部署是一件比较麻烦的事情,每次的改动,都需要把整个应用程序都发布启动一次。而且系统规模越大,部署过程越复杂,时间越长。

而在微服务架构中,模块部署起来相对更快,更容易。你可以在短时间内对于同一个模块做多次部署,网关可以帮你实现蓝绿部署。

如图所示之前的用户服务版本是V1.0,然后部署V1.1版本,在网关上只需要做一个转发配置的修改,就可以迅速的将所有流量都流到新版本。

灰度发布

 

image.png

类似金丝雀的理念,你对一次性升级版本感到担忧,可以先配置5%的流量达到新版本,让部分人试用一下,等线上观察一段时间后,可以逐步增加对新版本的流量百分比,最终实现百分之百切流。

负载均衡

 

image.png

此能力需要依赖服务注册和服务发现。

服务熔断

image.png

网关还可以实现断路器的功能;如果某个下游忽然返回了大量错误,原因有可能是服务挂了或者网络问题或者服务器负载太高,如果此时继续给这个问题服务转发流量就可能会产生级联故障。

出问题的服务有可能产生雪崩,雪崩会沿着调用链向上传递,导致整个服务链都崩溃。

断路器可以停止向问题模块转发流量,在业务层面可以给用户返回一个服务降级之后的页面,开发人员就有相对充分的时间来定位和解决问题。

2.1.3 开源网关

image.png

目前常见的开源网关按照语言大概分为上图的五种,如果按照使用数量和成熟度来划分的话,主流有4个,分别是 OpenResty、Kong、Zull和Spring Cloud。

其中 Zull 和Spring Cloud 是用java 实现,前两种是用Nginx+Lua实现的,其中,OpenResty 是一个基于Nginx+Lua实现的一个高性能web 平台,它集成了大量的第三方模块和lua库,用于方便的搭建高性能扩展性强的web 应用服务或者网关,

Kong 是一个基于OpenResty实现的一个高性能可扩展的API网关。从性能上来说:Kong的性能是最好的,其次分别是OpenResty、Spring Cloud 和Zuul。

2.1.4 Nginx介绍

大家熟悉的Nginx是用C语言实现的一个开源、跨平台、高性能的HTTP和反向代理Web服务器,具有高度模块化、扩展性强、轻量级、资源消耗少、高并发、高性能等特点。

Nginx进程模型

 

image.png

 

Nginx是一个多进程模型,包含一个master 进程和多个worker 进程。

master 进程主要负责接收外部信号,向各个worker 进程发送信号,监控worker 进程的状态。当worker 进程异常退出后,服务不会中断的。master 进程会迅速拉起新的worker 进程来工作。基本的网络事件比如读写,都是在worker 进程来实现。

多个worker 进程是相互独立的,他们共同竞争来自客户端的请求,一个请求只能在一个worker 中进行处理。

Nginx网络模型

image.png

首先,master 进程会listen socket,然后再fork出多个worker 进程,每个worker 进程都可以去accept 这个socket。

Nginx 提供了一把共享accept mutex锁来保证只有一个worker 进程可以把这个请求accept 成功。当这个worker 进程accept 连接成功之后,就可以进行请求的解析读取。

大概数据流:master 先 fork 多个worker 进程,然后当有client 来的时候,client 会连接到一个worker 进程里面,发送消息request。worker 进程再去读取、解析并处理,最终把response 返回给客户端。

那么大家可以想一下这个问题,Nginx 采用了一个多worker 的方式来处理请求,每个worker 里面其实是只有一个主线程,那么它是怎么实现高并发的呢?

答案是采用异步非阻塞的方式;什么是异步非阻塞?

举个例子,当worker 收到一个来自client request 时,就会有一个worker 进程去处理它。但这个worker 进程并不是全程处理,worker 会处理到请求可能会发生阻塞的地方。比如它向后端服务器转发的这个request,并等待请求的返回,

worker 进程不会同步的等待,而是注册一个事件,如果下游返回了,再继续处理这个事件。如果有新的请求再进来,它就可以很快按照这种方式再进行处理。这其实就是非阻塞和IO多路复用。

一旦服务端返回了,就会触发worker 刚才注册的回调事件,worker 才会继续接手这个request。  

2.2 Zuul实战

刚才前面已经说过,网关是客户端和服务器之间的中间层,作为系统唯一对外的入口,能够处理流量治理、安全访问等工作。

功能类型

功能说明

统一接入

智能路由

AB测试、灰度测试

负载均衡、容灾处理

日志埋点(类似Nignx日志)

流量监控

限流处理

服务降级

安全防护

鉴权处理

监控 

 机器网络隔离

 

业内主要的网关有如下几种:1、zuul:是Netflix开源的微服务网关,可以和Eureka,Ribbon,Hystrix等组件配合使用,Zuul提供了动态路由、监控、弹性负载和安全功能。

2、kong: 由Mashape公司开源的,基于OpenResty(Nginx+Lua)的 API gateway。

3、Nginx + Lua:高性能的HTTP和反向代理服务器,Lua作为脚本语言,为Nginx提供执行程序,可以高并发、非阻塞的处理各种请求

下面我们以Zuul为案例,来测试下网关的使用。

2.2.1 配置路由规则

新建一个spring-clouid项目,导入Maven 依赖:

image.png

1  <!-- eureka client -->  2         <dependency>  3             <groupId>org.springframework.cloud</groupId>  4             <artifactId>spring-cloud-netflix-eureka-server</artifactId>  5         </dependency>  6         <!-- zuul网关 -->  7         <dependency>  8             <groupId>org.springframework.cloud</groupId>  9             <artifactId>spring-cloud-starter-netflix-zuul</artifactId> 10             <version>2.2.10.RELEASE</version> 11         </dependency>

image.png

配置yaml文件:

image.png

1 server:  2   port: 1002  3 spring:  4   application:  5     name: zuul-proxy # 服务的名称  6 eureka:  7   instance:  8     hostname: localhost  9   client: 10     service-url:  # 这边就保证了注册到 eureka-service 这个注册中心去 11       defaultZone: http://localhost:1000/eureka/ 12  13 #自定义路由映射 14 zuul: 15   routes: #路由规则 16     key-v1:  #自定义key 17       path: /proxy/**   # 匹配路径,/proxy/ 会路由到 zuul-proxy服务 18       serviceId: zuul-proxy 19       url: http://${eureka.instance.hostname}:${server.port}/zuulservice/api/v1.0/  # 只要路径匹配,就转到这个服务对应路径下

image.png

Application中启动网关代理:

image.png

1 @SpringBootApplication 2 @EnableZuulProxy // 开启网关代理 3 public class ZuulGatewayApplication { 4     public static void main(String[] args) { 5         SpringApplication.run(ZuulGatewayApplication.class, args); 6         System.out.println("start zuulgateway!"); 7     } 8 }

image.png

接口实现:

image.png

1 /**  2  * @author brand  3  * @Description:  4  * @Copyright: Copyright (c) 2021  5  * @Company: Helenlyn, Inc. All Rights Reserved.  6  * @date 2021/12/5 12:30 下午  7  * @Update Time:  8  * @Updater:  9  * @Update Comments: 10  */ 11 @Controller 12 @RequestMapping("/zuulservice/api/v1.0") 13 public class ZuulServiceController { 14  15     /** 16      * 获取注册服务信息 17      */ 18     @RequestMapping(value = "/serviceinfo", method = {RequestMethod.GET}) 19     @ResponseBody 20     public String getServiceInfo() { 21         return  "serviceinfo:v1.0,instance 1";    

image.png

 

查看效果,proxy路由成功了:

image.png

 

 

image.png

2.2.2 测试负载均衡

我们在添加一个端口为1003的服务,跟端口为1002做zuul-proxy服务做负载均衡,这时候先修改 zuul-proxy 的yaml配置。

image.png

1 # 自定义路由映射  2 zuul:  3   routes: # 路由规则  4     key-v1:  # 自定义key  5       path: /proxy/**   # 匹配路径,/proxy/ 会路由到 zuul-proxy服务  6       serviceId: zuul-proxy  7 ribbon:  8   eureka:  9     enabled: true # 允许Ribbon使用Eureka 10 zuul-proxy: 11   ribbon: 12     listOfServers: localhost:1002,localhost:1003 # 这边需要建立两个服务 1002,1003,在这两个服务间做负载均衡

image.png

创建一个module,命名zuul-client,增加注册依赖

1         <!-- eureka client --> 2         <dependency> 3             <groupId>org.springframework.cloud</groupId> 4             <artifactId>spring-cloud-netflix-eureka-server</artifactId> 5         </dependency>

配置zuul-client的yaml文件:

image.png

1 server: 2   port: 1003 # 这边注意,端口为1003,跟上面对应起来了 3 spring: 4   application: 5     name: zuul-client # 服务的名称 6 eureka: 7   client: 8     service-url:  # 这边就保证了注册到 eureka-service 这个注册中心去 9       defaultZone: http://localhost:1000/eureka/

image.png

补充一个接口,注意返回的信息不一样:

image.png

1 /**  2  * @author brand  3  * @Description:  4  * @Copyright: Copyright (c) 2021  5  * @Company:Helenlyn, Inc. All Rights Reserved.  6  * @date 2021/12/5 3:52 下午  7  * @Update Time:  8  * @Updater:  9  * @Update Comments: 10  */ 11 @Controller 12 @RequestMapping("/zuulservice/api/v1.0") 13 public class ZuulServiceController { 14     /** 15      * 获取注册服务信息 16      */ 17     @RequestMapping(value = "/serviceinfo", method = {RequestMethod.GET}) 18     @ResponseBody 19     public String getServiceInfo() { 20         return  "serviceinfo:v1.0,instance 2"; 21     } 22 }

image.png

网关 zuul-proxy 和 服务zuul-client都启动起来,可以看到如下的效果:

image.png

 

image.png

 

 

image.png

相关实践学习
SLB负载均衡实践
本场景通过使用阿里云负载均衡 SLB 以及对负载均衡 SLB 后端服务器 ECS 的权重进行修改,快速解决服务器响应速度慢的问题
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
相关文章
|
2月前
|
Cloud Native API
微服务引擎 MSE 及云原生 API 网关 2024 年 9 月产品动态
微服务引擎 MSE 及云原生 API 网关 2024 年 9 月产品动态。
|
2月前
|
Dubbo Java 应用服务中间件
Spring Cloud Dubbo:微服务通信的高效解决方案
【10月更文挑战第15天】随着信息技术的发展,微服务架构成为企业应用开发的主流。Spring Cloud Dubbo结合了Dubbo的高性能RPC和Spring Cloud的生态系统,提供高效、稳定的微服务通信解决方案。它支持多种通信协议,具备服务注册与发现、负载均衡及容错机制,简化了服务调用的复杂性,使开发者能更专注于业务逻辑的实现。
74 2
|
2月前
|
缓存 监控 API
探索微服务架构中的API网关模式
【10月更文挑战第5天】随着微服务架构的兴起,企业纷纷采用这一模式构建复杂应用。在这种架构下,应用被拆分成若干小型、独立的服务,每个服务围绕特定业务功能构建并通过HTTP协议协作。随着服务数量增加,统一管理这些服务间的交互变得至关重要。API网关作为微服务架构的关键组件,承担起路由请求、聚合数据、处理认证与授权等功能。本文通过一个在线零售平台的具体案例,探讨API网关的优势及其实现细节,展示其在简化客户端集成、提升安全性和性能方面的关键作用。
77 2
|
2月前
|
存储 缓存 监控
探索微服务架构中的API网关模式
【10月更文挑战第1天】探索微服务架构中的API网关模式
98 2
|
6天前
|
NoSQL 前端开发 测试技术
👀探秘微服务:从零开启网关 SSO 服务搭建之旅
单点登录(Single Sign-On,简称SSO)是一种认证机制,它允许用户只需一次登录就可以访问多个应用程序或系统。本文结合网关和SaToken快速搭建可用的Session管理服务。
37 8
|
14天前
|
Cloud Native API 微服务
微服务引擎 MSE 及云原生 API 网关 2024 年 11 月产品动态
微服务引擎 MSE 及云原生 API 网关 2024 年 11 月产品动态。
|
16天前
|
运维 Cloud Native 应用服务中间件
阿里云微服务引擎 MSE 及 云原生 API 网关 2024 年 11 月产品动态
阿里云微服务引擎 MSE 面向业界主流开源微服务项目, 提供注册配置中心和分布式协调(原生支持 Nacos/ZooKeeper/Eureka )、云原生网关(原生支持Higress/Nginx/Envoy,遵循Ingress标准)、微服务治理(原生支持 Spring Cloud/Dubbo/Sentinel,遵循 OpenSergo 服务治理规范)能力。API 网关 (API Gateway),提供 APl 托管服务,覆盖设计、开发、测试、发布、售卖、运维监测、安全管控、下线等 API 生命周期阶段。帮助您快速构建以 API 为核心的系统架构.满足新技术引入、系统集成、业务中台等诸多场景需要
|
21天前
|
设计模式 负载均衡 监控
探索微服务架构下的API网关设计
在微服务的大潮中,API网关如同一座桥梁,连接着服务的提供者与消费者。本文将深入探讨API网关的核心功能、设计原则及实现策略,旨在为读者揭示如何构建一个高效、可靠的API网关。通过分析API网关在微服务架构中的作用和挑战,我们将了解到,一个优秀的API网关不仅要处理服务路由、负载均衡、认证授权等基础问题,还需考虑如何提升系统的可扩展性、安全性和可维护性。文章最后将提供实用的代码示例,帮助读者更好地理解和应用API网关的设计概念。
49 8
|
1月前
|
负载均衡 监控 API
dotnet微服务之API网关Ocelot
Ocelot 是一个基于 .NET 的 API 网关,适用于微服务架构。本文介绍了如何创建一个 Web API 项目并使用 Ocelot 进行 API 请求路由、负载均衡等。通过配置 `ocelot.json` 和修改 `Program.cs`,实现对 `GoodApi` 和 `OrderApi` 两个项目的路由管理。最终,通过访问 `https://localhost:7122/good/Hello` 和 `https://localhost:7122/order/Hello` 验证配置成功。
32 1
dotnet微服务之API网关Ocelot
|
1月前
|
缓存 负载均衡 JavaScript
探索微服务架构下的API网关模式
【10月更文挑战第37天】在微服务架构的海洋中,API网关犹如一座灯塔,指引着服务的航向。它不仅是客户端请求的集散地,更是后端微服务的守门人。本文将深入探讨API网关的设计哲学、核心功能以及它在微服务生态中扮演的角色,同时通过实际代码示例,揭示如何实现一个高效、可靠的API网关。