乐趣区 分享快乐的地方

👋 欢迎来到乐趣区!

  • hi,大家好!欢迎来到我的博客。文章有自创有转发,上架的几个app均为自研,千言万语尽一句,希望能给大家提供帮助。有什么好的建议或者有需要的佛经app,也可以给我发邮件(wukuili@gmail.com)。我会尽可能的开发上线。一切祝好!

RabbitMQ 延迟消息实战(全场景 + 完整实现)

RabbitMQ 本身未直接提供「延迟消息」核心功能,但可通过 死信交换机(DLX)+ 消息过期时间(TTL)、RabbitMQ Delayed Message Exchange 插件 两种方案实现,前者适配轻量场景,后者是官方推荐的通用方案。以下从「核心原理」「实战实现」「场景适配」「性能优化」四维度完整拆解延迟消息落地。 一、核心方案对比(先选对方案) 方案 实现原理 优点 缺点 适用场景 死信交换机+TTL 1. 消息发送到「无消费者的普通队列」并设置 TTL; 2. 消息过期后进入绑定的死信交换机; 3. 死信交换机将消息路由到「实际消费队列」。 无需安装插件,原生支持; 轻量、无额外依赖。 1. 队列级 TTL 会导致「消息批量过期」(队首消息过期才触发); 2. 延迟精度低(依赖队列消费触发); 3. 需额外创建死信交换机/队列,配置复杂。 延迟时间固定、消息量小、精度要求低的场景(如订单超时取消(固定15分钟))。 延迟插件(推荐) 安装 rabbitmq_delayed_message_exchange 插件,交换机类型为 x-delayed-message,消息携带 x-delay 头指定延迟时间,插件在延迟到期后将消息路由到目标队列。 1. 延迟精度高(毫秒级); 2. 支持单消息自定义延迟时间; 3. 配置简单,无需额外队列。 1. 需安装插件; 2. 消息延迟期间存储在内存(可配置磁盘持久化); 3. RabbitMQ 3.5.8+ 支持。 所有延迟场景(尤其是延迟时间不固定、高精度要求的场景,如定时任务、预约提醒)。 二、环境准备 1. 插件安装(延迟插件方案必做) (1)查看 RabbitMQ 版本(需匹配插件版本) 1 2 rabbitmqctl version # 示例输出:RabbitMQ 3.12.0 (2)下载并安装插件 1 2 3 4 5 6 7 8 9 10 11 12 # 1. 下载对应版本插件(以 3.12.0 为例) wget https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases/download/v3.12.0/rabbitmq_delayed_message_exchange-3.12.0.ez # 2. 将插件复制到 RabbitMQ 插件目录 cp rabbitmq_delayed_message_exchange-3.12.0.ez /usr/lib/rabbitmq/lib/rabbitmq_server-3.12.0/plugins/ # 3. 启用插件 rabbitmq-plugins enable rabbitmq_delayed_message_exchange # 4. 验证插件是否启用 rabbitmq-plugins list | grep delayed_message_exchange # 输出 [E*] rabbitmq_delayed_message_exchange 表示启用成功 Docker 环境快捷安装(推荐) 1 2 3 4 5 6 7 # 启动 RabbitMQ 并自动安装延迟插件 docker run -d --name rabbitmq-delayed \ -p 5672:5672 -p 15672:15672 \ -e RABBITMQ_DEFAULT_USER=admin \ -e RABBITMQ_DEFAULT_PASS=admin \ rabbitmq:3.12-management \ rabbitmq-plugins enable rabbitmq_delayed_message_exchange 2. 依赖引入(Java 项目示例) 1 2 3 4 5 6 7 8 9 10 11 12 <!-- Maven 依赖 --> <dependency> <groupId>com.rabbitmq</groupId> <artifactId>amqp-client</artifactId> <version>5.20.0</version> </dependency> <!-- Spring Boot 项目推荐用 starter --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> <version>3.1.0</version> </dependency> 三、实战实现(两种方案完整代码) 方案1:死信交换机+TTL(订单超时取消场景) 核心流程: 1 生产者 → 普通队列(无消费者,设置TTL)→ 死信交换机 → 死信队列 → 消费者 步骤1:声明交换机/队列(Spring Boot 示例) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 import org.springframework.amqp.core.*; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class RabbitMQDeadLetterConfig { // 1. 普通交换机(接收生产者消息) public static final String NORMAL_EXCHANGE = "normal_exchange"; // 2. 普通队列(无消费者,消息过期后进入死信) public static final String NORMAL_QUEUE = "normal_queue"; // 3. 死信交换机 public static final String DEAD_EXCHANGE = "dead_exchange"; // 4. 死信队列(实际消费队列) public static final String DEAD_QUEUE = "dead_queue"; // 声明普通交换机 @Bean public DirectExchange normalExchange() { return new DirectExchange(NORMAL_EXCHANGE); } // 声明死信交换机 @Bean public DirectExchange deadExchange() { return new DirectExchange(DEAD_EXCHANGE); } // 声明普通队列(绑定死信交换机+设置TTL) @Bean public Queue normalQueue() { return QueueBuilder.durable(NORMAL_QUEUE) // 绑定死信交换机 .deadLetterExchange(DEAD_EXCHANGE) // 死信路由键 .deadLetterRoutingKey("dead_key") // 队列级 TTL(所有消息统一延迟,可选:也可单消息设置TTL) .ttl(15 * 60 * 1000) // 15分钟 .build(); } // 声明死信队列 @Bean public Queue deadQueue() { return QueueBuilder.durable(DEAD_QUEUE).build(); } // 绑定普通队列到普通交换机 @Bean public Binding normalBinding() { return BindingBuilder.bind(normalQueue()).to(normalExchange()).with("normal_key"); } // 绑定死信队列到死信交换机 @Bean public Binding deadBinding() { return BindingBuilder.bind(deadQueue()).to(deadExchange()).with("dead_key"); } } 步骤2:生产者发送延迟消息 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.stereotype.Component; import javax.annotation.Resource; @Component public class DelayMessageProducer { @Resource private RabbitTemplate rabbitTemplate; // 发送订单超时取消消息(支持单消息自定义TTL) public void sendDelayMessage(String orderId, long delayTime) { // 消息内容:订单ID String message = "订单超时取消:" + orderId; // 发送消息(若设置单消息TTL,需覆盖队列TTL) rabbitTemplate.convertAndSend( RabbitMQDeadLetterConfig.NORMAL_EXCHANGE, "normal_key", message, // 单消息设置TTL(优先级高于队列TTL) msg -> { msg.getMessageProperties().setExpiration(String.valueOf(delayTime)); return msg; } ); System.out.println("发送延迟消息:" + message + ",延迟时间:" + delayTime / 1000 + "秒"); } } 步骤3:消费者消费死信队列消息 1 2 3 4 5 6 7 8 9 10 11 12 import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.stereotype.Component; @Component public class DelayMessageConsumer { // 监听死信队列(实际处理延迟任务) @RabbitListener(queues = RabbitMQDeadLetterConfig.DEAD_QUEUE) public void consumeDeadMessage(String message) { System.out.println("处理延迟任务:" + message + ",时间:" + System.currentTimeMillis()); // 业务逻辑:取消订单、释放库存等 } } 方案2:延迟插件(通用方案,推荐) 核心流程: 1 生产者(指定x-delay)→ 延迟交换机(x-delayed-message)→ 目标队列 → 消费者 步骤1:声明延迟交换机/队列(Spring Boot 示例) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 import org.springframework.amqp.core.*; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.HashMap; import java.util.Map; @Configuration public class RabbitMQDelayedConfig { public static final String DELAYED_EXCHANGE = "delayed_exchange"; public static final String DELAYED_QUEUE = "delayed_queue"; public static final String DELAYED_ROUTING_KEY = "delayed_key"; // 声明延迟交换机(类型为 x-delayed-message) @Bean public CustomExchange delayedExchange() { Map<String, Object> args = new HashMap<>(); // 指定交换机类型为延迟交换机 args.put("x-delayed-type", "direct"); // 构造参数:名称、类型、持久化、自动删除、参数 return new CustomExchange(DELAYED_EXCHANGE, "x-delayed-message", true, false, args); } // 声明延迟队列 @Bean public Queue delayedQueue() { return QueueBuilder.durable(DELAYED_QUEUE).build(); } // 绑定延迟队列到延迟交换机 @Bean public Binding delayedBinding() { return BindingBuilder.bind(delayedQueue()).to(delayedExchange()).with(DELAYED_ROUTING_KEY).noargs(); } } 步骤2:生产者发送自定义延迟消息 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.stereotype.Component; import javax.annotation.Resource; @Component public class DelayedMessageProducer { @Resource private RabbitTemplate rabbitTemplate; // 发送自定义延迟消息(支持任意延迟时间) public void sendDelayedMessage(String content, long delayTime) { System.out.println("发送延迟消息:" + content + ",延迟时间:" + delayTime / 1000 + "秒"); rabbitTemplate.convertAndSend( RabbitMQDelayedConfig.DELAYED_EXCHANGE, RabbitMQDelayedConfig.DELAYED_ROUTING_KEY, content, // 设置延迟时间(x-delay 头,单位:毫秒) msg -> { msg.getMessageProperties().setHeader("x-delay", delayTime); return msg; } ); } } 步骤3:消费者消费延迟消息 1 2 3 4 5 6 7 8 9 10 11 12 import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.stereotype.Component; @Component public class DelayedMessageConsumer { // 监听延迟队列 @RabbitListener(queues = RabbitMQDelayedConfig.DELAYED_QUEUE) public void consumeDelayedMessage(String message) { System.out.println("接收延迟消息:" + message + ",处理时间:" + System.currentTimeMillis()); // 业务逻辑:定时提醒、任务调度等 } } 测试代码(Spring Boot 启动类) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; @SpringBootApplication public class RabbitMQDelayApplication { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(RabbitMQDelayApplication.class, args); // 测试插件方案:发送延迟5秒的消息 DelayedMessageProducer producer = context.getBean(DelayedMessageProducer.class); producer.sendDelayedMessage("预约提醒:明天10点开会", 5 * 1000); // 测试死信方案:发送订单超时消息(延迟10秒) DelayMessageProducer deadProducer = context.getBean(DelayMessageProducer.class); deadProducer.sendDelayMessage("ORDER_123456", 10 * 1000); } } 三、关键场景适配与注意事项 1. 订单超时取消(死信+固定TTL) 推荐用「队列级 TTL」(统一设置15分钟),避免单消息TTL的批量过期问题; 关键优化:订单支付成功后,主动删除队列中未过期的消息(避免重复取消): 1 2 3 4 5 6 7 8 // 订单支付成功后,删除普通队列中的消息 public void removeUnExpiredMessage(String orderId) { rabbitTemplate.execute(channel -> { channel.basicGet(RabbitMQDeadLetterConfig.NORMAL_QUEUE, false); // 或根据消息ID删除(需发送时设置messageId) return null; }); } 2. 定时任务/预约提醒(插件+动态TTL) 支持任意延迟时间(如预约明天10点提醒,计算当前到目标时间的毫秒差); 精度保障:插件方案延迟精度为毫秒级,优于死信方案; 持久化:消息设置 deliveryMode=2(持久化),避免RabbitMQ重启丢失。 3. 高并发延迟消息(性能优化) 插件方案:延迟消息存储在内存,高并发时需调整RabbitMQ内存限制(rabbitmq.conf): 1 2 vm_memory_high_watermark.relative = 0.7 vm_memory_high_watermark_paging_ratio = 0.5 死信方案:避免单个普通队列堆积大量消息,按业务分多个队列(如按订单类型分队列); 批量处理:消费者开启批量消费,减少MQ交互次数: 1 2 3 // Spring Boot 配置批量消费 spring.rabbitmq.listener.simple.batch-enabled=true spring.rabbitmq.listener.simple.batch-size=10 4. 常见问题解决 问题1:死信方案消息批量过期 原因:队列级TTL是「队首消息过期才触发死信」,若队首消息未过期,后续消息即使过期也不会触发; 解决:改用「单消息TTL」+ 按延迟时间分队列(如1分钟、5分钟、15分钟队列)。 问题2:插件方案消息延迟不准确 原因:RabbitMQ 消息调度线程繁忙; 解决:调整插件调度线程数(rabbitmq.conf): 1 delayed_message_exchange.dispatch_pool_size = 10 问题3:延迟消息丢失 解决: 交换机/队列设置持久化(durable=true); 消息设置 deliveryMode=2; 开启生产者确认(publisher-confirm)和返回(publisher-return); 消费者开启手动ACK,处理完成后再确认。 四、生产环境最佳实践 监控告警:监控延迟队列的消息堆积量,超过阈值(如1000条)触发告警; 降级方案:延迟插件故障时,降级为「定时任务轮询数据库」(如每分钟查一次超时订单); 消息追踪:开启RabbitMQ消息追踪(rabbitmq_tracing插件),排查延迟消息异常; 版本兼容:插件版本需与RabbitMQ版本严格匹配(参考插件官方文档); 避免超长延迟:超过24小时的延迟消息,建议用定时任务+数据库,而非RabbitMQ(减少MQ存储压力)。 总结 死信+TTL:适合轻量、固定延迟、低并发场景,无需插件,配置稍复杂,精度较低; 延迟插件:适合所有场景(尤其是动态延迟、高精度、高并发),配置简单,是生产环境首选; 核心原则:延迟消息需保证「持久化+幂等性」(消费者处理消息时防重复),并做好监控和降级。 完整代码可直接在Spring Boot项目中运行,替换RabbitMQ连接配置(application.yml)即可: ...

