JACIN Blog

深度的 AI 应用开发者

专注 AI 应用开发、Python 后端与工程实践,持续记录大模型落地、工具构建与真实项目经验。

183篇已发布
主题索引
查看全部分类
全部文章
183
利用 kong 进行流量负载均衡处理
容器与云原生
5 分钟

利用 kong 进行流量负载均衡处理

这篇笔记聚焦用 Kong Upstream 为 Kubernetes 中的后端副本做流量分发,场景是 3 个 Pod 暴露在 10.42.0.20 到 10.42.0.22,并通过 Target 与 Service 组合交给 Kong 选择实际后端。内容先区分 Round Robin、Least Connections 与 Consistent Hashing:无状态标准 API 适合轮询,耗时较长的 RAG 向量计算更适合最小连接数,而带本地缓存、用户 Session 或上下文依赖的服务则需要哈希分流来保持请求落点稳定。配置层面强调 Upstream 模式与直连模式的差异,Service Host 指向 upstream 名称后,Service Port 即使写 80 也不会决定最终端口,Kong 会根据上游 Target 中的地址与端口转发到具体的 10.42.0.x:8006。文章还用取余哈希和一致性哈希对比解释扩缩容影响:简单取模在节点数量变化时会导致大量请求重新分布,而 Kong 的一致性哈希通过环形空间顺时针查找,只让新增或减少节点附近的一小段流量发生漂移。对于依赖缓存命中率的 RAG 服务,这种机制能降低扩容、缩容或 Pod 变更时的缓存失效范围,避免瞬时流量冲击。最后对 Target 的 weight 做了关键澄清:在一致性哈希下它更像虚拟节点数量,权重越高,在哈希环上的“分身”和覆盖范围越多,从而获得更大比例的请求,适合需要按 Pod 能力差异分配流量的后端服务。

服务器与部署
12 分钟

部署 Kong

这是一份在 Kubernetes 中部署 Kong 网关的配置笔记,重点放在 hostNetwork 模式下如何同时兼顾网关性能、本机 PostgreSQL 连接和外部访问安全。配置先用 Secret 保存 pg_password,再通过 Job 执行 kong migrations bootstrap 初始化数据库,随后在 Deployment 中设置 KONG_DATABASE、KONG_PG_HOST、KONG_PG_USER、KONG_PG_DATABASE 等环境变量,让 Kong 直接连接宿主机 127.0.0.1:5432 上的 postgres 数据库。网关容器启用 hostNetwork 并配合 ClusterFirstWithHostNet,代理端口只开放 0.0.0.0:8000,而 Admin API 和 Admin GUI 分别限制在 127.0.0.1:8001 与 127.0.0.1:1337,避免管理端口被公网直接访问。由于 Kong UI 默认没有账号体系,文章给出 Nginx 反代方案,通过 auth_basic 和 .htpasswd 为 kong-ui 域名增加访问保护,并将 /manager-api/ 转发到本地 8001,根路径转发到本地 1337,其中 proxy_pass 末尾斜杠被特别标注为关键细节。另一组 Nginx 配置用于 api 域名,将外部 HTTPS 请求转发到本地 8000 的 Kong Proxy,同时保留真实 IP、WebSocket Upgrade、关闭代理缓冲和上传大小设置。适合需要在单机或混合 Docker/K8s 环境中部署 Kong、使用本机数据库并通过 Nginx 统一暴露 UI 与 API 的后端和运维读者参考。

容器与云原生
3 分钟

K8s pod 副本与 Uvicorn Workers

这篇笔记围绕 FastAPI/Uvicorn 服务在 Kubernetes 中的并发扩展方式,区分了 Pod 副本和 Uvicorn Workers 的层级差异:前者是由 K8s 管理的容器级横向扩展,后者是在单容器内由 Python/Uvicorn 管理的进程级纵向扩展。正文强调二者本质上都会启动独立 Python 进程,因此无论是单 Pod 多 Worker,还是多 Pod 单 Worker,都可以绕开 GIL 对单解释器线程并行的限制,实现多核并行。差异主要落在资源隔离、负载均衡和故障边界上:多 Worker 会共享同一个容器的 CPU 与内存限制,由 Uvicorn 主进程分发请求;多 Pod 则由 K8s Service 做网络层负载均衡,并可为每个 Pod 设置独立资源配额。单 Pod 多 Worker 的优势是启动快、内存更省、进程切换开销较小,但在 2 核 CPU 开 4 个 Worker 这类配置下会发生资源争抢,容器 OOM 时所有 Worker 会一起退出。多 Pod 单 Worker 的优势是每个进程拥有更明确的资源保障,单个 Pod 死锁或内存泄漏只损失部分服务能力,并可由 K8s 自动重启,适合追求稳定性、容灾和大规模水平扩展的部署。读者可以据此判断在成本、启动速度、资源利用率与故障隔离之间如何取舍,而不是简单把副本数和 Worker 数视为等价参数。

