聊聊 Node.js RPC(二)— 服务发现

本文涉及的产品
注册配置 MSE Nacos/ZooKeeper,182元/月
任务调度 XXL-JOB 版免费试用,400 元额度,开发版规格
云原生网关 MSE Higress,422元/月
简介: Nodejs 在蚂蚁和阿里已经发展了四、五年时间,从最开始「前端工程师的玩具」,到 Web、BFF 场景的破局,逐步走到线上甚至是一些核心业务,非常不容易。

前言

Nodejs 在蚂蚁和阿里已经发展了四、五年时间,从最开始「前端工程师的玩具」,到 Web、BFF 场景的破局,逐步走到线上甚至是一些核心业务,非常不容易。回头想想 Nodejs 为什么能活下来?依靠的绝不仅仅是:非阻塞I/O、事件驱动、轻量这些官方宣传的特性,我认为更重要一点是我们打通了和 Java 的桥梁,实现了互联互通,这才让它真正融入阿里的技术体系。

伴随蚂蚁 SOFA(Scalable Open Financial Architecture)技术栈的开源,我们也开源了两个 Nodejs RPC 相关模块,希望能填补 Nodejs 社区这块的空白,也将我们几年来在 Nodejs 基础技术的一些经验做个总结和分享。

sofa-bolt-node:蚂蚁通讯协议 Bolt 的 Nodejs 实现

https://github.com/alipay/sofa-bolt-node

sofa-rpc-node:一个通用的 Nodejs RPC 模块

https://github.com/alipay/sofa-rpc-node

上一篇我们介绍了 RPC 通讯协议,它是实现 RPC 的第一步,接下来我们要讨论一下 RPC 的服务发现(Service Discovery)

什么是服务发现?

概念上讲,服务发现就是通过服务唯一标识来获取服务地址的过程,它在 RPC 里扮演了重要角色。下面我用一个点外卖的例子来通俗解释服务发现到底做些什么?它为什么重要?

假设我是一家外卖店的老板,我要考虑的一个问题是:如何让客户能够找到我的店,并且点我的外卖呢?最先想到的是发小广告,客户通过广告里的订餐热线就可以找到我们,这个过程其实就是最简单的服务发现。

这个方案是有效的,但是营运了一段时间后,我发现一些问题:

小广告的传播力有限,投放的精准度也不够,很多人可能随手扔进垃圾桶

客户可能因为丢失卡片或忘记号码而无法下单

一旦留的电话停机了,整个服务不可用

缺货、或者停业还是会接到客户电话

我的生意越来越好,很快开了分店,但是老客户并不知道新店的热线

后面,我听说有一个叫饿了么的点餐平台,抱着试一试态度在上面注册了我的店。没想到这个平台给我带来了大量的订单,而我不再需要到处发小广告,只需要专心做好饭菜、提高服务质量、维护良好的口碑就可以得到稳定的客源。

其次,我也不用担心电话停机、缺货、停业、开新店等服务变更带来的麻烦,我只需要在平台上修改服务信息即可。对于消费者来说他们也不需要收集一大堆外卖卡片,只要安装一个 app,就可以找到丰富的美食、并且可以根据评分选择更加优质的服务。这已经是相当高级的服务发现实现,可以看出无论对于提供者还是消费者,服务发现都是至关重要的。

服务发现的分类

硬负载
硬负载顾名思义是依靠硬件设备做负载,在调用链路上加一个独立部署的硬件设备(一般就是我们所熟知的 F5/LVS/HAproxy 集群),通过它们对后端的服务进行发现,对流量进行负载均衡。

+----------+  invoke   +---------------+        |  Services  |-+
| Consumer | --------> | Load Balancer | -----> |  Providers | |-+
+----------+           +---------------+        +------------+ | |
                                                 |-------------+ |
                                                   +-------------+
  • 优点

存在一个统一的流量集中化节点,可以实现一些全局性的掌控,比如路由、鉴权、安全防控等等

  • 缺点

硬负载设备的成本高,不易维护

在调用主链路上有一定性能损耗

硬负载设备需要实现集群化部署的模式以解决单点故障的问题

软负载
同理,软负载是依靠软件方式进行服务发现和负载均衡,这种方式具有以下特点:

没有了中心化的硬负载设备,把 LB 的功能以 SDK 的模式集成到服务消费方进程里