December 5, 2025 · 5 min · Theme PaperMod

深入解析 Android SDK 与 Android SDK Platform 的关键区别(3 大核心维度)

Android SDK(Software Development Kit)和 Android SDK Platform 是安卓开发中极易混淆的两个概念,前者是完整的开发工具集,后者是前者的核心组成部分(特定版本的系统层开发资源)。以下从「定义与定位」「核心构成」「使用场景」3大维度深度拆解区别,并补充实操层面的关键细节。 一、定义与定位:整体工具集 vs 特定版本系统核心 维度 Android SDK(安卓开发工具包) Android SDK Platform(安卓SDK平台包) 核心定位 面向安卓开发者的完整工具集合,覆盖从代码编写、编译、调试到打包的全流程 针对某一安卓 API Level(如 API 34 = Android 14)的系统层开发资源包,是 SDK 的核心子集 本质 「开发环境」:包含工具、资源、文档、系统库等所有开发所需组件 「系统适配层」:仅提供对应安卓版本的系统 API、编译依赖、系统镜像等核心资源 版本关联性 无独立版本号,整体随 SDK Tools 版本迭代(如 SDK Tools 34.0.0) 与安卓系统版本强绑定,版本号 = API Level(如 API 34 对应 Android 14 的 Platform 包) 依赖关系 包含多个版本的 Android SDK Platform(可同时安装 API 28、33、34 等 Platform 包) 必须依赖 Android SDK 的基础工具(如 aapt、dx)才能生效,无法单独使用 关键补充: 我们常说的「下载 Android SDK」,实际是下载「SDK 基础工具 + 若干个 Platform 包 + 其他可选组件」; 比如 Android Studio 自带的 SDK Manager,核心功能就是管理不同版本的 Platform 包、SDK Tools、Build-Tools 等。 二、核心构成:全流程工具链 vs 版本化系统资源 1. Android SDK 的完整构成(4大类组件) Android SDK 是一个「组合包」,核心包含以下部分,Android SDK Platform 只是其中第2类: ...