容器与云原生
1 分钟

关于“容器与云原生”类别

“容器与云原生”类别用于归纳与容器化、云原生体系及相关工程实践有关的内容,并为后续文章归类提供一致的判断依据。该类别的重点不只是收纳零散技术笔记,而是明确它适合承载哪些主题、解决哪些分类场景,以及与站内既有类别之间应如何区分。其准则需要说明使用该类别的理由、覆盖范围、典型话题边界,并判断是否存在与其他分类或子分类合并的可能。读者可以据此理解该分类的定位:它面向需要查找容器、平台化、部署运行和云原生相关知识的技术内容,同时强调分类边界的清晰性,避免相近主题被重复放置或分散管理。

部署 k8s 与配置项目
容器与云原生
14 分钟

部署 k8s 与配置项目

这份笔记围绕在单机环境中用 k3s 搭建 Kubernetes 并部署实际项目展开,先从 /root/k8s/config.yaml 的基础配置入手,记录了设置 token、tls-san、API 端口、kubeconfig 权限、禁用默认 Traefik 以及把数据目录固定到 /root/k8s/data 的安装方式。可视化管理部分使用 Portainer 官方 manifest 部署到 portainer 命名空间,通过 NodePort 暴露 9000 与 9443,并提醒 Portainer 需要 HTTPS 访问、首次初始化超时后可删除 Pod 触发重建。文章随后给出 Nginx 反向代理到本机 30779 端口的配置示例,包括 SSL、WebSocket 升级头、真实 IP 传递、关闭代理缓冲和上传大小限制。项目部署部分强调用 YAML 与环境文件管理应用,而不是依赖 UI 表单,示例中通过 kubectl create secret generic 从 ragapi.env 创建 Secret,再在 Deployment 中用 envFrom 注入环境变量,并配置私有镜像拉取、RollingUpdate 滚动更新和 Service 的 NodePort 暴露。文中还用类比区分 ConfigMap 与 Secret、Deployment 与 Service:前者分别承载非敏感配置和敏感信息,后者分别负责 Pod 生命周期与流量入口,解释了为什么更新 Pod 时 Service 的地址和端口可以保持稳定。最后整理了一组从 Docker 使用习惯迁移到 kubectl 的常用命令,覆盖查看 Pod/Service/Deployment、跟踪日志、查看资源占用、进入容器,以及通过 rollout restart 或删除 Pod 实现重启,适合刚把个人项目迁移到 k3s 的后端开发者和运维学习者参考。

k8s
K8s 简单介绍
容器与云原生
13 分钟

K8s 简单介绍

这是一篇面向 Docker 使用者的 Kubernetes 入门笔记,核心在于把 K8s 理解为负责管理和调度容器的编排系统,而不是 Docker 的替代品:Docker 负责打包和运行,K8s 通过声明式期望状态维持副本、自愈、伸缩和资源抽象。文章用对照表梳理 Namespace、Pod、Deployment、StatefulSet、Service、Ingress、ConfigMap/Secret、PV/PVC 等常见对象,并解释 Pod 是 K8s 的最小调度单位,同一 Pod 内容器共享 IP、localhost 通信和存储卷,因此端口不能冲突。重点说明 Pod 具有一次性生命周期,重建后 IP 会变化,所以需要 Service 作为稳定访问入口,并依赖 DNS 将服务名导向当前可用的后端 Pod。Namespace 用于隔离开发、测试、生产等环境,Ingress 则作为七层反向代理处理域名、路径和 HTTPS,相比 NodePort 更适合对外暴露 Web 服务。存储部分通过 PV 与 PVC 区分真实存储资源和使用申请,说明它如何让 Pod 跨节点漂移时仍能挂载到持久化数据。文章最后区分 Deployment 管理无状态应用、StatefulSet 管理数据库等有状态应用,并提醒滚动更新只保证新请求入口平滑切换,长连接仍会在宽限期结束或旧 Pod 退出时断开,需要应用处理 SIGTERM 和客户端重连。

