当前位置: 首页 > article >正文

Node.js系列(4)--微服务架构实践

Node.js微服务架构实践 🔄

引言

微服务架构已成为构建大规模Node.js应用的主流选择。本文将深入探讨Node.js微服务架构的设计与实现,包括服务拆分、服务治理、通信机制等方面,帮助开发者构建可扩展的微服务系统。

微服务架构概述

Node.js微服务架构主要包括以下方面:

  • 服务拆分:业务领域划分与服务边界
  • 服务治理:服务注册、发现与负载均衡
  • 通信机制:同步与异步通信方案
  • 数据管理:分布式事务与数据一致性
  • 可观测性:监控、日志与链路追踪

微服务架构实现

服务注册中心

// 服务注册中心
class ServiceRegistry {private static instance: ServiceRegistry;private services: Map<string, ServiceInfo[]>;private config: RegistryConfig;private healthChecker: HealthChecker;private constructor() {this.services = new Map();this.config = {checkInterval: 10000,timeoutThreshold: 30000};this.healthChecker = new HealthChecker(this.config);}// 获取单例实例static getInstance(): ServiceRegistry {if (!ServiceRegistry.instance) {ServiceRegistry.instance = new ServiceRegistry();}return ServiceRegistry.instance;}// 注册服务registerService(serviceInfo: ServiceInfo): void {const { name, version } = serviceInfo;const key = `${name}@${version}`;if (!this.services.has(key)) {this.services.set(key, []);}this.services.get(key)!.push(serviceInfo);console.log(`Service registered: ${key}`);// 启动健康检查this.healthChecker.addService(serviceInfo);}// 注销服务deregisterService(serviceInfo: ServiceInfo): void {const { name, version } = serviceInfo;const key = `${name}@${version}`;const services = this.services.get(key);if (services) {const index = services.findIndex(s => s.instanceId === serviceInfo.instanceId);if (index !== -1) {services.splice(index, 1);console.log(`Service deregistered: ${key}`);// 停止健康检查this.healthChecker.removeService(serviceInfo);}}}// 发现服务discoverService(name: string, version: string): ServiceInfo[] {const key = `${name}@${version}`;return this.services.get(key) || [];}// 更新服务状态updateServiceStatus(serviceInfo: ServiceInfo,status: ServiceStatus): void {const { name, version } = serviceInfo;const key = `${name}@${version}`;const services = this.services.get(key);if (services) {const service = services.find(s => s.instanceId === serviceInfo.instanceId);if (service) {service.status = status;service.lastUpdateTime = Date.now();}}}// 获取所有服务getAllServices(): Map<string, ServiceInfo[]> {return this.services;}
}// 健康检查器
class HealthChecker {private config: RegistryConfig;private checkTimer: NodeJS.Timeout | null;private services: Set<ServiceInfo>;constructor(config: RegistryConfig) {this.config = config;this.checkTimer = null;this.services = new Set();}// 添加服务addService(serviceInfo: ServiceInfo): void {this.services.add(serviceInfo);if (!this.checkTimer) {this.startHealthCheck();}}// 移除服务removeService(serviceInfo: ServiceInfo): void {this.services.delete(serviceInfo);if (this.services.size === 0 && this.checkTimer) {this.stopHealthCheck();}}// 启动健康检查private startHealthCheck(): void {this.checkTimer = setInterval(() => {this.checkServices();}, this.config.checkInterval);}// 停止健康检查private stopHealthCheck(): void {if (this.checkTimer) {clearInterval(this.checkTimer);this.checkTimer = null;}}// 检查服务健康状态private async checkServices(): Promise<void> {const registry = ServiceRegistry.getInstance();for (const service of this.services) {try {const status = await this.checkServiceHealth(service);registry.updateServiceStatus(service, status);} catch (error) {console.error(`Health check failed for service ${service.name}:`,error);registry.updateServiceStatus(service, 'unhealthy');}}}// 检查单个服务健康状态private async checkServiceHealth(service: ServiceInfo): Promise<ServiceStatus> {try {const response = await fetch(`${service.baseUrl}/health`,{timeout: this.config.timeoutThreshold});return response.ok ? 'healthy' : 'unhealthy';} catch (error) {return 'unhealthy';}}
}// 服务发现客户端
class ServiceDiscoveryClient {private registry: ServiceRegistry;private loadBalancer: LoadBalancer;constructor() {this.registry = ServiceRegistry.getInstance();this.loadBalancer = new LoadBalancer();}// 获取服务实例async getServiceInstance(name: string,version: string): Promise<ServiceInfo | null> {const services = this.registry.discoverService(name, version);// 过滤健康实例const healthyServices = services.filter(s => s.status === 'healthy');if (healthyServices.length === 0) {return null;}// 使用负载均衡选择实例return this.loadBalancer.select(healthyServices);}// 调用服务async callService(name: string,version: string,path: string,options: RequestOptions = {}): Promise<any> {const service = await this.getServiceInstance(name, version);if (!service) {throw new Error(`No healthy service instance found: ${name}@${version}`);}try {const response = await fetch(`${service.baseUrl}${path}`,{...options,timeout: options.timeout || 5000});if (!response.ok) {throw new Error(`Service call failed: ${response.statusText}`);}return await response.json();} catch (error) {// 标记服务不健康this.registry.updateServiceStatus(service, 'unhealthy');throw error;}}
}// 负载均衡器
class LoadBalancer {private currentIndex: number;constructor() {this.currentIndex = 0;}// 选择服务实例select(services: ServiceInfo[]): ServiceInfo {if (services.length === 0) {throw new Error('No services available');}// 轮询算法const service = services[this.currentIndex];this.currentIndex = (this.currentIndex + 1) % services.length;return service;}
}// 服务网关
class ServiceGateway {private registry: ServiceRegistry;private discoveryClient: ServiceDiscoveryClient;private routeConfig: RouteConfig[];constructor(routeConfig: RouteConfig[]) {this.registry = ServiceRegistry.getInstance();this.discoveryClient = new ServiceDiscoveryClient();this.routeConfig = routeConfig;}// 启动网关async start(port: number): Promise<void> {const app = express();// 配置中间件app.use(express.json());app.use(this.errorHandler.bind(this));// 注册路由this.registerRoutes(app);// 启动服务器app.listen(port, () => {console.log(`Gateway is running on port ${port}`);});}// 注册路由private registerRoutes(app: express.Application): void {for (const route of this.routeConfig) {app.use(route.path,this.createProxyMiddleware(route));}}// 创建代理中间件private createProxyMiddleware(route: RouteConfig): express.RequestHandler {return async (req, res, next) => {try {const response = await this.discoveryClient.callService(route.service,route.version,req.path,{method: req.method,headers: req.headers as any,body: req.body});res.json(response);} catch (error) {next(error);}};}// 错误处理中间件private errorHandler(err: Error,req: express.Request,res: express.Response,next: express.NextFunction): void {console.error('Gateway error:', err);res.status(500).json({error: 'Internal Server Error',message: err.message});}
}// 接口定义
interface ServiceInfo {name: string;version: string;instanceId: string;baseUrl: string;status: ServiceStatus;lastUpdateTime: number;metadata?: Record<string, any>;
}interface RegistryConfig {checkInterval: number;timeoutThreshold: number;
}interface RouteConfig {path: string;service: string;version: string;
}interface RequestOptions extends RequestInit {timeout?: number;
}type ServiceStatus = 'healthy' | 'unhealthy';// 使用示例
async function main() {// 创建服务注册中心const registry = ServiceRegistry.getInstance();// 注册服务registry.registerService({name: 'user-service',version: '1.0.0',instanceId: 'user-1',baseUrl: 'http://localhost:3001',status: 'healthy',lastUpdateTime: Date.now()});// 创建服务网关const gateway = new ServiceGateway([{path: '/api/users',service: 'user-service',version: '1.0.0'}]);// 启动网关await gateway.start(3000);// 创建服务发现客户端const client = new ServiceDiscoveryClient();// 调用服务try {const result = await client.callService('user-service','1.0.0','/users',{ method: 'GET' });console.log('Service call result:', result);} catch (error) {console.error('Service call failed:', error);}
}main().catch(console.error);