December 5, 2025 · 3 min · Theme PaperMod

前端 G6 图可视化库快速入门

G6 是蚂蚁集团开源的图可视化引擎,专注于关系型数据的可视化展示与交互,支持流程图、拓扑图、知识图谱、力导向图等多种场景。以下是从环境搭建到核心案例的快速上手指南,覆盖基础使用、核心配置、交互扩展等关键内容。 一、核心特性 高性能:支持万级节点/边的渲染与交互(Canvas 渲染核心); 丰富的内置元素:节点、边、锚点等基础元素,支持自定义形状; 灵活的布局:力导向、树形、环形、分层(Dagre)等 20+ 内置布局; 完整的交互体系:拖拽、缩放、选中等基础交互,支持自定义交互行为; 插件化扩展:内置 tooltip、mini-map、undo/redo 等插件,支持自定义插件。 二、快速上手(基础环境) 1. 安装 方式 1:NPM 安装(推荐,适用于 Vue/React/Svelte 等工程化项目) 1 2 3 4 5 6 # 最新稳定版 npm install @antv/g6 --save # 或 yarn/pnpm yarn add @antv/g6 pnpm add @antv/g6 方式 2:CDN 引入(适用于纯 HTML 项目) 1 2 <!-- 引入 G6 核心库 --> <script src="https://gw.alipayobjects.com/os/lib/antv/g6/5.0.0/dist/g6.min.js"></script> 2. 最小示例(渲染基础力导向图) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>G6 快速入门</title> <!-- 容器必须设置宽高 --> <style> #container { width: 800px; height: 600px; border: 1px solid #eee; } </style> </head> <body> <div id="container"></div> <script> // 1. 准备数据(节点 + 边) const data = { // 节点数组:每个节点必须有 id,name/shape/style 为可选 nodes: [ { id: 'node1', name: '节点1', x: 100, y: 200 }, { id: 'node2', name: '节点2', x: 300, y: 200 }, { id: 'node3', name: '节点3', x: 200, y: 100 }, ], // 边数组:每个边必须有 source(源节点)、target(目标节点) edges: [ { source: 'node1', target: 'node2' }, { source: 'node1', target: 'node3' }, { source: 'node2', target: 'node3' }, ], }; // 2. 初始化图实例 const graph = new G6.Graph({ container: 'container', // 挂载容器 ID width: 800, // 图宽度 height: 600, // 图高度 // 基础配置 defaultNode: { // 节点默认样式 size: 60, // 节点大小 style: { fill: '#409eff', stroke: '#fff', lineWidth: 2 }, labelCfg: { style: { fill: '#fff', fontSize: 14 } }, // 节点文字样式 }, defaultEdge: { // 边默认样式 style: { stroke: '#999', lineWidth: 2 }, }, // 布局:力导向布局(无坐标时自动计算节点位置) layout: { type: 'force', // 布局类型 linkDistance: 150, // 边的长度 preventOverlap: true, // 防止节点重叠 }, }); // 3. 加载数据并渲染 graph.data(data); graph.render(); // 4. 开启交互:缩放、拖拽 graph.enableZoom(); graph.enablePan(); </script> </body> </html> 效果说明: 3 个节点自动以力导向布局排列,节点间有边连接; 支持鼠标滚轮缩放、拖拽画布平移、拖拽节点调整位置。 三、核心概念与配置 1. 数据格式(核心) G6 严格要求数据为「节点 + 边」的结构化格式: ...

