[翻译] 为什么 Tracebit 用 C# 开发 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
liuliuliuliu
0D
V2EX    程序员

[翻译] 为什么 Tracebit 用 C# 开发

  •  3
     
  •   liuliuliuliu
    PRO
    228 天前 2615 次点击
    这是一个创建于 228 天前的主题,其中的信息可能已经有所发展或是发生改变。

    原文: [Why Tracebit is written in C#]

    作者: [Sam Cox (Tracebit 联合创始人兼 CTO)]

    译者: [六六]

    (译注:Tracebit 成立于 2022 年,是一家提供云威胁检测服务的公司。其平台采用轻触式基础设施,企业可以在短短 30 分钟内在云网络上设置和打开威胁欺骗。目前,Tracebit 已经保护了超过 250 个云账户和 1500 个云金丝雀资源,每周处理超过 24 亿个安全事件。)

    当我们开始构建 Tracebit 时,我面临的首个决策是个很常见的问题 -- 选择什么样的技术栈?其中一些选择相当容易(例如 AWS 、Postgres ),但让我犹豫的是选择哪种编程语言?我最终的选择可能出乎你的意料,甚至在我最初评估选项时,也未曾预料到自己会做出这个决定。

    Tracebit 是一款面向企业的 SaaS 安全产品。如果向工程师(尤其是某橙色技术网站的读者[译注: hacker news 网站])发起调查,询问此类系统的“最佳”语言,常见的答案可能是 Python 、TypeScript 、Golang 、Rust 、JVM 系语言,或是 Elixir 。显然这里没有“标准答案”,但经过深思熟虑,我们选择了一条不同的道路:用 C# 开发 Tracebit 。

    为什么选择 C#?

    关于创业公司技术栈选择的常见建议是“坚持你熟悉的技术” -- 尤其是已验证有效的技术。这无疑是真理,也使得大多数决策变得容易。

    在我的职业生涯中,我曾用 Python 和 TypeScript 开发过大型且至关重要的代码库。我见证过它们的优势(生态系统、招聘便利性、工程师上手速度),但也亲历过明显的短板(动态类型、包管理与依赖项维护、大型代码库的维护)。

    因此,在选择语言时,我希望探索包括未曾使用过的语言。

    选择标准

    开发效率

    如果要定义我对编程语言的核心诉求,那便是开发效率。总的来说,我认为能让开发者把时间花在重要工作的技术栈,才是良好开发体验的本质。

    效率的维度众多,且在产品或公司生命周期的不同阶段有不同的相对重要性。

    早期阶段:快速迭代和验证想法的能力至关重要,因为你很可能在错误的方向上投入。这种验证应在编码前开始,但编码时需选择能快速表达想法并实现产品的语言。

    维护阶段:所有软件都需要维护。随着对问题域的理解加深和功能扩展,需能安全高效地重构代码,同时尽量减少无益于产品或工程师的维护时间。

    规模化阶段:当产品、代码库和团队扩大时,该语言能否保持生产力和软件的可持续性?

    截至目前,.NET 展现出惊人的生产力,我们相信它是未来发展的坚实基础。

    免费与开源

    我们希望在开源(且免费)的平台上构建产品。无法查看实现细节会增加开发难度,而早期阶段我们希望避免不必要的开支。

    几乎所有候选技术栈都满足这些条件[^1]。但此前我未意识到,.NET 如今已是 MIT 协议的开源免费框架。微软可能意识到真正的利润来自 Azure 的算力销售,而更多 .NET 开发者意味着更可能选择 Azure 部署。当然,部署 .NET 并非必须使用 Azure -- 我们目前就没有!微软从我们这赚到的钱,单一个 Teams 许可证就超过整个技术栈的费用。

    跨平台支持

    我已 15 年未使用 Windows ,也绝无兴趣在其上部署生产系统!提到这点是因为我很惊讶地发现,C#/.NET 是真正的跨平台框架 -- Tracebit 的首行代码就是在 Arch Linux 上毫无困难地编写的。现在我们用 MacBook 开发,部署于 ARM 架构的 Linux 服务器。

    微软甚至与 Ubuntu 合作提供“精简化”的 Docker 基础镜像,以最大限度地减少攻击面和补丁管理,同时从可信且广泛兼容的上游直接获取安全更新。

    流行度

    语言流行度虽不直接代表质量,但至关重要:

    业务扩张时需要快速招聘工程师,若人才池不足将限制企业发展速度。对初创公司而言,团队扩容往往是工程侧的最大瓶颈。同样重要的是,工程师获得的技能应具备行业通用性,助力其职业发展。

    流行语言的优势还包括:

    • 丰富的 SDK/库资源
    • 海量文档和在线示例(及 LLM 训练数据)
    • 更少成为语言特性或核心库缺陷的首个踩雷者。

    所有这些都有助于工程师提高工作效率。

    所以我们只考虑 TIOBE 前 20Stack Overflow 开发者调查中的语言。其中 C# 相当稳定地排在第 5 位(对于通用语言而言)。

    ( Stack Overflow 开发者调查截图)

    看到它如此受欢迎,我有点惊讶,但我不得不提醒自己,流行度并不等同于时髦度 -- C# 与时髦不沾边。C# 很少登上 Hacker News 头条(我认为相对于用户群而言,它可能是讨论最少的语言),就像你不会经常看到人们赞美在 Linux 主机上部署软件或使用关系数据库的优点 -- 但这并不意味着这些不是受欢迎的选择,而是意味着有很多人只是默默地使用它

    内存安全

    内存安全是完全没有商量余地的 -- 这感觉毫无争议,我觉得不值得多讨论。当 CISA 都在呼吁《软件产品内存安全的迫切需求》时,用 C 语言开发安全创业产品简直是行为艺术。

    垃圾回收

    为何需要 GC ?或者说“为何不选 Rust”?因为我们不做实时/系统/嵌入式编程,可以承受 GC 暂停。我不想冒这样的风险,选择 Rust 后,我会花更多的时间与借用检查器搏斗,而不是迭代产品。

    静态类型

    静态类型至关重要。基于动态和静态类型语言的双重经验,我认为静态类型在编码时引入的“开销”,会通过代码可读性和可维护性获得超额回报。尽管存在争议,但静态类型确实能减少错误,还能提升性能。

    对我而言,核心价值在于提升代码阅读和维护效率。静态类型帮助我快速理解记忆模糊或陌生的代码意图与实现。更不用说 IDE 中 "查找所有引用"/"跳转定义" 的精准性,以及更自信的重构能力。

    如果把类型系统视为从 'true + true == "2"' 到 ' A monad is a monoid in the category of endofunctors '(译注: 函数式编程的梗) 的光谱,C# 恰好处于中间位置。它拥有我欣赏的实用特性(泛型、record 类型、运行时支持、合理推断)。我唯一真正怀念的是联合类型,目前仍处于提案阶段

    至于渐进式类型?我曾用此类语言构建重要生产系统,但最终心态变成 "逐步将动态类型代码转为静态类型",而非 "太好了,新代码不用考虑类型"。既然如此,何不从一开始就选择目标方案?尤其当整个生态的同行和依赖项都如此实践时[^2]。

    稳定性

    这是 C#/.NET 真正闪耀的领域:每年同一时间发布主版本,LTS (长期支持)和 STS (短期支持)交替。LTS 获得 3 年补丁支持,STS 为 18 个月支持。变更文档完善、测试充分且向后兼容。生态系统中的大部分都遵循此发布节奏,因此核心依赖项能立即受益于新语言特性、数据类型和性能改进,并经过协同测试。

    (.NET 发布周期截图)

    如果你来自不支持或较少使用访问修饰符( public/private/internal 等)的语言,初期可能觉得冗长或受限。但在主版本升级时,这些设计会带来回报,因为你只需关注依赖项公开的 API 接口。

    自 Tracebit 启动以来,我们已完成三次主版本升级,每次都非常利(耗时均不足一天)。

    开箱即用

    NET 平台包含大量优质库、API 和框架。你想要实现任何功能,很可能会在 .NET 团队 / Microsoft 维护的库中找到解决方案 [^3]。无论是通用集合、日期 / 时间函数、大 JSON 文件流式反序列化、加密函数、结构化日志、测试框架、世界级 HTTP 服务器、OpenIdConnect 实现、ORM 、WASM 编译器、OpenAPI 规范生成,还是分布式 Actor 框架 -- 应有尽有。

    这点对我们价值难以估量。在某些生态系统中,你可能会陷入选择困难,耗费大量时间评估 n 个依赖项:

    • 其许可协议是否合规?会变更吗?
    • 维护者是谁?可信度如何?
    • 会引入多少传递依赖?
    • 性能 / 测试 / 文档是否达标?
    • 会导致多少 Dependabot 警报?补丁发布速度?
    • 是否应该自行实现?

    Tracebit 作为需要客户环境特权的安全产品,我们必须严格把控这些因素。明确回答 "如何实现这个问题?" 能为初始开发和持续维护节省大量时间。某些使用 node 实现的简单 CSS 的构建,其依赖项数量甚至超过我们整个 C# 产品!

    工具链

    成熟生态系统带来的丰富高质量工具是另一大优势。我们使用 Rider -- 这是一款出色的 IDE ,非商业用途免费 - 我强烈推荐它。它具备所有预期功能(调试、测试、重构等),还支持动态程序分析等高级特性,能自动检测低效数据库访问模式、过度内存分配、缓慢 HTTP 处理程序等问题。交互式调试无缝且强大,内存分析、快照对比、堆检查、泄漏检测等功能一应俱全。

    (动态程序分析检测高行数查询的截图)

    还有大量的静态分析器可用,它们可以提供很好的防护,通常内置自动修复功能。

    ( JetBrains dotMemory 工具截图)

    还有可轻松集成到 docker 镜像中的运行时诊断工具,能收集海量诊断数据直达问题核心。例如,我们曾通过收集预发环境的跟踪和堆转储,快速解决本地未复现的性能问题 -- 否则需要繁琐地添加日志埋点、跨度指标等来定位问题根源。

    性能

    性能很少是选择语言的主因,但无疑是锦上添花。从这个角度看,C# 表现优异。观察最具代表性的 TechEmpower 基准测试 "fortunes"(使用 ORM 和完整框架),主流的 .NET 技术栈位列第 10 (共 80 个)。可以公平地说,排名再靠前的框架多数较为小众,并非你会随意采用的技术。

    虽然我不太看重基准测试,但明显性能是 .NET 团队的重点关注方向。每个新版本发布时,我都期待阅读那些详述最新性能优化的深度文章,以及升级带来的显著改进。有些问题难以水平扩展,节省下来的优化和排障时间可以投入其他领域。

    TechEmpower 'Fortunes' 基准测试前 15 名( ORM & 完整框架)

    功能特性

    .NET 有许多令人印象深刻的技术特性和高效工具:LINQ 、Entity Framework 、TPL Dataflow 、ASP.NET 、F# 等等。这些绝对值得深入研究 -- 我真诚认为某些功能在其他技术栈中无可匹敌。

    实践效果如何?

    启动 Tracebit 时我们面临许多需要快速决策的事项。语言选择只是其中之一,虽然当时感觉存在风险,但我对选择 C# 感到满意。至今我们已提交数千次 commit ,发布超 10 万行代码,包括从未接触过 C# 的工程师。所有人都能快速上手(否则我们早就弃用了!)。C# 是我们取得当前成就的关键要素,从未出现意外状况。在许多方面,它甚至超出了我的预期。

    语言选择没有银弹,终究是主观决策。很可能其他选择同样能带来满意结果。

    本文某种程度上是写给曾经持有偏见的自己(完全不会考虑 C# 的那个自己):值得重新审视。对于任何认真考虑 C# 的读者:希望你们也能享受它!

    脚注

    [^1]: 虽然对 Java 的情况不太确定。如果说我对微软存在某些成见,那我对 Oracle 的成见更深! OpenJDK 似乎是 GPL 许可,不确定能否在自己的项目中借用或改编其标准库代码。鉴于 Java 的广泛使用,我的理解可能有误。

    [^2]: 严格来说 C# 支持动态类型,但仅限特定场景且非常用写法。静态类型是 "默认选择" 而非 "可选添加"。这类似于 Rust 的 unsafe 或 Haskell 的 unsafePerformIO -- 例外反证了规则。

    [^3]: 并非否定优秀第三方开源库的存在 -- 确实有很多。当这些库获得广泛关注时,.NET 团队乐于接纳并扩展它们以惠及所有用户。例如提供广泛兼容的日志和指标接口,只需 "启用"OpenTelemetry 就能以统一方式输出日志、指标和跨度(包括依赖项的数据)。

    24 条回复    2025-02-27 02:24:27 +08:00
    cnbatch
        1
    cnbatch  
       228 天前   1
    我日常工作主要靠 C# /.Net ,连网站也用 C# 那一套。对于需要节省脑细胞的场景,用 C# 真的很方便,在 IDE 内随便点几下鼠标就能找到满足需求的库,VS2022 甚至自带了简单的代码预测。而且现在 AI 辅助满天飞,问 AI 也能简单地获得可用的代码。

    跟文章原作不同的是,我主要是在 Windows Server 运行 .Net 程序,用户鉴权使用 Windows 活动目录那一套。公司的内部限制导致只能用 .Net Framework ,难以安装 .Net 5+ 的版本(其实是公司服务器安装任何软件都不方便),然而即使是这样,大多数第三方库依然能够正常使用,基本足够解决工作需求。
    PendingOni
        2
    PendingOni  
       228 天前
    用完 C#后发现再去学 C 方便很多 需要懂些基本的数据结构和底层逻辑
    sagaxu
        3
    sagaxu  
       228 天前   1
    讲了那么多优点,把 C#换成 Java/Kotlin 一样成立啊。dotnet 有些调试工具还是 windows only 。
    jamesjammy061
        4
    jamesjammy061  
       228 天前   1
    kotlin yyds ,虽然我是前端
    maix27
        5
    maix27  
       228 天前
    > dotnet 有些调试工具还是 windows only 。
    你这句话说了不跟没说一样现在大部分的 C#工具都迁移到 Linux or 直接开发 Linux 版。
    sagaxu
        6
    sagaxu  
       228 天前
    @maix27
    https://learn.microsoft.com/en-us/aspnet/core/performance/diagnostic-tools?view=aspnetcore-9.0

    8 项 Only supported on Windows.
    https://learn.microsoft.com/en-us/dotnet/core/diagnostics/sos-debugging-extension

    vs, PerfView, PerfCollect, .NET Memory Profiler 这几个都没有

    有些调试文档是基于 windbg 写的,对 Linux 用户也非常不友好。
    NightFlame
        7
    NightFlame  
       228 天前
    不错,有介绍 C#缺点的文章,想兼听则明
    maix27
        8
    maix27  
       228 天前
    @sagaxu 你大可不必找我辩白,就算没有 linux 版,也有其他公司 or 社区开发的替代品,你们 J 佬很奇怪诶,论及 C#的时候就对社区贡献闭口不谈了?
    maix27
        9
    maix27  
       228 天前
    @sagaxu 最重要的一点,有一大票行业软件是依赖 windows 的,windows 不是毒药,眼睛别只盯着互联网,只盯着互联网你拿多少钱加多少班多少人卷啊?
    LaTero
        10
    LaTero  
       228 天前 via Android
    个人感觉的比较记忆深刻的缺点:没有 immutable ,没有 union 类型,if 不能有值,微软的文档莫名其妙很难搜索。而优点对于 C++背景最大的是运行时类型信息非常完整,反射,[]属性和代码生成有非常强而易用的元编程(虚幻 C++全是宏),但是这些 kotlin 好像也都有……
    liuliuliuliu
        11
    liuliuliuliu  
    OP
    PRO
       228 天前
    @sagaxu #3 不是的,您可能没有仔细看文章。
    原文里有提到,作者担心 java 的 GPL 许可对商业不友好以及性能上,在 TechEmpower 的测试里 java 的 spring 可能很靠后,再有功能和特性一节,某些功能在其他技术栈并不存在。
    原文里还提到,他们正在 Rider 这个 IDE 开发,具备所有预期功能(调试、测试、重构等)
    maix27
        12
    maix27  
       228 天前
    @sagaxu 哥们别查资料了,你赢了,我输了,我错了,java 最牛,呜呜呜。没必要大半夜发消息,明天早上我看到了膈应。
    opengps
        13
    opengps  
       228 天前
    用最熟悉的+1 ,最核心问题不是选什么技术,因为主流的都能实现相同的功能。业务模式才是核心
    maix27
        14
    maix27  
       228 天前
    @sagaxu 你那哪是没仔细看,你是没看,我也说了 “现在大部分的 C#工具都迁移到 Linux or 直接开发 Linux 版。”

    你就非要说人家没开发,8 项命令是没有啊,问题是全部加起来有 40 多项命令,你不用这个换 net-dump 也没问题,不符合我提到的 大部分能迁移的迁移,不能迁移的直接开发 linux 版吗?

    PerfCollect 是没有啊,微软不在下面给了解决方案吗,不带 only windows 都能用。我说了到 2025 年为止,微软已经给了足够的诚意给 Linux 用户,看看文中提到的 docker 镜像和各种开源工具/库。
    maix27
        15
    maix27  
       228 天前
    @LaTero 原作者说了选择 C#的原因,他提到只选择了 tobie 前 20 的语言。
    mark2025
        16
    mark2025  
       228 天前
    这是 C#/.NET 真正闪耀的领域:每年同一时间发布主版本,LTS (长期支持)和 STS (短期支持)交替。
    =========
    NodeJs 不也采用类似的发布策略么
    sagaxu
        17
    sagaxu  
       227 天前
    @liuliuliuliu TechEmpower 那个测试截图中,aspcore 第 10 名,成绩是 140K ,Java 的 quarkus 排第二,成绩是 214K 。用什么技术,很大程度上是技术官僚政治问题,而非技术本身。千人以上公司,Java 转 dotnet ,dotnet 转 Java 例子都有。国内还有打着信创名义禁用的,比如某一线城市卫生系统


    @maix27 前几天排查一个 unmanaged memory 泄露的问题,找到的方法大都是 windows 下的。而这个问题在 windows 下还没法重现,解决问题的门槛变得更高了。

    @mark2025 微软维护的 OpenJDK LTS 最少支持 5 年,其它厂商支持的更久。讲个笑话,dotnet 8 比 Java 8 更早 EOL 。
    hez2010
        18
    hez2010  
       227 天前 via Android
    .NET 兼容性确实不错,升级就是改个版本号的事情,而且每次升级都能坐享免费的性能提升。
    前不久给 garnet ( C# 实现的 redis 服务器)做性能测试,简简单单提升个 .NET 版本号就能看见性能以肉眼可见的幅度往上走。

    charlie21
        19
    charlie21  
       227 天前
    数据库和 ORM 用的哪个
    poorcai
        20
    poorcai  
       227 天前
    网上流传:每一个写惯了 C# 的程序员,再尝试写 爪哇 时,高低都会骂两句又臭又长
    1Z3KYa0qBLvei98o
        21
    1Z3KYa0qBLvei98o  
       227 天前
    我也喜欢 C#,但是在机器学习领域,C# 和 python 对比咋样?
    hez2010
        22
    hez2010  
       227 天前
    @VchentozV 现在有 TorchSharp ( https://github.com/dotnet/TorchSharp )了,基本上你 python 怎么写 ML 在 C# 就怎么写 ML ,同样支持 CUDA 加速等等还没有部署打包的烦恼。不过很多构建在 pytorch 之上的第三方库还是得自己移植。
    liuliuliuliu
        23
    liuliuliuliu  
    OP
    PRO
       225 天前
    @sagaxu #17
    TechEmpower 的问题,原文里有提到,您还是没看原文
    “主流的 .NET 技术栈位列第 10 (共 80 个)。可以公平地说,排名再靠前的框架多数较为小众,并非你会随意采用的技术。”
    您提到的 quarkus 是很小众的框架,并非会随意采用的技术。

    其实我作为一个译者,并不想与你讨论更多孰好孰坏,我更关心原作者的意思有没有被真实的表达,鉴于您数次不看原文就提出问题,我真的不是很想回答或讨论了。
    liuliuliuliu
        24
    liuliuliuliu  
    OP
    PRO
       225 天前
    @charlie21 原文里有提到 Postgres 和 Entity Framework
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1247 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 17:18 PVG 01:18 LAX 10:18 JFK 13:18
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86