写点什么

云端开发是个坑!4 年后,我们又回到了本地环境

  • 2022-03-30
  • 本文字数:3055 字

    阅读完需:约 10 分钟

云端开发是个坑!4年后,我们又回到了本地环境

云端开发环境是软件工程的未来吗?


一些运行在 Kubernetes 中的复杂微服务架构是 CPU 和内存密集型的,在某些情况下编译或测试可能非常耗时且占用大量资源。然而大多数工程师的标准设备是笔记本电脑,有 CPU 和内存的限制,编译一次的时间估计够喝好几杯咖啡。


建立在云端的远程实例通常可以根据需要进行扩展,以适应对容量的额外需求,因此在容器化变革的基础上,一些企业开始不再那么依赖于本地开发环境。虽然近一两年有一些令人兴奋的远程方案,比如 GitHub Codespaces、AWS Workspaces 或其它使用云的标准解决方案,但在它们足够成熟和安全之前,很多企业早已选择了自建云端开发环境,Lyft 就是其中之一。


云端开发逐渐成为了坑


早在 2018 年,Lyft 的工程师就将一个大单体拆分成了一系列微服务。基于 Docker 容器的模块化开发环境最终转移到了云端。然而随着时间的推移,工程师、微服务和测试的数量的激增,他们的开发工具跟不上了。


实际上,Lyft 对综合开发环境的第一次重大投资始于 2015 年,当时的工程师人数为 100 名,大部分开发还是在一个单体架构上,只有少数用例是微服务,但预计到工程师和服务的数量会增长,所以他们认为迁移到容器是很有意义的。最初的计划是构建一个基于 Docker 的容器编配环境,工程师可以用它们做测试。它将在生产环境中使用多租户环境,相比以前的解决方案,可以更便宜、更快地进行伸缩。


2016 年初,Lyft 发布了一个本地开发环境,叫作 Devbox,是“盒子里的开发环境”的缩写,由一些管理本地虚拟机及其配置的工具组成,包括数据生成、包和镜像的下载和安装。开发人员只需要发出一个命令就可以构建一个可以处理请求的环境。


这些体验很棒,让工程师们第一次拥有了一种一致的、可重复的、简单跨多个服务开发方法,于是很快出现了共享这些环境的需求。Devbox 转向了云端,变成了 Onebox。Onebox 本质上是一个运行在 EC2 实例上的 Devbox 环境。由于它的容量更大,下载镜像的速度更快,工程师们自然更喜欢它而不是 Devbox。



两种不同风格的开发环境


在将 Devbox 和 Onebox 作为容器化开发环境引入四年后,使用这些环境的工程师增加了十倍,微服务数量也一直在激增,配置和启动 Onebox 实例变得越来越困难和耗时。


由于每个服务都有很深的交互树结构,实例可能需要很多的资源。可观察性工具不能跟上所有正在运行的环境,导致调试工作变得很困难。打比方说,不可能在数百个环境中运行相同的可观察性工具,当出现问题时,就很难查明确切原因。此外,工程师的认知负担显著增加,因为他们需要牢记整个系统,而不是专注于特定的组件。


根据 Lyft 的工程设计,工程师的代码变更过程可以分为“内部开发循环”和“外部开发循环”。前者应该只需要几秒钟就能给出反馈,因为它只涉及修改代码和运行一些测试。后者可能需要更长的时间(至少 10 分钟),因为它涉及持续集成和代码评审。集成测试臃肿笨拙,花费一个小时是司空见惯的事情。并且 80% 以上的测试要么是不必要的,要么可以在短时间内重写并在没有外部依赖的情况下运行。测试失败还要花费数小时的调试时间,大多数还都是误报。



另一方面,执行内部开发循环通常需要将代码更改同步到开发人员自己在 Onebox 的远程 VM 环境。考虑到 Onebox 环境的设置和启动速度很慢,再加上明显的不稳定性,工程师通常会依赖外部开发循环的 CI 测试来验证每个代码变更迭代。