December 5, 2025 · 6 min · Theme PaperMod

前端 PingCode Wiki 协同编辑技术揭秘

PingCode Wiki(现归属于阿里云效)是面向研发团队的在线协同文档工具,其前端协同编辑能力核心解决了多人实时编辑冲突、内容同步、操作追溯等问题。以下从技术架构、核心原理、关键实现细节三个维度拆解其前端协同编辑技术: 一、核心技术架构 PingCode Wiki 前端协同编辑基于「CRDT 算法 + 富文本编辑器 + WebSocket 实时通信 + 本地缓存/快照」构建,整体架构如下: 1 用户操作 → 富文本编辑器(ProseMirror/Slate)→ CRDT 转换操作指令 → WebSocket 同步 → 服务端广播 → 其他客户端 CRDT 合并 → 编辑器渲染更新 核心组件分工: 组件 作用 富文本编辑器内核 基于 ProseMirror(主流)封装,处理内容编辑、选区、格式渲染 CRDT 算法层 将编辑操作(插入/删除文本、修改格式)转换为无冲突的操作指令 WebSocket 通信层 实时同步客户端操作,断线重连后增量同步未发送的操作 本地操作队列/缓存 暂存未同步的本地操作,避免网络波动导致内容丢失 服务端协调层 接收操作指令、广播给其他客户端、生成操作日志/快照,用于历史回溯 二、核心原理:为什么能“无冲突协同”? 1. 核心算法:CRDT(无冲突复制数据类型) PingCode Wiki 未采用传统的 OT(Operational Transformation)算法(如 Google Docs 早期方案),而是选择了更易扩展的 CRDT(具体为 Yjs 框架,主流开源协同编辑库),核心优势: 去中心化冲突解决:无需服务端集中协调操作顺序,客户端本地即可合并不同用户的操作; 支持离线编辑:本地操作可暂存,联网后自动同步; 低性能损耗:操作指令体积小,同步效率高。 CRDT 核心逻辑(以文本编辑为例): 每个字符/节点被分配唯一的「位置 ID」(由客户端 ID + 时间戳 + 递增序列组成),而非传统的索引位置; 当用户插入文本时,生成包含「位置 ID、内容、操作类型」的指令; 其他客户端接收指令后,根据「位置 ID」确定字符的最终位置,而非基于当前文本长度计算索引(避免“张三插入第5位,李四删除第3位”导致的索引冲突); 删除操作仅标记「位置 ID 失效」,而非直接删除内容,确保多端合并时不丢失上下文。 2. 富文本编辑器适配:ProseMirror + Yjs 集成 PingCode Wiki 前端编辑器基于 ProseMirror 二次封装,核心适配点: ...

