lyft 的线下开发环境秘籍
几个月前听过一个老同事说早期 lyft 来国内交流的时候,展示过他们强大的线下开发环境,所有的前后端服务都可以在同一台电脑上启动,颇为羡慕,正好最近陶师傅分享了 lyft 的线下环境方案,感觉参考价值挺大的。
先来定义一下问题:现在微服务架构在国内互联网公司已经普及了,互联网公司的主流程服务比较复杂,尽管已经尽最大努力进行解耦,改造过后还是会依赖几十至上百的外部服务。这样导致的最大的问题是,业务研发在线下测试主流程服务极其困难。
如果你恰好在这样的环境工作,想一想,你在修改了主流程的代码之后,是不是没有办法在本地完成测试?是不是必须得把你的开发分支部署到远端的某个环境去?或者是不是必须部署到有 QA 维护的 Staging 环境才能开发 debug?如果中招了,那么你也应该看看 lyft 的方案。
多语言/多版本
在 lyft 内部的服务大部分是 Go 写的,少部分是 Python,前端环境需要用 Node,线下环境需要解决这些语言的运行问题。
- Python 主要是 Virtual Env 那一套
- Go 比较简单,你不知道怎么搞只要 Google 搜 Go multiple version 就好
- Node 和 Python 类似,nodeenv 之类的
这些没啥可说的。。
运行一个服务
基本的服务执行流程无非是下面这些步骤:
- Run environment checks (e.g. correct tools are installed, necessary git repos checked out, ports are free)
- Activate virtual environment (Python and Node services)
- Start datastores (e.g. dynamodb, elasticsearch, postgres)
- Start proxy app (more on this later)
- Run datastore population scripts
- Run the service
这些步骤人肉搞既费时又容易出错,自然要有工具来解决问题,这里 lyft 用了 Tilt 这个工具,
Tilt 能帮你自动初始化所有依赖项,服务只要开发运行,在 IDE 里修改代码会立刻重新加载服务,省去了你自己各种 make,build 的步骤。加快了线下的开发反馈循环。
向其它服务发请求
大多微服务都会通过 RPC 访问外部服务,这里主要有两种处理方式:
- Return a mocked response
- Forward the request to another environment with live services
这里的需求其实和前后端协作的时候,要解耦开发流程专门做的 mock service 很像,lyft 内部之前本来就给前后端解耦专门做了一个 proxy 应用,用 electron 开发的:
这个 APP 和 lyft 内部用的 pb 的 IDL 是深度集成的,用户可以直接在 monaco editor 来编辑依赖的外部服务返回的响应序列。因为是和 IDL 集成的,editor 内部也集成了类型检查和自动完成功能,还支持一些复杂的需求,比如把 request 中某个字段的数据填到 response 里。
lyft 扩展了一下这个 APP,直接让它可以支持这种本地开发模式的响应 mock 和响应转发,转发过程可以直接将请求转发到 staging 环境去。
向本地服务发请求
比较简单,在 editor 上可以自动补全本地服务的 URL 和 request,点个按钮就可以,不用你找 curl 或者 postman 之类的工具了。
结论
lyft 的这些工具发布给内部的 RD 之后,大部分的服务开发都可以在本地的电脑上完成,不需要开发者有任何的远端环境了。所有测试都可以在本机电脑上跑,包括 e2e 的集成测试。
同时后续可能也要去做一些比较小众的需求,比如把请求从 staging 环境转回到本地服务来,改进 UI 让新手能直接在内部的 API playground 找到可以参考的请求模板,以及一些更先进的方案如 Github CodeSpaces 等等。