一年前,将开发环境迁移到 Kubernetes 之后,工程资源的变化让大家不得不重新审视开发环境:维护基础设施以支持这些按需环境变得过于昂贵,而且只会随着时间的推移而恶化,所以需要对开发和测试微服务的方式进行更根本性的改变。


开发环境必须回到工程师的机器上


为了摆脱不断增长的烦恼和挫折,Lyft 将开发环境带回到工程师的笔记本电脑上,同时重新构建内部开发循环。


在容器中运行代码并不是一种免费的抽象,因此他们决定在 MacOS 的隔离环境中运行服务代码,不使用容器或虚拟机。


在 Lyft,大多数后端服务是用 Python 或 Go 语言开发的,而前端服务是用 Node 开发的:


  • 对于 Python 服务,通过使用不可变的虚拟环境进行隔离。每次 requirements.txt 文件发生变化,都会构建一个新的虚拟环境。

  • Go 服务利用 Go 模块工具链在 go run 或 go test 命令执行时自动下载和链接所有依赖项。

  • 他们基于 nodeenv 构建了一个包装器,用于根据每个 Node 服务的元数据为其创建合适的环境。


一些专门的服务,如数据存储,也在本地运行,通常会使用容器。数据存储在启动时使用由服务所属团队维护的脚本来加载新数据。


因此,在本地启动服务需要多个步骤。通过手动来执行它们既乏味又容易出错。Lyft 使用 Tilt 来协调服务的生命周期及其环境,避免通过手动执行所有的步骤。每个服务都有一个 Tiltfile,用于描述在本地运行服务所需的步骤。当工程师在 IDE 中修改了代码时,运行中的服务也会重新加载自己,从而进一步缩短内部开发循环。


除了运行服务之外,还需要与服务发生交互。由于 Lyft 使用了不同的传输格式,比如 gRPC、JSON/HTTP 和 protobuf/HTTP,因此向服务发出请求并不是那么简单。工程师们使用 Lyft 开发的一个工具向本地服务发送请求。这个工具可以与服务的 IDL 集成,因此可以利用工具的自动补全功能。


最终结果


自从将这个工具推广到整个公司以来,Lyft 工程师反馈非常积极。


开发人员喜欢无需任何远程环境即可在笔记本电脑和 IDE 中运行测试的能力。创建一个新的 Onebox 环境通常需要大约一个小时,但现在笔记本电脑环境始终可以运行测试,使用 Tilt 在本地启动服务只需几分钟。


负责基础架构的高级软件工程师 Scott Wilson 说:“我们还观察到开发人员的行为转变,因为他们花费更多时间专注于测试他们的服务。在测试本地服务时,用户可以直接向服务 API 发送请求,而不是通过移动应用程序与公共 API 对话。这增加了开发人员对服务 API 的熟悉程度,并缩小了在出现错误时的调试范围。”


而且让用户在他们的笔记本电脑上单独运行服务意味着真正减少所需的总计算资源。“虽然成本不是这个项目的主要驱动因素,但不再为每个开发人员支付 Onebox 的 AWS 实例,我们最终节省了大量资金。”


总的来说,对于开发者来说,因开发环境而导致正常工作停滞不前是特别让人不可忍受的。不好的开发环境会严重影响大家的生产力,而一个好的本地开发环境,允许开发人员在没有破坏共享环境或干扰面向客户的环境的风险的情况下运行和测试代码。而且,它通常是低成本的,依赖于已经支付的资产,比基于云的环境更高效、更便宜。


另外,Scott Wilson 表示他们也正在密切观望完全远程的开发环境,例如 Github Codespaces,以了解它们成熟后是否适合自己。


参考链接:


https://eng.lyft.com/scaling-productivity-on-microservices-at-lyft-part-1-a2f5d9a77813


https://eng.lyft.com/scaling-productivity-on-microservices-at-lyft-part-2-optimizing-for-fast-local-development-9f27a98b47ee


https://eng.lyft.com/scaling-productivity-on-microservices-at-lyft-part-3-extending-our-envoy-mesh-with-staging-fdaafafca82f