引入了注册中心(Servcie Registry),用来动态管理所有的服务地址

注册中心不在调用的主链路上,它在旁路

                  +------------------+
                  | Service Registry |
                  +------------------+
                  /                 ^
                 /                   \
             Discover          Register & Keep Alive
               /                         \ 
              /                           \
             v                             \
+----------+                                +----------+
| Consumer | ---- Load Balance & Invoke --> | Provider |
+----------+                                +----------+

优点

Consumer 直接调用 Provider,不再有中间节点

不需独立的负载均衡设备,也就不存在成本和运维的问题

缺点

对 Consumer 端有侵入性,存在接入成本

去中心化,所以弱管控

虽然注册中心在旁路,但也是一个关键的基础设施,需要确保高可用

业界常见的服务发现解决方案
硬负载

阿里云的 SLB

AWS 的 ELB

软负载

Eureka

zookeeper/etcd/consul

阿里和蚂蚁的 ConfigServer

这些方案都各有场景,但在 RPC 里我们通常采用软负载来做服务发现

Node.js 如何做服务发现?

接口抽象
这里主要讨论 Node.js 接入软负载的一些经验和套路。在典型的软负载模式下包含三个角色:

服务提供者(Service Provider)

服务消费者(Service Consumer)

服务注册中心(Service Registry)

Node.js 主要承担前两种角色,所以我们要做的是开发服务注册中心的客户端 SDK。虽然注册中心有多种实现,但我们可以将其接口抽象为:

服务注册

服务注销

服务订阅

服务去订阅

健康检查(可选)

服务治理相关查询(可选)

由此我们可以创建一个 RegistryBase 基类,它的 API 定义如下:

interface RegistryBase {
  async register(config: any): void;

  async unRegister(config: any): void;

  subscribe(config: any, listener: function): void;

  unSubscribe(config: any, listener: function): void;

  async close(): void;
}

针对不同的服务端,会有其对应的实现,比如:ZookeeperRegistry、EurekaRegistry 等等。

实际例子可以参考:ZookeeperRegistry 的实现

https://github.com/alipay/sofa-rpc-node/blob/master/lib/registry/zk/data_client.js

服务发现自己的服务发现
调用注册中心接口本身也需要有一个服务发现的过程,这里感觉有点鸡蛋问题。一般来说这个服务发现我们需要依赖一个更加基础的地址服务(比如:DNS),然后通过轮训或其他策略来更新注册中心的地址列表,最后从中选择一台发起请求,完整的时序图如下:

+--------+               +-----------+                +--------------+
| Client |               |    DNS    |                |   Registry   |
+--------+               +-----------+                +--------------+
    |                          |                              |
    |  -- 1. 查询注册中心地址 --> |                              |
    |  <--- 返回注册中心地址 ---- |                              |
    |                          |                              |
    |                                                         |
    |  ---------------- 2. 注册消费者 / 发布者 ----------------> |   
    |  <-------------------- 注册结果反馈 --------------------- |
    |                                                         |
    |                                                         |
    |  ------------------ 3. 订阅服务发布者 ------------------> |   
    |  <-------------------- 订阅结果反馈 --------------------- |
    |                                                         |
    |                                                         |
    |  <----------------- 4. 推送服务地址 --------------------- |
    |  ----------------------- 反馈收到 ---------------------- |
    |                                                         |

关于健康检查
服务注册中心不同于一般的动态配置系统,因为服务是有状态的(至少包含可用和不可用两种状态)。在服务发布成功以后,还需要持续通过健康检查来确保服务是可用的。

健康检查的方式一般分两种:

1、通过心跳
服务提供方和注册中心通过定时发送心跳包来维护一个长连接,只要长连接不断,就代表服务可用。

优点

对业务透明,实现也比较简单

可以确保至少网络连接是通的

缺点

粒度较粗,无法检查实际业务是否健康

对于注册中心来说需要维护大量长连接

Zookeeper, 阿里的 ConfigServer 都采用这种方式来做健康检查

2、暴露接口用于定时检查
服务提供方单独暴露一个接口给注册中心来轮训,根据接口的返回状态来判断服务是否可用

优点

业务可以自定健康标准,做更精确的健康检查

不用维护长连接

缺点

对业务有一定侵入

K8s 里的 Health Checks 就是这种方式