December 5, 2025 · 2 min · Theme PaperMod

Ubuntu 中快速安装 Oh My Zsh 完整教程

Oh My Zsh 是 Zsh 终端的增强框架,提供丰富的主题、插件和便捷的配置,能大幅提升终端使用体验。以下是 Ubuntu 系统下一键安装+优化配置的完整步骤: 一、前置准备:安装 Zsh(若未安装) Oh My Zsh 依赖 Zsh,先检查并安装: 1 2 3 4 5 # 1. 检查是否已安装 Zsh zsh --version # 2. 未安装则执行(Ubuntu 20.04/22.04 通用) sudo apt update && sudo apt install -y zsh 二、一键安装 Oh My Zsh 推荐使用官方脚本(两种方式任选其一): 方式 1:curl 安装(推荐) 1 sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" 方式 2:wget 安装(若 curl 未安装) 1 sh -c "$(wget -O- https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" 安装过程说明: 脚本会自动检测 Zsh,提示是否将 Zsh 设置为默认 shell(输入 y 确认); 安装完成后终端会自动切换到 Oh My Zsh 环境,默认主题为 robbyrussell; 若出现网络超时(GitHub 访问问题),可改用国内镜像: 1 2 # 国内 Gitee 镜像 sh -c "$(curl -fsSL https://gitee.com/mirrors/oh-my-zsh/raw/master/tools/install.sh)" 三、验证安装 1 2 3 4 5 6 7 # 1. 检查 Oh My Zsh 安装目录(默认 ~/.oh-my-zsh) ls ~/.oh-my-zsh # 2. 检查默认 shell 是否为 Zsh echo $SHELL # 输出 /usr/bin/zsh 则成功 # 3. 重启终端后,命令行前缀会显示 Oh My Zsh 标识(如 ➜ ~ ) 四、常用优化配置(必做) 1. 切换主题(推荐高颜值主题) Oh My Zsh 内置上百种主题,核心配置文件为 ~/.zshrc: ...

