【ArchSummit】如何通过AIOps推动可量化的业务价值增长和效率提升?>>> 了解详情
写点什么

云端开发是个坑!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:2112276

评论

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

最强总结——分布式事务处理方式

小闫

面试 分布式 分布式锁 分布式存储 分布式缓存

第五周总结

武鹏

打造Redis分布式环境下的银弹?我觉得Redisson比Redlock更胜一筹

码农月半

Java redis redis高可用 Redis项目

架构师训练营 - 第 5 周命题作业

红了哟

Spring Boot 多数据源 Redis 配置

南南

redis 面试 Spring Boot Redis作者

架构师训练营 一致性Hash算法Java实现

Cloud.

让你大显身手——掌握RocketMQ与Kafka中如何实现事务

小谈

kafka 面试 RocketMQ JVM原理

产业区块链发展迎来爆发期

CECBC

产业区块链 系统稳定性 应用安全性 信任的机器

一篇文章深入理解分布式锁

itlemon

redis 分布式锁

20道Redis面试题(含答案)面试官会问的我都找到了

你是人间四月天

redis 面试 Spring Cloud redis6.0.0 Redis项目

【week05】总结

chengjing

程序员是这样解读《隐秘的角落》

陈东泽 EuryChen

学习 程序员 隐秘的角落

week5 学习总结

Geek_2e7dd7

码农必备SQL高性能优化指南!35+条优化建议立马get

码哥小胖

MySQL SQL语法 sql查询 sql

阿里P7岗位面试,面试官问我:为什么HashMap底层树化的标准元素个数是8

鄙人薛某

Java 面试 hashmap 哈希

公司制的黄昏:区块链重构商业世界

CECBC

区块链思维 裂变 契约 激励

这份架构PDF如何得到百度、洋码头、饿了么CTO等大咖联袂推荐?

小新

Java 架构 面试 队列

因为我的一个低级错误,生产数据库崩溃了将近半个小时

鄙人薛某

Java MySQL 数据库 故障定位

深入理解队列:LinkedBlockingQueue源码深度解析

itlemon

阻塞队列 LinkedBlockingQueue Queue

【week05作业】

chengjing

正确的做事比做正确的事更重要

魔曦

架构师 极客大学架构师训练营

Uniapp使用GoEasy实现websocket实时通讯

GoEasy消息推送

uni-app websocket 即时通讯

week5

Geek_2e7dd7

架构师训练营 - 第 5 周学习总结

红了哟

阿里内推面试,挂在了一道简单的问题上…

小新

Java 阿里巴巴 程序员 架构 面试

最右JS2Flutter框架——开篇(一)

刘剑

flutter 大前端 探索与实践

搞懂Spring事务失效的8大原因,轻轻松松面试过关

码哥小胖

Java spring Spring Boot

老龄化时代的人机共生:京东数科以AI机器人推动产业增长

脑极体

啃碎并发(一):Java线程总述与概念

猿灯塔

记录一次拼多多Web前端面试【一面+二面+hr面】

阿文

面试 Spring Cloud Spring Boot Web

架构师训练营 - 第五周命题作业

牛牛

极客大学架构师训练营 命题作业 一致性Hash算法

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