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

Nestjs 微服务实战 - 动态微服务创建链接

所有的微服务都需要做服务治理

服务治理包括(配置中心、服务发现、注册服务等等),常见的包括 Java 的 Nacos,这里不关注与服务治理,只说明,如何用 nest 网关,并且在网关层动态实现微服务注入

nestjs 官网的案例明显是偏向于手动注册微服务的,例如:

/** Model */
@Module({imports: [/** Model 中使用并注册 */ ClientsModule.register([{ name: 'MATH_SERVICE', transport: Transport.TCP },]),]...
});/** service / controller 使用 */
constructor(/** 通过 @Inject 装饰器只能挨个进行倒入,有多少服务倒入多少 */@Inject('MATH_SERVICE') private client: ClientProxy,
) {}

以上属于官网列出的例子,对于真正的微服务开发肯定是不够用的,因为服务并没有根据配置中心的配置进行动态变更倒入,这种情况下,假如某个服务很占用 CPU、内存导致荡机了,也无法进行动态扩展,只能去重启服务手动更改配置,而我需要的是完全动态,每个服务部署都独立部署出来,对于高CPU的服务进行动态扩展服务器,进行自动切换 ip 端口线路。

首先所有的服务都不要在 Model 中进行注册,建议全丢在 service / controller 中使用,我这里以 controller 为例:

import { All, Controller, Req, Res } from '@nestjs/common';
import { ClientProxyFactory, Transport } from '@nestjs/microservices';
import { createProxyServer } from 'http-proxy';/** 动态数组,这里后面要通过定时任务去配置中心拉取 */
const serviceList = [{name: 'user-center',host: '127.0.0.1',port: 65531,},
];@Controller()
export class AppController {/** 首先所有路由不管任何请求方式全部代理到这个方法上 */@All('*')async root(@Req() req, @Res() res): Promise<any> {/** 获取所有可获取的参数 */const { method, originalUrl, query, body, headers } = req;/** 根据 url 字符串切割一下获取,主要获取第一级和第二级路由 */const list = originalUrl.split('?')[0].split('/').filter((item: string) => item !== '');/** 所有,开头为 /api 的参数,并且路由大于并且等于 2 级以上的,基本都可以调用微服务 */if (list.length >= 2 && list[0] === 'api') {/** 微服务真正的地址,是三级路径 */const path = `/${list.slice(2).join('/')}`;/** 服务名称是二级目录 */const service = list[1];/** 查找服务名称是否存在 */const server = serviceList.find((item) => item.name === service);/** 服务存在 */if (server) {/** 错误执行 */const errorNext = (err: string) => {/** 地址错误 */if (err === 'There is no matching message handler defined in the remote service.') {/** 手动关闭服务链接 */this[service].close();/** 清楚链接,下次链接如果服务可用就触发重新链接 */this[service] = undefined;res.status(404);res.send({code: -1,msg: '地址错误',});} else {console.log(`其他错误: ${err}`);}};/** 当前 class 中找不到服务,需要创建服务 */if (!this[service]) {/** 动态创建服务链接 */this[service] = ClientProxyFactory.create({transport: Transport.TCP,options: {host: server.host,port: server.port,},});try {/** 链接服务 */await this[service].connect();/** 发送消息*/const data = this[service].send(/** 服务的接口地址是 { method = 请求方法, path = 等于相对路径 }  */{ method, path },/** 把所有 http 的参数全部传递过去,让那边服务自己判断处理 */{ query, body, headers },);/** 接受流消息 */data.subscribe({/** 成功执行 next */next: (_res_: any) => {res.status(200);res.send(_res_);},/** 失败吧错误信息丢个 errorNext */error: (err: any) => errorNext(err),});} /** 服务存在,但是可能荡机了,又或者服务正在重启过程中 */ catch (err) {/** 手动关闭服务链接 */this[service].close();/** 清楚链接,下次链接如果服务可用就触发重新链接 */this[service] = undefined;res.status(503);res.send({code: -1,msg: '当前服务正在维护中',});}} /** 服务已存在 */ else {/** 发送消息*/const data = this[service].send(/** 服务的接口地址是 { method = 请求方法, path = 等于相对路径 }  */{ method, path },/** 把所有 http 的参数全部传递过去,让那边服务自己判断处理 */{ query, body, headers },);/** 接受流消息 */data.subscribe({/** 成功执行 next */next: (_res_: any) => {res.status(200);res.send(_res_);},/** 失败吧错误信息丢个 errorNext */error: (err: any) => errorNext(err),});}} /** 未找到服务 */ else {res.status(404);res.send({code: -1,msg: '未找到对应的服务',});}} /** 反向代理到 admin 地址 */ else if (list.length >= 2 && list[0] === 'admin') {const proxy = createProxyServer({target: 'http://127.0.0.1:4000',changeOrigin: true,});proxy.on('error', () => {res.status(503);res.send({code: -1,msg: '当前服务正在维护中',});});proxy.web(req, res);} /** 反向代理到 nuxt ssr 前端页面地址 */ else {const proxy = createProxyServer({target: 'http://127.0.0.1:5000',changeOrigin: true,});proxy.on('error', () => {res.status(503);res.send({code: -1,msg: '当前服务正在维护中',});});proxy.web(req, res);}}
}