December 5, 2025 · 3 min · Theme PaperMod

关于 Svelte UI 20:基于 Svelte.js 的轻量级 UI 组件库

Svelte UI 20 是一款专为 Svelte/SvelteKit 打造的轻量级 UI 组件库,核心特点是无虚拟 DOM 开销、体积小、性能优,贴合 Svelte 「写更少代码,做更多事」的设计理念,适合构建轻量、高效的前端应用。以下从核心特性、快速上手、核心组件示例、定制化等维度详细介绍: 一、核心特性 极致轻量化:组件按需引入,无冗余代码,整体打包体积 < 50KB(gzip); 原生 Svelte 体验:基于 Svelte 原生语法开发,无额外运行时依赖,组件更新直接编译为原生 DOM 操作; 响应式设计:适配移动端/PC 端,内置响应式工具类; 主题定制:支持 CSS 变量/主题文件自定义,适配不同品牌风格; 无障碍支持:遵循 WAI-ARIA 规范,保障键盘导航、屏幕阅读器兼容性; TypeScript 友好:全组件类型声明,开发时类型提示完善。 二、快速上手 1. 安装(基于 SvelteKit 项目) 1 2 3 4 5 # npm npm install svelte-ui20 --save # pnpm(推荐) pnpm add svelte-ui20 2. 全局引入基础样式(src/routes/+layout.svelte) 1 2 3 4 <script> // 引入全局样式(包含重置样式、基础变量) import 'svelte-ui20/dist/styles/index.css'; </script> 3. 按需引入组件 无需额外配置,直接导入使用: ...

December 5, 2025 · 4 min · Theme PaperMod

[实践指南] 为 AI 代理构建实时知识库(基于 Airweave 实现)

