Thrift与NestJS:构建高性能分布式系统的实战指南

前言

Thrift 是由 Facebook 开发并在 2007 年开源的一种跨语言服务通信框架,旨在简化不同编程语言写的服务之间的通信。它提供了一种高效的数据传输方式,并且能够让开发者在不同编程语言间无缝调用。
Thrift 的核心在于它提供了一种接口定义语言(IDL,Interface Definition Language),通过该语言开发者可以定义数据类型和服务接口,然后 Thrift 根据这些定义生成相应的代码文件,支持多种编程语言如 C++、Java、Python、PHP、Ruby、Go 等等。

Thrift 的工作原理

  1. 定义接口:使用 Thrift IDL 文件(.thrift),定义服务接口和数据结构。
  2. 生成代码:使用 Thrift 编译器(thrift),根据 IDL 文件生成相应语言的客户端和服务端代码。
  3. 实现服务:在生成的代码基础上,填充具体的业务逻辑。
  4. 部署服务:启动服务端,客户端可以通过 Thrift 协议调用服务。
    这种方式解决了跨语言通信的难题,同时也使得分布式系统的开发变得更加简单和高效。

在 NestJS 中使用 Thrift

NestJS 受 Angular 的启发,用 TypeScript 写成,提供了强大的模块化和装饰器功能。虽然 NestJS 本身并没有直接支持 Thrift,但是我们可以通过一些配置和库来使用 Thrift。

步骤 1:安装必要的依赖

首先,你需要安装一些 Thrift 相关的依赖。你可以使用 npm 来安装这些包。

npm install --save thrift

步骤 2:编写 Thrift IDL 文件

创建一个 .thrift 文件,例如 service.thrift,定义你的服务和数据类型。

namespace js exampleservice HelloService {string sayHello(1: string name)
}

步骤 3:使用 Thrift 编译器生成代码

使用 Thrift 编译器生成对应的 TypeScript 代码。

thrift --gen js:node service.thrift

生成的代码通常会放在 gen-nodejs 目录下。

步骤 4:编写 NestJS 服务

创建一个新的 NestJS 服务,使用生成的代码实现业务逻辑。

import { Injectable } from '@nestjs/common';
import { HelloService } from './gen-nodejs/HelloService';@Injectable()
export class HelloServiceImpl implements HelloService.Iface {async sayHello(name: string): Promise<string> {return Hello, ${name}!;}
}

步骤 5:手动创建 Thrift 服务

由于 NestJS 并不直接支持 Thrift 作为传输层,我们需要手动创建 Thrift 服务并与 NestJS 的模块集成。

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { createServer } from 'thrift';
import { HelloService, HelloServiceHandler } from './gen-nodejs/HelloService';async function bootstrap() {// 创建 NestJS 应用const app = await NestFactory.create(AppModule);await app.listen(3000);// 创建 Thrift 服务器const handler: HelloServiceHandler = {async sayHello(name: string): Promise<string> {return Hello, ${name}!;},};const server = createServer(HelloService, handler);server.listen(9090, () => {console.log('Thrift server is running on port 9090');});
}
bootstrap();

步骤 6:客户端调用

客户端可以使用生成的 Thrift 代码来调用服务。

import thrift from 'thrift';
import { HelloService } from './gen-nodejs/HelloService';const connection = thrift.createConnection('localhost', 9090);
const client = thrift.createClient(HelloService, connection);client.sayHello('World', (err, response) => {if (err) {console.error(err);} else {console.log(response);}connection.end();
});

进阶配置

1. 配置 Thrift 传输协议和协议层

Thrift 支持多种传输协议(Transport)和协议层(Protocol),例如 TBinaryProtocol、TCompactProtocol 等。在实际应用中,我们可以根据需求选择合适的协议。

import { TBinaryProtocol, TBufferedTransport } from 'thrift';const server = thrift.createServer(HelloService, handler, {protocol: TBinaryProtocol,transport: TBufferedTransport,
});
server.listen(9090, () => {console.log('Thrift server is running on port 9090');
});