最佳实践与建议

  1. 服务设计

    • 遵循单一职责原则
    • 合理划分服务边界
    • 保持服务独立性
    • 避免服务耦合
  2. 服务治理

    • 实现服务注册发现
    • 配置健康检查
    • 使用负载均衡
    • 实现熔断降级
  3. 通信机制

    • 选择合适协议
    • 处理通信异常
    • 实现重试机制
    • 保证消息可靠
  4. 数据管理

    • 实现分布式事务
    • 保证数据一致性
    • 处理并发访问
    • 优化查询性能
  5. 可观测性

    • 收集服务指标
    • 实现链路追踪
    • 聚合服务日志
    • 设置告警规则

总结

Node.js微服务架构需要考虑以下方面:

  1. 服务拆分与治理
  2. 通信机制与数据管理
  3. 监控与可观测性
  4. 部署与运维支持
  5. 安全与性能优化

通过合理的微服务架构设计,可以提高系统的可扩展性和可维护性。

学习资源

  1. 微服务架构设计
  2. 服务治理实践
  3. 分布式系统理论
  4. DevOps最佳实践
  5. 云原生技术栈

如果你觉得这篇文章有帮助,欢迎点赞收藏,也期待在评论区看到你的想法和建议!👇

终身学习,共同成长。

咱们下一期见