1. 一段话总结 Airweave 是由 airweave.ai 开发的完全开源的 AI 代理跨应用与数据库上下文检索层,支持连接 30+ 应用、生产力工具、数据库及文档存储并将内容转化为可搜索知识库,通过 REST API 或 MCP 提供标准化搜索接口;提供托管服务(Airweave Cloud)和自托管(依赖 Docker 与 Docker Compose) 两种部署方式,支持 Python、TypeScript/JavaScript SDK,具备数据同步、实体提取、语义搜索等核心功能,技术栈涵盖 React/TypeScript(前端)、FastAPI(后端)、PostgreSQL 与 Qdrant(数据库)等,当前最新版本为 v0.7.19(2025年12月4日发布),遵循 MIT 许可证。 2. 思维导图(mindmap) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 ## **Airweave 基础信息** - 定位:完全开源的 AI 代理跨应用与数据库上下文检索层 - 开发者:airweave.ai - 核心目标:连接多源数据,转化为可搜索知识库,提供标准化接口 - 许可证:MIT 许可证 - 最新版本:v0.7.19(2025.12.4发布) - 代码仓库:GitHub(https://github.com/airweave-ai/airweave) ## **快速开始** - 托管服务:Airweave Cloud(直接使用) - 自托管步骤 - 前提:安装 Docker 与 Docker Compose - 步骤1:克隆仓库(git clone https://github.com/airweave-ai/airweave.git) - 步骤2:进入目录(cd airweave) - 步骤3:授权脚本(chmod +x start.sh) - 步骤4:运行脚本(./start.sh) - 访问地址:仪表盘 http://localhost:8080 ## **支持的集成(30+ 来源)** - 生产力工具:Asana、Gmail、Google Docs、Google Drive、Google Slides、Notion、Todoist、Trello 等 - 开发工具:GitHub、GitLab - 业务工具:Airtable、Attio、Confluence、Dropbox、Hubspot、Jira、Linear、Monday、Salesforce、Slack、Stripe、Zendesk 等 ## **使用方式** - 前端 - 访问地址:http://localhost:8080 - 功能:连接数据源、配置同步、查询数据 - API - Swagger 文档地址:http://localhost:8001/docs - 功能:创建连接、触发同步、搜索数据 - SDK - Python:pip 安装(airweave-sdk),支持集合创建、源连接添加、多种搜索模式 - TypeScript/JavaScript:npm/yarn 安装(@airweave/sdk),功能与 Python SDK 一致 ## **核心功能** - 数据同步:30+ 来源同步,最小化配置 - 数据处理:实体提取与转换流水线 - 架构设计:多租户架构,支持 OAuth2 - 更新机制:基于内容哈希的增量更新 - 搜索能力:语义搜索、混合搜索(语义+关键词)、带查询扩展与重排序的搜索、带时效性偏向的搜索 - 结果输出:支持原始结果返回、AI 生成答案返回 - 数据管理:数据变更版本控制 ## **技术栈** - 前端:React/TypeScript + ShadCN - 后端:FastAPI(Python) - 数据库:PostgreSQL(元数据)、Qdrant(向量数据) - 任务调度:Temporal(工作流编排)、Redis(发布/订阅) - 部署:Docker Compose(开发环境)、Kubernetes(生产环境) ## **贡献与社区** - 贡献指南:参考 CONTRIBUTING.md - 社区渠道:Discord(互助与功能讨论)、GitHub Issues(bug 反馈与功能请求)、Twitter(更新跟进) 3. 详细总结 一、Airweave 核心定位与价值 Airweave 是由 airweave.ai 开发的完全开源的上下文检索层,专门服务于 AI 代理,核心价值在于打破应用与数据库的数据壁垒: ...

December 5, 2025 · 3 min · Theme PaperMod

关于 Wing FTP Server 搭建 FTP 服务器的入门教程