https://eng.lyft.com/scaling-productivity-on-microservices-at-lyft-part-4-gating-deploys-with-automated-acceptance-4417e0ebc274


https://github.com/readme/guides/developer-onboarding


今日好文推荐


不用任何框架开发 Web 应用程序,可能吗?


腾讯回应裁员;小米辞退绩效考核分数低员工终审败诉;GitHub 频繁宕机原因:MySQL 负载过重 | Q资讯


微软、英伟达等多家企业源代码被偷,“带头大哥”居然是未成年人?


开源还有真假?Neo4j 起诉3家公司虚假宣传开源胜诉


2022-03-30 14:2113426

评论

发布
暂无评论
发现更多内容

第五周 第一课笔记

Geek_娴子

普本毕业,阿里五面成功斩下offer,名校出身的我究竟输在哪?

Java架构之路

Java 程序员 架构 面试 编程语言

成为阿里P7移动架构师到底有多难?带你快速通过字节跳动面试,讲的明明白白!

欢喜学安卓

android 程序员 面试 移动开发

第五周笔记

Ashley.

“他者”德意志(二):“走稳路”的德国半导体

脑极体

2.1 Go语言从入门到精通:Go语言基础语法

xcbeyond

28天写作 基础语法 Go 语言

Linux之旅 - 入⻔命令集 - 文件管理(1/2)

诚义舅

bash Linux Shell linux命令

LeetCode题解:121. 买卖股票的最佳时机,JavaScript,动态规划,详细注释

Lee Chen

算法 大前端 LeetCode

Linux之旅 - 行程介绍

诚义舅

bash Linux Shell

边缘计算云原生开源方案选型比较

远鹏

Kubernetes 边缘计算 kubeedge openyurt superedge

Newbe.Claptrap 框架入门,第一步 —— 开发环境准备

newbe36524

Docker 云计算 分布式 微服务 .net core

架构设计篇之微服务实战笔记(八)

小诚信驿站

架构 刘晓成 小诚信驿站 28天写作

安卓开发环境!一份字节跳动面试官给你的Android技术面试指南,终获offer

欢喜学安卓

android 程序员 面试 移动开发

【LeetCode】至少有K个重复字符的最长子串Java题解

Albert

算法 LeetCode 28天写作 2月春节不断更

Newbe.Claptrap 框架入门,第二步 —— 创建项目

newbe36524

Docker 云计算 分布式 微服务 .net core

2021最新华为面经分享:Java高分面试指南(25分类1000题50w字解析)

比伯

Java 编程 架构 面试 计算机

2021年金三银四Java面试突击大全,吃透这套Java真题合集,突破BAT面试官这道“防线”

Java 架构 面试

诊所数字化:实施私域,诊所店员的赋能路径

boshi

数字化医疗 私域运营 七日更 28天写作

备战金三银四必备:2021最新Java面试汇总(附答案解析)

比伯

Java 编程 架构 面试 计算机

Elasticsearch Doc Values 和 doc_values

escray

elastic 七日更 28天写作 死磕Elasticsearch 60天通过Elastic认证考试 2月春节不断更

2021最全iOS面试题及底层视频分享专栏

ios 面试 音视频 iOS底层 iOS逆向

第五周作业

Ashley.

开发者的福音,go也支持linq了

happlyfox

学习 28天写作 2月春节不断更 Go 语言

可能是Java Stream的最佳实践(三)

ES_her0

28天写作

Linux之旅 - 自序

诚义舅

bash Linux Shell

Nginx入门的基本使用和配置详解

数据库 架构 运维

《华为技术认证HCNA网络技术实验指南》参考配置Ⅰ

依旧廖凯

华为 网络 交换机

Selenium 项目代码的优化与重构之路,滚雪球学 Python 番外篇

梦想橡皮擦

Python 28天写作 2月春节不断更

Linux之旅 - 入⻔命令集

诚义舅

bash Linux 运维 Shell

状态图与概念模型

克比

第五周 第二课笔记

Geek_娴子

云端开发是个坑!4年后,我们又回到了本地环境_服务革新_明知山_InfoQ精选文章