💻

相关文章:

Node.js系列(4)--微服务架构实践

Node.js微服务架构实践 &#x1f504; 引言 微服务架构已成为构建大规模Node.js应用的主流选择。本文将深入探讨Node.js微服务架构的设计与实现&#xff0c;包括服务拆分、服务治理、通信机制等方面&#xff0c;帮助开发者构建可扩展的微服务系统。 微服务架构概述 Node.js…...

基于Spring Boot的公司资产网站的设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…...

CSS 中flex - grow、flex - shrink和flex - basis属性的含义及它们在弹性盒布局中的协同作用。

大白话CSS 中flex - grow、flex - shrink和flex - basis属性的含义及它们在弹性盒布局中的协同作用。 在 CSS 的弹性盒布局&#xff08;Flexbox&#xff09;里&#xff0c;flex-grow、flex-shrink 和 flex-basis 这三个属性对弹性元素的尺寸和伸缩性起着关键作用。下面为你详细…...

基于CVX优化器的储能电池调峰调频算法matlab仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 原理概述 4.2 CVX工具箱概述 5.完整工程文件 1.课题概述 基于CVX优化器的储能电池调峰调频算法matlab仿真。CVX 是一种用于求解凸优化问题的强大工具。凸优化问题具有良好的数学性质&#xff0c;能…...

SpringBoot3+Vue3开发学生成绩管理系统

系统介绍 此系统功能包含&#xff1a;首页、课程管理、成绩查询、成绩详情、班级管理、专业管理、用户管理等功能。用户管理又细分为账号管理、学生管理、教师管理、管理员管理。 基础功能包含&#xff1a;登录、退出、修改登录人信息、修改登录人密码。 分为4种角色&#x…...

正则魔法:解码 return /^\d+$/.test(text) ? text : ‘0‘ 的秘密

&#x1f680; 正则魔法&#xff1a;解码 return /^\d$/.test(text) ? text : 0 的秘密 &#x1f31f; 嘿&#xff0c;技术探险家们&#xff01;&#x1f44b; 今天我们要破解一段看似简单的代码&#xff1a;return /^\d$/.test(text) ? text : 0。它藏在一个 Vue 前端组件中…...

基于BClinux8部署Ceph 19.2(squid)集群

#作者&#xff1a;闫乾苓 文章目录 1.版本选择Ceph版本发布历史目前官方在维护的版本 2.部署方法3.服务器规划4.前置配置4.1系统更新4.2配置hosts cat >> /etc/hosts << EOFssh-keygenssh-copy-id ceph01ssh-copy-id ceph02ssh-copy-id ceph034.5 Python34.6 Syst…...

CVPR2025 | 对抗样本智能安全方向论文汇总 | 持续更新中~

汇总结果来源&#xff1a;CVPR 2025 Accepted Papers 若文中出现的 论文链接 和 GitHub链接 点不开&#xff0c;则说明还未公布&#xff0c;在公布后笔者会及时添加. 若笔者未及时添加&#xff0c;欢迎读者告知. 文章根据题目关键词搜索&#xff0c;可能会有遗漏. 若笔者出现…...

[leetcode]1631. 最小体力消耗路径(bool类型dfs+二分答案/记忆化剪枝/并查集Kruskal思想)

题目链接 题意 给定 n m n\times m nm地图 要从(1,1) 走到 (n,m) 定义高度绝对差为四联通意义下相邻的两个点高度的绝对值之差 定义路径的体力值为整条路径上 所有高度绝对差的max 求所有路径中 最小的路径体力值是多少 方法1 这是我一开始自己写的记忆化剪枝 比较暴力 时…...