k8s
使用 attu 创建向量数据库
AI 大模型开发
8 分钟

使用 attu 创建向量数据库

这篇操作笔记围绕在 Attu 中创建 Milvus Collection 展开,把 RAG 知识库建表时容易混在一起的字段设计、索引配置和检索参数拆开说明。正文先以 FloatVector(1024)、VarChar text 和 JSON metadata 为核心字段,解释向量维度必须与 Embedding 模型输出一致,原文文本用于最终回填给 LLM,元数据则服务于按文档、时间等条件做标量过滤。检索部分重点说明 COSINE 余弦相似度适合文本语义搜索,并区分相似度越大越相关、距离或 radius 越小越严格的参数含义,避免在 Milvus 查询时误解阈值方向。索引配置选择 HNSW,并解释 M=16 与 efConstruction=128 分别影响邻居连接数、内存占用、构建速度和查询准确率。文章还对比 Collection 与 Partition 的层级关系:前者类似表并定义统一 Schema,后者是在集合内按业务或时间切分数据,用于缩小搜索范围和控制内存加载。最后补充 Bounded 一致性在写入可见性与吞吐之间折中,以及 Dense、Sparse 和 Hybrid Search 如何把语义检索与关键词权重结合起来提升召回,适合正在搭建 Milvus RAG 数据库的开发者参考。

AI 大模型开发
11 分钟

RAG 架构的认识

这篇笔记把 RAG 从离线索引到在线回答拆成一条完整工程链路,关注的不是概念定义,而是每个环节如何影响召回准确率、响应速度和幻觉控制。数据准备部分强调先做 ETL 清洗,再选择合适的分块策略,并通过元数据记录来源、页码、日期、章节等结构化信息,让后续检索既能依赖向量相似度,也能进行更可靠的过滤。文章特别提醒入库和查询必须使用一致的 Embedding 模型与参数,并用 HNSW 解释向量索引为什么会带来“入库慢、查询快”的取舍。在线阶段则覆盖查询改写、子问题拆解、混合检索和 RRF 融合,说明向量检索适合语义相近内容,而关键词检索更适合型号、人名、缩写等精确信息。排序与生成部分进一步引入 Rerank、阈值过滤和上下文去噪,用更高成本的精排模型提升候选 Chunk 质量,并在低相关度时返回“不知道”以避免强行编造。最后通过 Prompt 约束和引用溯源把答案限制在检索上下文内,适合正在搭建或优化知识库问答系统、希望从“能检索”推进到“可解释、可调优、可追溯”的 AI 应用开发者。

rag
ping 延迟、三次握手、 TLS/SSL 握手 延迟
计算机网络
6 分钟

ping 延迟、三次握手、 TLS/SSL 握手 延迟

这篇笔记围绕网络请求中的 RTT 成本展开,用 ping 返回的 time=44ms 说明它表示从发出到收到回复的完整往返时间,系统不会把结果除以二来显示单程延迟。正文先从广州到北京的光纤传播估算切入,指出即使理想直连往返约 22ms,真实链路还会受到骨干路由跳数、线路绕行以及电光转换等因素影响,因此 44ms 中包含明显的网络损耗。随后文章用时间线拆解 TCP 三次握手,强调真正阻塞客户端继续发送数据的是等待 SYN-ACK 返回的 1 个 RTT,第三次 ACK 不必等服务器收到后才进入下一阶段。对于 HTTP 请求,第三次 ACK 可以和 HTTP 数据捎带发送,因此一次未加密请求可近似理解为 TCP 建连 1 个 RTT 加请求响应 1 个 RTT。对于 HTTPS,请求在 TCP 之后还要完成 TLS/SSL 协商,TLS 1.3 通常再消耗 1 个 RTT,TLS 1.2 可能更多,所以 HTTPS 最快约为 3 个 RTT 加服务器处理时间。文章也说明四次挥手通常不计入一次请求的可感知耗时,因为业务代码拿到 response 时关键路径已经结束,断开连接多在后台完成,适合需要估算接口首包延迟、理解 TCP/TLS 建连成本的后端和网络学习者阅读。