以上是我的核心逻辑部分,主要逻辑应该是一下步骤,

/** 1、创建服务 */
const proxy = ClientProxyFactory.create({transport: Transport.TCP,options: {host: '127.0.0.1',port: 65531,},
});/** 2、服务连接 */
await proxy.connect();/** 3、发送消息 */
const data = this[service].send(消息接口,附加数据,
);/** 4、接受流消息 */
data.subscribe({/** 成功消息 */next: (_res_: any) => {res.status(200);res.send(_res_);},/** 排错 */error: (err: any) => {},
});

相关文章:

Nestjs 微服务实战 - 动态微服务创建链接

所有的微服务都需要做服务治理 服务治理包括&#xff08;配置中心、服务发现、注册服务等等&#xff09;&#xff0c;常见的包括 Java 的 Nacos&#xff0c;这里不关注与服务治理&#xff0c;只说明&#xff0c;如何用 nest 网关&#xff0c;并且在网关层动态实现微服务注入 …...

K8S部署pod状态CreateContainerConfigError问题解决

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…...

PyTorch 简单易懂的实现 CosineSimilarity 和 PairwiseDistance - 距离度量的操作

目录 torch.nn子模块Distance Functions解析 nn.CosineSimilarity 功能 主要参数 输入和输出的形状 使用示例 nn.PairwiseDistance 功能 主要参数 输入和输出的形状 使用示例 总结 torch.nn子模块​​​​​​​Distance Functions解析 nn.CosineSimilarity torc…...

app加载不到aar中的so库