一、核心结论 Wing FTP Server 是一款轻量易操作的 FTP 服务器软件,Windows/macOS/Linux 均支持,新手通过“下载安装→创建域名→添加用户→配置权限→测试连接”5步即可完成基础搭建。 二、关键步骤(以 Windows 系统为例) 1. 下载与安装软件 官网下载最新版 Wing FTP Server(有免费版,满足个人/小型团队使用)。 安装时默认下一步即可,勾选“创建桌面快捷方式”方便后续操作。 2. 创建 FTP 域名(核心配置) 打开软件,左侧导航栏点击“Domains”→“Add Domain”。 填写域名名称(自定义,如“MyFTP”),端口默认 21(FTP 标准端口,无冲突建议保留)。 根目录选择本地文件夹(如 D:\FTPFile),作为 FTP 服务器的文件存储路径,点击“OK”保存。 3. 添加 FTP 访问用户 选中已创建的域名→右侧“Users”→“Add User”。 填写用户名(如“ftpuser”)和密码,勾选“Enable Account”激活账号。 切换到“Dir Access”标签,选择根目录,设置权限(如“Read+Write”读写权限,根据需求调整)。 4. 关闭防火墙拦截(重要) 进入 Windows 防火墙设置,允许 Wing FTP Server 程序通过防火墙(包括公用/专用网络)。 若需外网访问,需在路由器中做“端口映射”(映射本地 IP + 21 端口)。 5. 测试 FTP 连接 本地测试:使用 FileZilla 等 FTP 客户端,输入服务器 IP(本地为 127.0.0.1)、用户名、密码,端口 21,连接成功即可上传/下载文件。 外网测试:用外网设备输入服务器公网 IP,重复上述连接步骤,成功则搭建完成。 三、新手注意事项 免费版支持最多 3 个并发连接,商用需升级授权。 避免使用默认端口 21 暴露在外网(可修改为 1024+ 端口,提升安全性)。 根目录建议单独创建文件夹,不要直接用系统盘(如 C 盘),防止误操作导致系统文件风险。

November 24, 2025 · 1 min · Theme PaperMod

Vue 项目作为子应用接入乾坤(qiankun)框架改造笔记

一、改造核心目标 将独立的 Vue 项目(Vue2/Vue3 均适用)改造为 qiankun 可识别的子应用,实现: 主应用通过域名/路径无感知嵌入子应用 主-子应用间通信、路由隔离 样式隔离、资源加载不冲突 支持独立运行(改造后仍可单独启动调试) 二、前置准备 环境要求: 主应用已集成 qiankun(参考 qiankun 官方文档) 子应用 Vue 版本:Vue2(需配合 vue-router 3.x)、Vue3(需配合 vue-router 4.x) 打包工具:Webpack(Vue CLI 默认)或 Vite(需额外配置) 关键概念: 子应用需暴露 bootstrap、mount、unmount 三个生命周期钩子 路由需配置为基于主应用分配的基础路径(如主应用通过 /vue-app 访问子应用,则子应用路由 base 为 /vue-app) 资源需支持跨域访问(主应用加载子应用静态资源时触发 CORS) 三、分步骤改造(Vue CLI 项目,Vue2/Vue3 通用) 步骤 1:安装 qiankun 依赖(子应用) 子应用需引入 qiankun 的辅助依赖,用于暴露生命周期: 1 2 3 # Vue2/Vue3 均适用 npm install qiankun --save # 或 yarn add qiankun 步骤 2:配置子应用入口文件(main.js) 核心是暴露 qiankun 要求的三个生命周期钩子,同时兼容独立运行模式。 ...

November 23, 2025 · 7 min · Theme PaperMod

轻松去除 Alist 端口号

轻松去除Alist端口号,核心是通过反向代理配置实现,无需复杂操作,能显著优化网络访问体验。 一、核心原理 利用Nginx或Caddy等反向代理工具,将域名直接映射到Alist服务的“IP:端口”。 访问时只需输入域名(如alist.example.com),代理工具会自动转发请求到对应端口,实现端口号隐藏。 二、简单操作步骤(以Nginx为例) 安装Nginx:通过服务器包管理工具快速安装(如CentOS用yum install nginx,Ubuntu用apt install nginx)。 配置反向代理:编辑Nginx配置文件(通常在/etc/nginx/conf.d/目录下),添加如下内容: 1 2 3 4 5 6 7 8 9 server { listen 80; server_name alist.example.com; # 替换为你的域名 location / { proxy_pass http://127.0.0.1:5244; # 替换为Alist实际的IP:端口 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } 重启Nginx:执行命令systemctl restart nginx,使配置生效。 解析域名:在域名服务商处,将域名解析到服务器IP,等待解析生效后即可通过域名访问Alist。 三、注意事项 确保服务器80端口(HTTP)或443端口(HTTPS)未被占用,且已在防火墙放行。 若需HTTPS加密访问,可通过Let’s Encrypt申请免费证书,在Nginx配置中添加SSL相关参数。 以下是 Alist 端口号隐藏的 Nginx 完整配置文件(含 HTTP 自动跳转 HTTPS + 免费 SSL 证书配置),直接复制替换参数即可使用,无需额外修改核心逻辑: ...

November 23, 2025 · 3 min · Theme PaperMod