目录
相关文章
|
3月前
|
JavaScript Unix Linux
nvm与node.js的安装指南
通过以上步骤,你可以在各种操作系统上成功安装NVM和Node.js,从而在不同的项目中灵活切换Node.js版本。这种灵活性对于管理不同项目的环境依赖而言是非常重要的。
819 11
|
8月前
|
弹性计算 JavaScript 前端开发
一键安装!阿里云新功能部署Nodejs环境到ECS竟然如此简单!
Node.js 是一种高效的 JavaScript 运行环境,基于 Chrome V8 引擎,支持在服务器端运行 JavaScript 代码。本文介绍如何在阿里云上一键部署 Node.js 环境,无需繁琐配置,轻松上手。前提条件包括 ECS 实例运行中且操作系统为 CentOS、Ubuntu 等。功能特点为一键安装和稳定性好,支持常用 LTS 版本。安装步骤简单:登录阿里云控制台,选择扩展程序管理页面,安装 Node.js 扩展,选择实例和版本,等待创建完成并验证安装成功。通过阿里云的公共扩展,初学者和经验丰富的开发者都能快速进入开发状态,开启高效开发之旅。
|
7月前
|
资源调度 JavaScript 前端开发
前端开发必备!Node.js 18.x LTS保姆级安装教程(附国内镜像源配置)
本文详细介绍了Node.js的安装与配置流程,涵盖环境准备、版本选择(推荐LTS版v18.x)、安装步骤(路径设置、组件选择)、环境验证(命令测试、镜像加速)及常见问题解决方法。同时推荐开发工具链,如VS Code、Yarn等,并提供常用全局包安装指南,帮助开发者快速搭建高效稳定的JavaScript开发环境。内容基于官方正版软件,确保合规性与安全性。
5930 24
|
8月前
|
JavaScript 前端开发 数据可视化
【01】Cocos游戏开发引擎从0开发一款游戏-cocos环境搭建以及配置-Cocos Creator软件系统下载安装-node环境-优雅草卓伊凡
【01】Cocos游戏开发引擎从0开发一款游戏-cocos环境搭建以及配置-Cocos Creator软件系统下载安装-node环境-优雅草卓伊凡
440 2
【01】Cocos游戏开发引擎从0开发一款游戏-cocos环境搭建以及配置-Cocos Creator软件系统下载安装-node环境-优雅草卓伊凡
|
8月前
|
弹性计算 JavaScript 前端开发
一键安装!阿里云新功能部署Nodejs环境到ECS竟然如此简单!
一键安装!阿里云新功能部署Nodejs环境到ECS竟然如此简单!
一键安装!阿里云新功能部署Nodejs环境到ECS竟然如此简单!
|
7月前
|
数据库
【YashanDB知识库】安装共享集群时报错:YAS-05721 invalid input parameter, reason: node name invalid
【YashanDB知识库】安装共享集群时报错:YAS-05721 invalid input parameter, reason: node name invalid
|
11月前
|
存储 JavaScript 搜索推荐
Node框架的安装和配置方法
安装 Node 框架是进行 Node 开发的第一步,通过正确的安装和配置,可以为后续的开发工作提供良好的基础。在安装过程中,需要仔细阅读相关文档和提示,遇到问题及时解决,以确保安装顺利完成。
585 58
|
9月前
|
JavaScript
nodejs安装之npm ERR! code CERT_HAS_EXPIREDnpm ERR! errno CERT_HAS_EXPIRED reason: certificate has expired-证书错误通用问题解决方案-优雅草央千澈
nodejs安装之npm ERR! code CERT_HAS_EXPIREDnpm ERR! errno CERT_HAS_EXPIRED reason: certificate has expired-证书错误通用问题解决方案-优雅草央千澈
1394 27
|
11月前
|
Web App开发 JavaScript 前端开发
2024年5月node.js安装(winmac系统)保姆级教程
本篇博客为2024年5月版Node.js安装教程,适用于Windows和Mac系统。作者是一名熟悉JavaScript与Vue的大一学生,分享了Node.js的基本介绍、下载链接及简单安装步骤。安装完成后,通过终端命令`node -v`验证版本即可确认安装成功。欢迎关注作者,获取更多技术文章。
342 2
2024年5月node.js安装(winmac系统)保姆级教程