Technology
6450 discoveries · Hand-picked discoveries from the open web, newest first.
-
Flyer:基于FastAPI的轻量级API开发框架
概述 我们经常会听到“不会开发的运维不是个好运维”,确实在运维工作当中,娴熟的开发经验能让运维工作如鱼得水,事半功倍!高级的运维除了需要精通 Shell 脚本编程之外,最好还需要掌握一门高级语言,比如 Python、Golang、PHP、Lua 等。高级语言除了可以解决一些更复杂的运维场景,还可以帮助我们更好的理解业务,做好业务运维,毕竟知己知彼才能百战不殆。 经常看到很多运维同学写接口通常是基于 Flask,只用一个脚本一撸到底,完全没有框架的概念,总体给人的感觉比较粗糙简陋。本文分享一个我个人基于 FastAPI 框架设计的轻量级 API 开发框架,能够应付绝大部分的业务运维的后台 API 场景,这个框架我取名为 Flyer,意味着轻量且快速。 Flyer API 开发框架 框架特性 继承 FastAPI 所有特性,包括高性能、自带 Swagger/ReDoc 文档、易开发等,详见:( FastAPI (tiangolo.com) ) 拥抱云原生,所有参数都可以通过七彩石/环境变量来自定义,代码中也可以非常方便的获取指定环境变量的值 鹅厂内部版本集成了七彩石、智研日志汇、监控宝等各种研效库(外部版本已剥离) MySQL/Redis/Kafka 等开源组件已默认对接,可以开箱即用 支持记录全局请求/被请求流水日志及耗时等监控特性 可以快速开启简单的 BasicAuth 鉴权等 更
张戈博客 · ZH
-
SQLAlchemy因密码含有@符号连接MySQL失败
最近新来的实习生在重构一个我入职时开发的老系统。这个系统之前用的是 Python twisted 框架,这次希望换成 FastAPI,也就是我上一篇文章分享的 Flyer 开发框架 。 小伙子很给力,自学了几天 FastAPI 和 Flyer 就开工了,结果用 Flyer 连接 MySQL 时报错: 问题现象 1 sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (2003, "Can't connect to MySQL server on 'xxxx@x.x.x.x' ([Errno -2] Name or service not known 报错原因一眼就能看出来: 密码里有一个 @ 符号 ,导致 @ 之后的内容被当成了数据库主机地址。 解决办法:密码做 URL 转义 用 urllib.parse.quote_plus 对密码转义即可: 1 2 3 4 from urllib.parse import quote_plus password = quote_plus ( "your_p@ssw0rd" ) # 再把转义后的密码拼进连接串 为什么我的老项目没这个问题 奇怪的是,我之前有个基于 Flyer 的项目复用了同一个数据库、同样的账号密码,却从没出现过这个问题,所以我一度笃定是 SQLAlche
张戈博客 · ZH
-
gRPC开发过程中遇到的问题记录
最近我在改造手头负责的一个 HTTP Restful API 服务,集成对 gRPC 协议(在鹅厂叫 tRPC,是 gRPC 的本土衍生版本)的支持。由于是从 0 学习这个协议,因此也踩了不少坑,这里用一篇文章来记录下,希望可以帮助到同样从 0 学习 gRPC 的朋友。 列表参数赋值 老的 Rest 接口中,大量用到了列表参数,看了下 pb 协议,给这个参数定义如下: 1 2 3 message Foo { repeated string Bar = 1 ; } 在 Python RPC 客户端调用测试时,按照经验,传参如下: 1 2 req = pb . Foo () req . Bar = [ "a" , "b" ] 结果赋值就报错了: 1 AttributeError: Assignment not allowed to repeated field "Bar" in protocol message object. 经过一番搜索,最终发现 Python 客户端应该如下赋值列表参数: 1 2 3 req = pb . Foo () bar_list = [ "a" , "b" ] req . Bar . extend ( bar_list ) 这样就可以正常赋值了,但是总觉得这个设计太绕了,直接赋值不行么?总体来说,gRPC 还是偏编译型语言的设计的,在 Python 这种解
张戈博客 · ZH
-
FastTTS:支持私有化部署和源阅读无缝对接的语音合成服务
概述 长话短说,最近发现微软的语音服务莫名扣费了,然后看着国内云服务动辄几千上万的语音合成服务资源包,一阵苦涩。搜了下,发现挺多基于 edge-tts 的白嫖项目,试用了下确实能用,就是和源阅读对接的体验有待提高。 因此决定自己封装一个更适合源阅读 APP 的语音合成服务,以下是介绍,有需要的直接拿。 项目介绍 本项目基于 Edge-TTS 和 FastFlyer 开发框架,可以直接私有化部署提供语音合成服务,支持和源阅读 APP 无缝对接。 体验地址(账号密码:guest / guest): 在线合成 在线调试 项目地址: FastTTS 框架介绍 FastFlyer 是基于 FastAPI 设计的轻量级 API 开发框架。在 FastAPI 优异特性的基础上集成了一系列开箱即用的组件,包括 Redis、MySQL、Kafka 等。采用 SDK 接入方式,内置脚手架代码生成等辅助工具,让研发人员只需要专注于业务逻辑的实现,真正开箱即用! 注:更多框架介绍请阅读: FastFlyer 快速部署 1 docker run --name fasttts -d -p 8080:8080 jagerzhang/fast-tts 成功启动后,访问: http://<host>:8080/speech/docs 可以看到 Swagger 工具页面。 简单鉴权 如果需要外网访问,建议开启接口鉴权
张戈博客 · ZH
-
FastFlyer:基于FastAPI的轻量级API开发框架
概述 很早前分享过一个开发框架 Flyer,这些年一直在用,也攒了不少痛点:框架代码和业务代码耦合在一起,想升个级就得挨个项目改一遍,非常痛苦。 所以这次重写了一版,取名 FastFlyer ——基于 FastAPI 的轻量级 API 开发框架。最大的变化是把框架做成了 SDK ,和业务代码彻底隔离,装个包就能用,升级也只是换个版本号的事。 项目地址: https://github.com/jagerzhang/fastflyer 主要特性 SDK 即装即用 :框架以 SDK 形式提供,与业务代码隔离,不再有「框架版本难以升级」的问题 自动生成项目骨架 :一条命令生成标准目录结构和演示应用,开箱即用 自动加载应用 :自动加载 app/ 目录下符合规范的应用,只需暴露名为 router 的路由对象 自带接口文档 :启动即有 SwaggerUI 和 Redoc 性能足够用 :单核单进程空载 9000+ QPS ,基本能覆盖绝大部分运维场景 快速开始 安装 SDK 1 pip3 install --upgrade fastflyer 这一步是可选的,主要为了让 IDE 能正常提示。 创建项目 1 2 3 4 5 export new_project = myproject mkdir -p /data/ ${ new_project } && cd /data/ ${ new_proje
张戈博客 · ZH
-
Beggar:让 CodeBuddy 多 Agent 协作研发成本直降 90% 的开源套件
一套可复用的多 Agent 配置方案,通过模型差异化分工 + 双 Reviewer 交叉审查 + Review Gate 自动升级,在保证质量的前提下大幅降低 AI 编程成本。 为什么需要 Beggar 如果你正在用 CodeBuddy Code 做 AI 辅助开发,大概率遇到过这样的困境: 成本焦虑 :所有任务都用最强模型?太贵。都用便宜模型?质量没保障。 单模型盲区 :同一个模型写代码又审代码,自己的 bug 自己审不出来。 编排混乱 :Agent 之间职责不清,Leader 直接下场写代码,角色边界形同虚设。 缺乏质量兜底 :审查不过怎么办?升级谁?几轮后还不过呢?Beggar 的解决思路很直接—— 把"用哪个模型做哪件事"这件事工程化 。 核心设计:四层成本优化 1. 模型分层——不是所有任务都需要最强模型 Beggar 把研发流程拆成 9 个角色,每个角色匹配能力够用的最便宜模型: 角色类型 代表 Agent balanced 预设模型 倍率 编排调度 Leader deepseek-v4-pro x0.16 方案设计 Architect glm-5.2 x0.79 复杂编码 Coder-Senior deepseek-v4-pro x0.16 常规编码 Coder-Standard deepseek-v4-flash x0.06 简单编码 Coder-Lite hy3
张戈博客 · ZH
-
博客重构手记:从 WordPress 到 Hugo 静态化
起因:其实挺惭愧的 这个博客荒废挺久了。 工作越来越忙,更新从一周一篇变成一月一篇,再到后来大半年都想不起来登录。偶尔上去看一眼,后台堆着一堆插件更新提示,我一般直接关掉——不是不想管,是真抽不出时间,而且心里清楚,一个没人维护的 WordPress 本身就是个隐患。 真正让我下决心的是前阵子 PHP 又爆了个漏洞。看到消息的时候我第一反应不是“赶紧升级”,而是“算了,换个不需要 PHP 的方案吧”。 为什么不直接升级 也不是没想过就地升级。但盘了一下现状就放弃了: WordPress 版本落后不少,主题是好几年前改过的,插件一堆 PHP 环境也要跟着升,升完还得一个个测兼容性 服务器上的 MySQL、Nginx 配置都是当年手动调的,动一个地方心里没底 最关键的是,就算全部升级完,得到的还是一个需要我一直维护的动态站。而我恰恰最缺的就是“一直维护”这四个字。 静态化就很对症:没有 PHP、没有数据库、没有后台,生成完就是一堆 HTML。攻击者连个入口都找不到。平时我只管写 Markdown,剩下的交给 Git。 文章迁移:467 篇 数据库里躺着的家当比我以为的多不少: 1 2 3 4 5 6 post publish 467 篇(另有 8 篇草稿) page 8 个 attachment 1745 个 comment 20309 条(13.8MB,全库最大的一张表) 分类 13
张戈博客 · ZH
-
把 Waline 迁到 EdgeOne KV,折腾了几轮才算完
博客最近刚做完 静态化 ,全站搬到 EdgeOne 之后,唯一还需要服务端的就剩评论了:后端跑在 Vercel 上,数据存在 Neon。 等于站子在一个平台、评论在另一个平台。没出过什么事,也没什么非搬不可的理由,主要是想着既然都上 EdgeOne 了,干脆一并挪过来,监控、日志、部署、账单收在一处,比跨两个平台来回切省心。函数用 Hono 写,数据落在 EdgeOne KV,对外域名继续用 api.zhangge.net 。 最终 14,675 条评论、474 条 Counter、1 个用户都搬过来了。过程比预想的麻烦,麻烦的地方基本都不是“不会配”,而是“看起来已经好了”。 接口返回 200,浏览器却不让你读;后台能登录,评论列表却是空的;数据导进去了,时间全是 1970 年;批量导入把批次改小了还是写不完;类型检查过了、部署也过了,接口却是 404。 本文纯属折腾记录,中间有大量试错过程,只想抄作业的可以直接跳到文末的「回头看」。 起因:站子都搬过来了,评论别单独留在外面 念头其实很简单:站子已经全静态跑在 EdgeOne 上,评论却还挂在另一个平台的另一个数据库里,等于每次要看点什么都得切一次地方,没什么必要。正好 EdgeOne 有 KV 存储,Waline 的服务端又能跑在 Edge Function 上,看着是个顺手的事。 当时我评估下来只剩两个不确定项:一是 Wal
张戈博客 · ZH
-
Memory Machines: The Evolution of Hypertext
— 摘自 Belinda Barnet 《Memory Machines: The Evolution of Hypertext》, 来自 Dynamicland 的推荐书单 这些页面提出了一个愿景,既简单又统一,气势宏大:这是一个关于相互连接的
夜行人 · EN
-
Mr. Wilson's Cabinet Of Wonder
— 摘自 Lawrence Weschler 《Mr. Wilson’s Cabinet Of Wonder》, 来自 Dynamicland 的推荐书单 看见就是忘记所见之物的名字 对桑纳本而言,记忆是一种幻觉。遗忘,而非记得,是所有经验的
夜行人 · EN
-
荒野中的认知
— 摘自 Edwin Hutchins 《Cognition in the Wild (荒野中的认知)》, 来自 Dynamicland 的推荐书单 在环境中个体所遇到的问题和解决办法都是由⽂化建构的,⽽且没有⼈能够独
夜行人 · EN
-
From Memex to Hypertext
— 摘自 James M Nyce, Paul Kahn 《From Memex to Hypertext》, 来自 Dynamicland 的推荐书单 在论述 Memex 时,布什主张计算机器和机器智能将会在人的智力生活中占有重要地位。
夜行人 · EN
-
Bootstrapping
— 摘自 Thierry Bardini 《Bootstrapping》, 来自 Dynamicland 的推荐书单 与其从技术对象的个体性出发,甚至从其非常不稳定的特殊性出发,试图在这种个体性或特殊
夜行人 · EN
-
孩子是如何学习的
— 摘自 John Holt 《How-Children-Learn (孩子是如何学习的)》, 来自 Bret Victor 的推荐书单 正是在他们上学之前,孩子们最有可能做到最佳的学习。
夜行人 · EN
-
[译] "to program is to understand" -- 记录一段发生在 MicroBlocks 社区中围绕 AI 与编程的讨论
前言 Raketenmann 在 MicroBlocks 社区中抛出了关于 “今天我们应该如何教授软件工程?” 的疑问, 引起了 Bernat Romagosa, John Maloney 和 klmi 的讨论. 本文记录了这段精彩的讨
夜行人 · EN
-
如果你不能外包你的理解,你咋掌控AI写的那一大坨代码
上一篇文章的结尾,我留了一个话题。 我引用了那句话: "你可以外包你的思考,但是你不能外包你的理解。" 有读者在后台问我:道理都懂,可 AI 一天给我生成的代码,比我自己一年写的都多。思考我可以外包给 AI,理解我肯定要自己消化——但是消化也得有时间和精力啊。生成是光速,理解是步行,AI拉的是一大坨,理解缺是要细嚼慢咽,这道题怎么解?
鸟窝 · ZH
-
MySQL 和 PostgreSQL 中的时间戳:Go 和 Java 访问时的坑
同样叫 timestamp,MySQL 和 PostgreSQL 的含义完全不同:一个是绝对时刻,一个是墙钟时间,正好相反。踩坑重灾区,也是面试高频题。这篇文章把两者放在一起对齐比较,并且提供了 Go 语言和 Java 语言应用访问数据库时间类型字段的坑。 前四节讲数据库侧(类型语义与对照),后四节讲应用侧(时间从应用流到列的链路、Go 与 Java 驱动的行为、可直接抄的配置清单)。 一、先分清两种语义 一切混乱的根源是"时间"这个词同时指两样东西: 绝对时刻(instant) :世界上唯一的一个瞬间,比如 2026-09-05 00:00:00 UTC 。下单、日志、消息发送用它。任何时区看到的都是同一个点,只是显示不同。 墙钟时间(wall time) :挂钟上的读数,比如"早上 9 点开会"。不带时区就没有唯一时刻,但业务要的就是这个字面值:每天 9:00 的闹钟、营业时间、生日、定时任务。 四种数据库类型各占一边: 绝对时刻 墙钟时间 MySQL TIMESTAMP DATETIME PostgreSQL timestamptz timestamp 名字陷阱就在这张表里:MySQL 的 TIMESTAMP 对应 PG 的 timestamptz ,不是 PG 的 timestamp 。跨库迁移或写 ORM 时极易搞反。后面所有内容都是这张表的展开。
鸟窝 · ZH
-
PostgreSQL与MySQL的JSON类型及Go语言处理
关系型数据库存 JSON 早就不稀奇了,但把它用对没那么简单。你得先分清 PostgreSQL 里 json 和 jsonb 到底差在哪、什么时候该建什么索引,再决定 Go 代码里怎么读写才不别扭。这篇就把这几件事讲清楚,代码都能直接抄进项目。 一、三种类型的本质区别 维度 PostgreSQL json PostgreSQL jsonb MySQL json 存储形式 原始文本(逐字节保存) 分解后的二进制 分解后的二进制 保留空格/键序 保留 不保留 不保留 保留重复键 保留 只留最后一个 只留最后一个 写入速度 快(不解析) 稍慢(要解析) 稍慢(要解析) 查询速度 慢(每次重解析) 快 快 支持索引 否(需表达式索引) GIN 索引 函数索引 / 多值索引 去重/规范化 否 是 是 一句话选型: PostgreSQL 绝大多数场景直接用 jsonb 。只有当你需要"原样存回、包括空格和键顺序"这种审计类需求时才用 json 。 MySQL 只有 json 一种 (内部实现类似 jsonb,二进制存储、支持部分更新)。
鸟窝 · ZH
-
grep 工具大盘点:rg、tgrep、rawgrep、zg
如果你问一个程序员"平时在代码库里怎么找东西",大概率会得到一个答案: rg 。ripgrep 从 2016 年发布到现在,快十年了,又快又稳,68k stars,早就成了事实标准。 但你要是追问一句" 仓库已经大到 rg 也要扫好几秒,怎么办 ",答案就变得有看头了。过去一两年,grep 世界冒出来好几路新势力,同一个老问题,各自给了一份不同的答卷: tgrep (微软):预建三元组索引,一次启动、永久秒搜,已经被 Copilot CLI 集成; rawgrep :绕过文件系统,直接读裸盘; zg (阿里 zvec):把 ripgrep、BM25、向量检索捏进一个入口,专门伺候人和 AI Agent。 加上守擂的 rg ,这四把刀恰好是四条完全不同的技术路线。挨个拆开看。 先交代一个背景。AI Coding 时代,"搜索"从开发者的日常工具变成了 Agent 的核心基础设施,Agent 找证据靠它、省 token 也靠它。所以这四把刀里有两把(tgrep、zg)几乎就是冲着 AI 编程助手做的。而且更有意思的是,今天主流的几个 Coding Agent,Claude Code、OpenAI Codex、Pi,默认的代码搜索引擎不约而同都选了 ripgrep。这个细节放到第五节说。
鸟窝 · ZH
-
网站被投毒
2026-09-17,我发现 colobu.com 的页面上被加载了一个可疑 iframe: https://soduncdn.com/m.html 。域名注册于十天前、没有任何 A 记录、被 6/89 个安全引擎标记。查了一圈之后,结论有点出乎意料。 结论 页面本身没被改。被投毒的是页面引用的那个第三方 CDN 脚本。 出问题的是一行看起来再普通不过的写法: 1 < script src = "//cdn.staticfile.org/jquery/1.11.1/jquery.min.js" > </ script > cdn.staticfile.org 会在 极低概率 下返回一个被追加了 383 字节的篡改版 jQuery(96169 字节,官方版本是 95786 字节)。这 383 字节干的事,就是往页面里塞一个隐藏 iframe。
鸟窝 · ZH
-
新AI模型 Jev 实战:概念、场景和两个实战
一、一个不写字的模型 9 月 15 日,一条推文在开发者社区里传开。 发帖人是 Diogo Almeida。他说自己参与发明了 ChatGPT,然后一直在问自己一个问题:为什么对话模型已经强到超人,AGI 还是没有出现?过去两年他"隐身",用一种新的训练方法(RLCD)训出了一个新类型的模型,今天发布,名字叫 Jev。 他给出的数字:快 20–200 倍,便宜 40–400 倍。TypeSafe AI 同期宣布了 4000 万美元种子轮。 接下来几天,用 TechCrunch 的标题概括就是:"一个来自 ChatGPT 发明者的新型 AI 模型,正在让开发者兴奋。"Reddit 上 r/ArtificialInteligence 的帖子一天之内冲到 120+ 评论,标题是"Jev / TypesafeAI is revolutionary as LLM's",正文第一句:"Jev is insane."X 上 @0xCodila 说这是 AI 行业的"互联网时刻",@akshay_pachaar 的总结是:"我们一直拿 LLM 当锤子,敲每一个 AI 问题,哪怕是再简单不过的判断。Jev 用毫秒和零头的成本把这些判断接了过去。"中文社区里,@Saccc_c 的推荐很直接:"强烈建议大家都亲自试试 Jev,能让你的 Codex 操作速度提高 10 倍并省下大量 token。" 同时,
鸟窝 · ZH
-
jev 兼容
https://github.com/mizorewww/laya-mlx https://github.com/mizorewww/laya-coreml 要运行 aac6fef/laya-coreml 并提供 Type-Safe(类型安全) 兼容的 API,最有效的方法是结合 Python 的 laya_coreml 库,并利用 Pydantic 或 Python 3.10+ 的 TypedDict / Literal 对输入结构与返回概率进行严格的类型约束。 由于该模型不是生成文本的大模型,而是直接返回“选择题、评分或布尔判断”的概率,我们可以完美地用类型系统将模型输入输出锁死,从而在编译器或 IDE(如 VS Code / PyCharm)中获得完整的类型提示。 [1] 下面是为您编写的完整运行及 Type-Safe API 封装方案:
鸟窝 · ZH