2. 配置超时和重试

在分布式系统中,设置合理的超时和重试机制非常重要,以防止单点失败影响整个系统。我们可以在客户端配置请求超时和重试逻辑。

const clientOptions = {transport: thrift.TBufferedTransport,protocol: thrift.TBinaryProtocol,connect_timeout: 5000, // 连接超时时间retry_max_delay: 3000, // 最大重试延迟时间
};const connection = thrift.createConnection('localhost', 9090, clientOptions);
const client = thrift.createClient(HelloService, connection);// 添加错误处理
connection.on('error', (err) => {console.error('Connection Error: ', err);
});

性能优化

1. 使用连接池

为了提高性能,可以使用连接池来管理 Thrift 连接,避免频繁创建和销毁连接带来的开销。可以使用一些第三方库来实现连接池,例如 generic-pool。

import thrift from 'thrift';
import genericPool from 'generic-pool';
import { HelloService } from './gen-nodejs/HelloService';const factory = {create: () => {const connection = thrift.createConnection('localhost', 9090);const client = thrift.createClient(HelloService, connection);return client;},destroy: (client) => {client.connection.end();},
};const pool = genericPool.createPool(factory, { max: 10, min: 2 });async function useClient() {const client = await pool.acquire();client.sayHello('World', (err, response) => {if (err) {console.error(err);} else {console.log(response);}pool.release(client);});
}

2. 监控和日志

对服务进行监控和日志记录是确保系统稳定性和性能的重要手段。可以使用中间件来记录请求和响应的日志。

import { Logger } from '@nestjs/common';const logger = new Logger('ThriftService');// 示例中间件
function logMiddleware(req, res, next) {logger.log('Request: ' + JSON.stringify(req));next();logger.log('Response: ' + JSON.stringify(res));
}const server = thrift.createServer(HelloService, handler, {protocol: TBinaryProtocol,transport: TBufferedTransport,
});// 添加中间件
server.use(logMiddleware);server.listen(9090, () => {console.log('Thrift server is running on port 9090');
});

全局错误处理

为了提高系统的健壮性,建议在 NestJS 应用中添加全局错误处理机制,捕获和处理所有未捕获的异常。