Python 开发
4 分钟

Python 异步编程 async 处理规则

这篇笔记围绕 Python 异步服务中哪些操作该 await、哪些不能指望 async 加速这一边界展开,适合在 FastAPI 等事件循环模型下处理接口、数据库、缓存、对象存储和本地计算任务的开发者参考。文章先强调网络 I/O 本身不消耗 CPU,调用 OpenAI、数据库、Redis、S3 等等待型操作时,应使用 httpx、asyncpg、motor 等异步库并显式 await,让主线程在等待网络返回时继续处理其他请求。随后区分 CPU/内存密集任务:Pandas 处理 Excel、视频转码、哈希计算或超长循环即使写进 async def,也仍会占用主线程并卡住 Event Loop,协程语法不会把单线程计算变成并行计算。针对这类阻塞,文章给出两类“扔到池子里”的处理方式:优先用 asyncio.to_thread 或线程池释放事件循环,尤其适合 Excel 解析、图片处理和许多 Pandas/Numpy 操作,因为其底层 C 实现可能在重计算或 I/O 时释放 GIL。对于纯 Python 重计算,文中建议使用 ProcessPoolExecutor 绕开 GIL,但同时提醒进程创建、序列化传输和无法共享内存都会带来更高成本。最后还提供了一个 AsyncWrapper 示例,用 __getattr__ 将同步厂商 SDK 方法统一包装成 await asyncio.to_thread(...) 的异步调用形式,用较小线程切换开销换取异步服务对旧同步接口的兼容。

Git
4 分钟

自用 VPS 配置 github action self-hosted runner

这份配置记录聚焦在自用 VPS 上部署 GitHub Actions self-hosted runner,并按“中心安装包 + 项目独立运行目录”的方式管理多个仓库。目录设计把 runner 压缩包统一放在 `/root/github-runners/package/actions-runner.tar.gz`,只需从 GitHub releases 下载一次,后续项目如 `go-react-prod`、`new-api` 都从该位置解压,避免重复下载和混用运行文件。首个项目配置时,需要创建专属目录、解压安装包,并在以 root 用户运行的 VPS 上先设置 `RUNNER_ALLOW_RUNASROOT=1`,再执行 `config.sh` 绑定仓库;如果 GitHub 页面生成的 token 过期,则要重新复制新的 token。运行方式上不建议直接执行 `./run.sh`,而是通过 `./svc.sh install root`、`./svc.sh start` 和 `./svc.sh status` 将 runner 安装为 root 用户下的系统服务,保证后台持续运行。新增仓库时重复建目录、复用压缩包、使用对应仓库 URL 和新 token 配置,再安装并启动服务即可。最后在 GitHub Actions workflow 中指定 `runs-on: self-hosted`,任务就能调度到这台 VPS,适合希望用个人服务器承接构建或部署流程的开发者。

AI 大模型开发
7 分钟

CPU 跑 Rerank 太慢?一个脚本开启 INT8 量化,性能大幅度提升!

面向企业级 RAG 系统中在 CPU 服务器部署 HuggingFace text-embeddings-inference Rerank 的场景,内容聚焦默认 FP32 ONNX 模型推理慢、CPU 利用率不高的问题。文章先用 FP32 与 INT8 的数据宽度差异解释瓶颈来源:全精度权重占用更多内存带宽和计算资源,而 Rerank 更关注排序相对结果,适合通过量化降低推理成本。随后结合 AMD EPYC、Intel Xeon 等现代 CPU 的 AVX-512/VNNI 能力,说明 INT8 在 SIMD 并行吞吐和内存占用上的优势,并给出理论上更高并发处理能力的原因。实践部分提供了基于 optimum.onnxruntime 的动态量化脚本,将 bge-reranker-v2-m3 的 FP32 ONNX 文件转换到 quantized 目录,并使用 avx512_vnni 配置面向 CPU 推理优化。脚本中特别处理了 TEI 启动所需的 tokenizer、config 等文件复制,以及将 model_quantized.onnx 重命名为 model.onnx 的兼容性细节。最后只需在 docker-compose.yml 中把 rerank 模型挂载路径切换到 quantized 目录,TEI 镜像无需更换即可加载 INT8 模型,适合需要在现有 CPU 资源上提升 Rerank 吞吐的 RAG 开发和运维人员参考。

文章归档
183