Linux-Ubuntu 系统学习笔记 | 从入门到实战

&#x1f4d8; Linux-Ubuntu 系统学习笔记 | 从入门到实战 &#x1f4dc; 目录 环境安装基本操作Linux操作系统介绍文件系统常用命令用户权限管理编辑器vimGCC编译器动态库与静态库Makefile 1. 环境安装 &#x1f31f; 下载镜像 推荐使用清华大学开源镜像站下载Ubuntu镜像&a…...

Java学习笔记-XXH3哈希算法

XXH3是由Yann Collet设计的非加密哈希算法&#xff0c;属于XXHash系列的最新变种&#xff0c;专注于极速性能与低碰撞率&#xff0c;适用于对计算效率要求极高的场景。 极速性能 在RAM速度限制下运行&#xff0c;小数据&#xff08;如 1-128 字节&#xff09;处理可达纳秒级&…...

【容器运维】docker搭建私有仓库

一、基础方案&#xff1a;使用 Docker Registry 快速搭建 1. 拉取并启动 Registry 镜像 # 拉取官方镜像 docker pull registry:2# 运行容器&#xff08;数据持久化到宿主机目录&#xff09; docker run -d -p 5000:5000 \--name my-registry \-v /opt/data/registry:/var/lib…...

深入理解 Spring 框架中的 AOP 技术

一、引言 在 Java 开发领域&#xff0c;Spring 框架凭借其强大的功能和丰富的特性&#xff0c;成为了众多开发者构建企业级应用的首选。其中&#xff0c;面向切面编程&#xff08;AOP&#xff09;作为 Spring 框架的核心技术之一&#xff0c;为开发者提供了一种全新的程序结构…...

磁盘清理工具-TreeSize Free介绍

TreeSizeFree是一个磁盘空间管理工具&#xff0c;主要用于分析磁盘使用情况&#xff0c;帮助用户找到占用空间大的文件和文件夹: 特点&#xff1a;按大小排序&#xff1a;快速找到占用空间最大的文件或文件夹 一般可以删除: 扫描 C:\Users\XXX\AppData\Local\Temp 或 C:\Window…...

redis MISCONF Redis is configured to save RDB snapshots报错解决

直接上解决方案 修改redis配置文件 stop-writes-on-bgsave-error no 重启redis...

c#知识点补充2

1.非静态类能否调用静态方法可以 2.对string类型扩展方法&#xff0c;如何进行 类用静态类&#xff0c;参数是this 调用如下 3.out的用法 一定要给a赋值 这种写法不行 这样才行 4.匿名类 5.委托的使用 无论是匿名委托&#xff0c;还是具命委托&#xff0c;委托实例化后一定要…...

循环神经网络(Recurrent Neural Network, RNN)与 Transformer

循环神经网络&#xff08;RNN&#xff09;与 Transformer 1. 循环神经网络&#xff08;RNN&#xff09;简介 1.1 RNN 结构 循环神经网络&#xff08;Recurrent Neural Network, RNN&#xff09;是一种适用于处理序列数据的神经网络。其核心特点是通过隐藏状态&#xff08;Hi…...

力扣45.跳跃游戏

45. 跳跃游戏 II - 力扣&#xff08;LeetCode&#xff09; 代码区&#xff1a; #include<vector> class Solution {public:int jump(vector<int>& nums) {int ans[10005] ;memset(ans,1e4,sizeof(ans));ans[0]0;for(int i0;i<nums.size();i){for(int j1;j…...

招聘面试季--方法论--如何从零到-规划一个新的app产品

规划一个新APP产品的系统化步骤及关键要点&#xff1a; 一、需求验证阶段 ‌明确目标用户与核心需求‌ 通过用户调研&#xff08;问卷、访谈&#xff09;定义目标人群的痛点和场景&#xff0c;例如购物类APP需优先满足浏览、支付等核心需求‌。判断APP的必要性&#xff1a;若功…...

MacOS安装 nextcloud 的 Virtual File System

需求 在Mac上安装next cloud实现类似 OneDrive 那样&#xff0c;文件直接保存在服务器&#xff0c;需要再下载到本地。 方法 在 官网下载Download for desktop&#xff0c;注意要下对版本&#xff0c;千万别下 Mac OS默认的那个。 安装了登录在配置过程中千万不要设置任何同…...