如何将so文件打入到aar包中 1 在main下面新建jniLibs目录并将so放进去 2 在android{}中添加 sourceSets {main {jniLibs.srcDir file(jni/)}}app引用不到aar中的so文件(巨坑&#xff0c;不去查谁知道啊) 在aar 的manifeset application标签中中添加 android:extractNativeLi…...

vue-springboot基于java的实验室安全考试系统

本系统为用户而设计制作实验室安全考试系统&#xff0c;旨在实现实验室安全考试智能化、现代化管理。本实验室安全考试管理自动化系统的开发和研制的最终目的是将实验室安全考试的运作模式从手工记录数据转变为网络信息查询管理&#xff0c;从而为现代管理人员的使用提供更多的…...

mysql+关掉密码过期

mysql关掉密码过期 要在MySQL中关闭密码过期功能&#xff0c;可以按照以下步骤进行操作&#xff1a; 登录到MySQL服务器。 使用管理员账户&#xff08;如root&#xff09;连接到数据库。 mysql -uroot -ppassword 运行以下命令来查看当前的密码过期设置&#xff1a; SHOW…...

实际项目中的环形缓冲区

在实际项目中&#xff0c;环形缓冲区的设计要比之前讲到的原型稍微复杂一些&#xff0c;需要一些接口函数来实现数据结构封装。GitHub上有个大帅哥写了一个轻量的环形缓冲区库&#xff0c;可以学习参考&#xff0c;也可以直接集成到自己的项目中&#xff0c;功能已经非常完善。…...

输出回文数-第11届蓝桥杯选拔赛Python真题精选

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第23讲。 输出回文数&#…...

内存溢出会导致模块测试正常,植入系统失败

前些天&#xff0c;遇到了一个问题&#xff1a;需要在系统中添加一个小功能&#xff0c;单独测试&#xff0c;然后植入系统。 代码使用了从网上下载的函数&#xff0c;模块单独运行&#xff0c;没有问题&#xff0c;但是放在系统中运行就会出问题。 不得已的情况下&#xff0c…...

【taro react】 ---- QRCode 二维码生成

1. 需求分析 需要将输入的值转换为图片资源;由于只是单纯的展示,所以不需要很多比如加 logo 等复杂功能;不需要后端生成,直接前端操作;使用的第三方库尽可能小,功能单一;最后选择使用 qrcode-generator 库,只有 40kb。2. 使用第三方库 qrcode-generator 3. 转换 base…...

rk3566 armbian修复usb2.0并挂载U盘

文章目录 usb接口修复一 执行命令二 修改rk3566-panther-x2.dts⽂件三 查看是否识别 U盘格式化、挂载一 U盘格式化1.1 查看U盘1.2 查看U盘文件系统类型1.3 格式化为ext4系统 二 挂载U盘2.1 手动挂载2.2 自动挂载&#xff08;可选&#xff09; usb接口修复 一 执行命令 将位于…...

猫头虎博主第9期赠书活动:《YOLO目标检测》计算机AI视觉实战YOLO人工智能目标检测与跟踪图像处理深度学习图像检测书籍

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通Golang》…...

python 如何将英语单词翻译成中文

要将英语单词翻译成中文&#xff0c;可以使用 Python 的第三方库 googletrans。该库使用 Google Translate 提供的 API 来进行翻译。 首先&#xff0c;需要安装 googletrans 库。可以使用以下命令在终端或命令提示符中安装&#xff1a; pip install googletrans4.0.0-rc1然后…...

Linux_CentOS_7.9_MySQL_5.7配置数据库服务开机自启动之简易记录

前言&#xff1a; 作为运维保障&#xff0c;都无法准确预估硬件宕机的突发阶段&#xff0c;其生产数据实时在产出&#xff0c;那作为dba数据库服务的其重要性、必要性就突显而出。这里拿虚拟机试验做个配置记录&#xff0c;便于大家学习参考。 # 如出现服务器重启后登入报错无…...

js实现拖动盒子查看内容 内容拖动

一.分析实现过程 1.鼠标拖动的操作是&#xff0c;按下鼠标不松&#xff0c;拖动鼠标&#xff0c;就需要监听鼠标点击事件(onmousedown),鼠标拖动事件(onmousemove) 2.鼠标拖动事件的监听时机&#xff0c;是在按下鼠标之后监听的&#xff0c;所以鼠标拖动事件需要放在鼠标按下事…...

[C#]winform利用seetaface6实现C#人脸检测活体检测口罩检测年龄预测性别判断眼睛状态检测

【官方框架地址】 https://github.com/ViewFaceCore/ViewFaceCore 【算法介绍】 SeetaFace6是由中国科技公司自主研发的一款人脸识别技术&#xff0c;它基于深度学习算法&#xff0c;能够快速、准确地识别出人脸&#xff0c;并且支持多种应用场景&#xff0c;如门禁系统、移动…...

c++ execl 执行 重定向

#include <unistd.h>int main() {pid_t childPid fork(); // 创建子进程if (childPid 0) {// 子进程// 关闭标准输入、输出和错误流close(STDIN_FILENO);close(STDOUT_FILENO);close(STDERR_FILENO);// 打开要写入的文件int fd open("output.txt", O_WRONLY…...

uni-app中实现元素拖动

uni-app中实现元素拖动 1、代码示例 <template><movable-area class"music-layout"><movable-view class"img-layout" :x"x" :y"y" direction"all"><img :src"musicDetail.bgUrl" :class&…...

Java系列-Class.forName和ClassLoader.loadClass的区别

Class.forName 和 ClassLoader.loadClass 是 Java 中两种加载类的方式&#xff0c;它们的主要区别在于加载类的时机和对异常的处理。 1.Class.forName Class.forName 是一个静态方法&#xff0c;用于在运行时加载类。它返回一个 Class 对象&#xff0c;但在加载类的过程中&am…...

找不到模块 “path“ 或其相对应的类型声明

src别名的配置 在开发项目的时候文件与文件关系可能很复杂&#xff0c;因此我们需要给src文件夹配置一个别名 // vite.config.ts import {defineConfig} from vite import vue from vitejs/plugin-vue import path from path export default defineConfig({plugins: [vue()],r…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

工业安全零事故的智能守护者:一体化AI智能安防平台

前言&#xff1a; 通过AI视觉技术&#xff0c;为船厂提供全面的安全监控解决方案&#xff0c;涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面&#xff0c;能够实现对应负责人反馈机制&#xff0c;并最终实现数据的统计报表。提升船厂…...

Java 8 Stream API 入门到实践详解

一、告别 for 循环&#xff01; 传统痛点&#xff1a; Java 8 之前&#xff0c;集合操作离不开冗长的 for 循环和匿名类。例如&#xff0c;过滤列表中的偶数&#xff1a; List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...

ffmpeg(四):滤镜命令

FFmpeg 的滤镜命令是用于音视频处理中的强大工具&#xff0c;可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下&#xff1a; ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜&#xff1a; ffmpeg…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

[USACO23FEB] Bakery S

题目描述 Bessie 开了一家面包店! 在她的面包店里&#xff0c;Bessie 有一个烤箱&#xff0c;可以在 t C t_C tC​ 的时间内生产一块饼干或在 t M t_M tM​ 单位时间内生产一块松糕。 ( 1 ≤ t C , t M ≤ 10 9 ) (1 \le t_C,t_M \le 10^9) (1≤tC​,tM​≤109)。由于空间…...