import { ExceptionFilter, Catch, ArgumentsHost, HttpException, Logger } from '@nestjs/common';
import { ThriftException } from 'thrift';@Catch()
export class AllExceptionsFilter implements ExceptionFilter {private readonly logger = new Logger(AllExceptionsFilter.name);catch(exception: any, host: ArgumentsHost) {this.logger.error('Unhandled Exception', exception.stack);const ctx = host.switchToRpc();const response = ctx.getContext();// 自定义 Thrift 异常处理if (exception instanceof ThriftException) {response.send({ message: 'Thrift Exception Occurred' });} else if (exception instanceof HttpException) {const status = exception.getStatus();response.send({ statusCode: status, message: exception.message });} else {response.send({ statusCode: 500, message: 'Internal Server Error' });}}
}// 在你的 main.ts 中
import { AllExceptionsFilter } from './common/filters/all-exceptions.filter';async function bootstrap() {const app = await NestFactory.create(AppModule);app.useGlobalFilters(new AllExceptionsFilter());await app.listen(3000);// 创建 Thrift 服务器const handler: HelloServiceHandler = {async sayHello(name: string): Promise<string> {return Hello, ${name}!;},};const server = createServer(HelloService, handler);server.listen(9090, () => {console.log('Thrift server is running on port 9090');});
}
bootstrap();

总结

通过本文的介绍,我们从基础的 Thrift 概念和简单实现,到进阶的配置与优化,逐步深入理解了如何在 NestJS 中集成和使用 Thrift。我们探讨了如何手动创建 Thrift 服务、使用连接池、配置日志和监控,以及全局错误处理等进阶技巧。这些内容为你提供了实用的指导,助你在构建高效、稳定的分布式系统时更加得心应手。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/473814.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Qt 之 qwt和QCustomplot对比

QWT&#xff08;Qt Widgets for Technical Applications&#xff09;和 QCustomPlot 都是用于在 Qt 应用程序中绘制图形和图表的第三方库。它们各有优缺点&#xff0c;适用于不同的场景。 以下是 QWT 和 QCustomPlot 的对比分析&#xff1a; 1. 功能丰富度 QWT 功能丰富&a…

实用教程:如何无损修改MP4视频时长

如何在UltraEdit中搜索MP4文件中的“mvhd”关键字 引言 在视频编辑和分析领域&#xff0c;有时我们需要深入到视频文件的底层结构中去。UltraEdit&#xff08;UE&#xff09;和UEStudio作为强大的文本编辑器&#xff0c;允许我们以十六进制模式打开和搜索MP4文件。本文将指导…

使用nossl模式连接MySQL数据库详解

使用nossl模式连接MySQL数据库详解 摘要一、引言二、nossl模式概述2.1 SSL与nossl模式的区别2.2 选择nossl模式的场景三、在nossl模式下连接MySQL数据库3.1 准备工作3.2 C++代码示例3.3 代码详解3.3.1 初始化MySQL连接对象3.3.2 连接到MySQL数据库3.3.3 执行查询操作3.3.4 处理…

Linux下编译MFEM

本文记录在Linux下编译MFEM的过程。 零、环境 操作系统Ubuntu 22.04.4 LTSVS Code1.92.1Git2.34.1GCC11.4.0CMake3.22.1Boost1.74.0oneAPI2024.2.1 一、安装依赖 二、编译代码 附录I: CMakeUserPresets.json {"version": 4,"configurePresets": [{&quo…

号卡分销系统,号卡系统,物联网卡系统源码安装教程

号卡分销系统&#xff0c;号卡系统&#xff0c;物联网卡系统&#xff0c;&#xff0c;实现的高性能(PHP协程、PHP微服务)、高灵活性、前后端分离(后台)&#xff0c;PHP 持久化框架&#xff0c;助力管理系统敏捷开发&#xff0c;长期持续更新中。 主要特性 基于Auth验证的权限…

Java基础-集合

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 目录 前言 一、Java集合框架概述 二、Collection接口及其实现 2.1 Collection接口 2.2 List接口及其实现 …

基于Python的仓库管理系统设计与实现

背景&#xff1a; 基于Python的仓库管理系统功能介绍 本仓库管理系统采用Python语言开发&#xff0c;利用Django框架和MySQL数据库&#xff0c;实现了高效、便捷的仓库管理功能。 用户管理&#xff1a; 支持员工和管理员角色的管理。 用户注册、登录和权限分配功能&#x…

机器学习(基础2)

特征工程 特征工程:就是对特征进行相关的处理 一般使用pandas来进行数据清洗和数据处理、使用sklearn来进行特征工程 特征工程是将任意数据(如文本或图像)转换为可用于机器学习的数字特征,比如:字典特征提取(特征离散化)、文本特征提取、图像特征提取。 特征工程API 实例化…

MATLAB向量元素的引用

我们定义一个向量后&#xff0c;如果想引用的话&#xff0c;可以通过索引 i n d ind ind来实现。 注意&#xff1a;MATLAB中向量的开始索引是1&#xff0c;与许多编程语言不同。 例如&#xff1a; 如果想引用多个的话&#xff0c;可以用索引 i n d ind ind来提取多个位置 例如…

微信小程序之路由跳转传数据及接收

跳转并传id或者对象 1.home/index.wxml <!--点击goto方法 将spu_id传过去--> <view class"item" bind:tap"goto" data-id"{{item.spu_id}}"> 结果: 2.home/index.js goto(event){// 路由跳转页面,并把id传传过去//获取商品idlet i…

贪心算法入门(三)

相关文章 贪心算法入门&#xff08;一&#xff09;-CSDN博客 贪心算法入门&#xff08;二&#xff09;-CSDN博客 1.什么是贪心算法&#xff1f; 贪心算法是一种解决问题的策略&#xff0c;它将复杂的问题分解为若干个步骤&#xff0c;并在每一步都选择当前最优的解决方案&am…

QT仿QQ聊天项目,第三节,实现聊天界面

一&#xff0c;界面控件示意图 界面主要由按钮QPushButton,标签QLabel,列表QListWidget 要注意的是QListWidget既是实现好友列表的控件&#xff0c;也是实现聊天气泡的控件 二&#xff0c;控件样式 QPushButton#btn_name {border:none;}QPushButton#btn_close {border:1px;bac…

Gin 框架入门(GO)-1

解决安装包失败问题(*) go env -w GO111MODULE=on go env -w GOPROXY=https://goproxy.cn,direct 1 介绍 Gin 是一个 Go (Golang) 编写的轻量级 http web 框架,运行速度非常快,Gin 最擅长的就是 Api 接口的高并发。 2 Gin 环境搭建 1.下载并安装 gin go get -u github.…

workerman的安装与使用

webman是一款基于workerman开发的高性能HTTP服务框架。webman用于替代传统的php-fpm架构&#xff0c;提供超高性能可扩展的HTTP服务。你可以用webman开发网站&#xff0c;也可以开发HTTP接口或者微服务。 除此之外&#xff0c;webman还支持自定义进程&#xff0c;可以做worker…

学习日记_20241117_聚类方法(高斯混合模型)

前言 提醒&#xff1a; 文章内容为方便作者自己后日复习与查阅而进行的书写与发布&#xff0c;其中引用内容都会使用链接表明出处&#xff08;如有侵权问题&#xff0c;请及时联系&#xff09;。 其中内容多为一次书写&#xff0c;缺少检查与订正&#xff0c;如有问题或其他拓展…

开源音乐分离器Audio Decomposition:可实现盲源音频分离,无需外部乐器分离库,从头开始制作。将音乐转换为五线谱的程序

今天给大家分析一个音频分解器&#xff0c;通过傅里叶变换和信封匹配分离音乐中的各个音符和乐器&#xff0c;实现音乐到乐谱的转换。将音乐开源分离为组成乐器。该方式是盲源分离&#xff0c;从头开始制作&#xff0c;无需外部乐器分离库。 相关链接 代码&#xff1a;https:…

多模态基础模型:从专家到通用助手

概要 本文对展示视觉和视觉语言能力的多模态基础模型的分类和演变进行了全面调查&#xff0c;重点关注从专业模型到通用助手的过渡。研究领域包括五个核心主题&#xff0c;分为两类。&#xff08;i&#xff09; 我们从对成熟研究领域的调查开始&#xff1a;为特定目的预先训练…

Nature Communications 基于触觉手套的深度学习驱动视触觉动态重建方案

在人形机器人操作领域&#xff0c;有一个极具价值的问题&#xff1a;鉴于操作数据在人形操作技能学习中的重要性&#xff0c;如何有效地从现实世界中获取操作数据的完整状态&#xff1f;如果可以&#xff0c;那考虑到人类庞大规模的人口和进行复杂操作的简单直观性与可扩展性&a…

ReactPress与WordPress:一场内容管理系统的较量

ReactPress Github项目地址&#xff1a;https://github.com/fecommunity/reactpress WordPress官网&#xff1a;https://wordpress.org/ ReactPress与WordPress&#xff1a;一场内容管理系统的较量 在当今数字化时代&#xff0c;内容管理系统&#xff08;CMS&#xff09;已成为…

解决Windows远程桌面 “为安全考虑,已锁定该用户账户,原因是登录尝试或密码更改尝试过多。请稍后片刻再重试,或与系统管理员或技术支持联系“问题

当我们远程连接服务器连接不上并提示“为安全考虑&#xff0c;已锁定该用户账户&#xff0c;原因是登录尝试或密码更改尝试过多。请稍候片刻再重试&#xff0c;或与系统管理员或技术支持联系”时&#xff0c;根本原因是当前计算机远程连接时输入了过多的错误密码&#xff0c;触…