OpenCV Imgproc 模块使用指南(Python 版)

一、模块概述 imgproc 模块是 OpenCV 的图像处理核心&#xff0c;提供从基础滤波到高级特征提取的全流程功能。核心功能包括&#xff1a; 图像滤波&#xff1a;降噪、平滑、锐化几何变换&#xff1a;缩放、旋转、透视校正颜色空间转换&#xff1a;BGR↔灰度 / HSV/Lab 等阈值…...

C/C++蓝桥杯算法真题打卡(Day6)

一、P8615 [蓝桥杯 2014 国 C] 拼接平方数 - 洛谷 方法一&#xff1a;算法代码&#xff08;字符串分割法&#xff09; #include<bits/stdc.h> // 包含标准库中的所有头文件&#xff0c;方便编程 using namespace std; // 使用标准命名空间&#xff0c;避免每次调用…...

ORACLE RAC ASM双存储架构下存储部分LUN异常的处理

早上接到用户电话&#xff0c;出现有表空间不足的告警&#xff0c;事实上此环境经常巡检并且有告警系统&#xff0c;一开始就带着有所疑惑的心理&#xff0c;结果同事在扩大表空间时&#xff0c;遇到报错 ORA-15401/ORA-17505,提示ASM空间满了&#xff1a; ALERT日志&#xff1…...

【设计模式】SOLID 设计原则概述

SOLID 是面向对象设计中的五大原则&#xff0c;不管什么面向对象的语言&#xff0c; 这个准则都很重要&#xff0c;如果你没听说过&#xff0c;赶紧先学一下。它可以提高代码的可维护性、可扩展性和可读性&#xff0c;使代码更加健壮、易于测试和扩展。SOLID 代表以下五个设计原…...

从边缘到核心:群联云防护如何重新定义安全加速边界?

一、安全能力的全方位碾压 1. 协议层深度防护 四层防御&#xff1a; 动态过滤畸形TCP/UDP包&#xff08;如SYN Flood&#xff09;&#xff0c;传统CDN仅限速率控制。技术示例&#xff1a;基于AI的协议指纹分析&#xff0c;拦截异常连接模式。 七层防御&#xff1a; 精准识别业…...

others-rustdesk远程

title: others-rustdesk远程 categories: Others tags: [others, 远程] date: 2025-03-19 10:19:34 comments: false mathjax: true toc: true others-rustdesk远程, 替代 todesk 的解决方案 前篇 官方 服务器 - https://rustdesk.com/docs/zh-cn/self-host/rustdesk-server-o…...

记录 macOS 上使用 Homebrew 安装的软件

Homebrew 是 macOS 上最受欢迎的软件包管理器之一&#xff0c;能够轻松安装各种命令行工具和 GUI 应用。本文记录了我通过 Homebrew 安装的各种软件&#xff0c;并对它们的用途和基本使用方法进行介绍。 &#x1f37a; Homebrew 介绍 Homebrew 是一个开源的包管理器&#xff…...

springmvc中使用interceptor拦截

HandlerInterceptor 是Spring MVC中用于在请求处理之前、之后以及完成之后执行逻辑的接口。它与Servlet的Filter类似&#xff0c;但更加灵活&#xff0c;因为它可以访问Spring的上下文和模型数据。HandlerInterceptor 常用于日志记录、权限验证、性能监控等场景。 ### **1. 创…...

C++基础 [八] - list的使用与模拟实现

目录 list的介绍 List的迭代器失效问题 List中sort的效率测试 list 容器的模拟实现思想 模块分析 作用分析 list_node类设计 list 的迭代器类设计 迭代器类--存在的意义 迭代器类--模拟实现 模板参数 和 成员变量 构造函数 * 运算符的重载 运算符的重载 -- 运…...

使用excel.EasyExcel实现导出有自定义样式模板的excel数据文件,粘贴即用!!!

客户要求导出的excel文件是有好看格式的&#xff0c;当然本文举例模板文件比较简单&#xff0c;内容丰富的模板可以自行设置&#xff0c;话不多说&#xff0c;第一步设置一个"好看"的excel文件模板 上面要注意的地方是{.变量名} &#xff0c;这里的变量名对应的就是…...