「开发全流程在线化」近些年来热度不断攀升,比如 AWS 在 C9 的实践、开源届比较出名的 TheiaJS,到后起之秀 code-server、行业佼佼者 VS Online 等。我个人以及我们团队对于「开发流程在线化」也做了较为深入的探索实践,从开始的懵懂迷茫到现在的目标清晰。
从 WebIDE 讲起
整个集团对于 WebIDE 的建设可以说起步较晚,当业界有了 Theia-IDE 的完整解决方案、coding.net 自己 CloudStudio 的商业模式,我们还在内部建设阶段。但好的方面,我们基于 IDE 技术领域及相关工具平台在近期如雨后春笋般涌现:Studio、IDE、K* 以及更广义的可视化搭建设计器等。
我们团队在 18 年调研过后决定基于 Ds 的 **Studio 来进行上层封装满足业务需求,后面由于种种原因不再适合放弃了。
19 年中,基于开源的 code-server) 和云原生 Kubernetes 的加持,我们自己打造了一款 YunIDE,由于需要花费大量的精力去调度运维 IDE 底层,这对于一个业务团队来说也是很难变现的,在第一版本迭代完成之后也选择迁移了。
最后我们基于 **IDE 并结合 XCloud 平台、Dawn 工具、云查询,打造了更加垂直易用的在线开发工具,打通了整个 I2P(Init to Publish)在线开发流程,对特定场景化及外包同学开发提效起到了关键性作用。
自建的过程与挑战
基本上 WebIDE 由三部分构成:
- Client: 客户端也是最重要的端,将代码编辑等本地功能移植到浏览器中。
- Server: 服务端也是控制端,包括管理数据交互及资源调度。
- Container Pool: 运行时,用户代码真正运行的容器环境。
三者之间最典型的架构如下图所示:
code-server 在很大程度上解决了 Client 端的问题,其本身基于 VSCode 二次开发,在体验及一些编辑器基础性问题上,我们不再去花时间重构,将重点精力放在 Server 端和 Container Pool。
服务端设计
YunIDE 从一开始就是面向云上设计的,所以在真正讨论架构的时候,更多的话语权在于使用云上基础设施 & 业界开源工具,所以在用户权限体系、容器资源调度、代码文件持久化方式等问题上,都与弹内的大部分 WebIDE 实践有所区别,一张早期的架构大图:
截止 YunIDE 第一个版本迭代,整个服务端开发对我个人而言挑战还是蛮多的,尤其是「资源调度 & 编排」这部分,需要对容器、Kubernetes 有足够深入的理解,对云资源、网络环境、集团现有基础设施中间件有一定的了解和经验。WebIDE 资源调度本身就是一个追求极限的过程(谁不想自己的 IDE 冷启动快一些呢),一丁点知识上的盲区都会带来雪崩版的负面影响。
编辑器 & IPC
编辑器端我们最大化的沿用了 Coder/VSCode 的实现,也就是这个原因,YunIDE 在最初的体感上要比 TheiaIDE 更舒服更接地气,而且通过对 VSCode 扩展体系的继承,可以获得几乎无限的想象空间。
我们扩展的功能也通过 vscode extensions 来实现,区别于三方扩展,内建的插件无法被移除。
IPC 这一层除了 code-server 所做的工作,YunIDE 在 HTTP 应用层对 socket IPC 做了代理和 Hack,做了相应的鉴权与应用层适配。
关键性问题
资源利用率:资源的合理编排以及最大化利用永远是我们追求的目标,在弱编辑场景(只编码不调试预览)如何在保证隔离性的基础上共享资源:
保证高可用性:缩短运行时生命周期,同时也要保证用户代码文件不丢失。最理想的状况是按 socket 连接数来动态的配置运行时容器,但技术上目前实现成本过高,只能以「小时/天」计算销毁周期。通过 NFS 挂载用户工作空间,用户数据不依赖运行时条件,做到数据可恢复。
启动速度优化:
完全冷启动:未知镜像的情况很难优化,但垂直场景下可以做到 1 分钟内。
预置容器池 + Container Buffer:体验很好,但造成一定的浪费。
插件生态:VSCode 官方插件体系已经足够完善,但也还有精进的余地,而且在集团前后端技术百花齐放的大背景下,界面的可定制性不够强等缺陷就凸显出来了(基于 TheiaIDE 的方案则更加灵活),vsc 官方插件市场是公开使用的,但由于协议等问题不能被直接使用。
自此而终,自建 WebIDE 的路上有过太多机遇与挑战,也有了相当程度的技术沉淀,逐渐的我们考虑快速将业务场景落地到集团基础设施,也就有了后面基于 **IDE 的 I2P 全流程在线化战役。
全流程在线化战役
基于集团现有基础设施如 IDE/K* 等可以很快构建垂直场景的在线开发环境,后面主要分享下我们的相关经验沉淀与提效成果。
环境定制
跟几乎所有 WebIDE 的环境准备一样,开发运行时开箱即用通过构建相应的 image 来实现。由于我们团队在前端基础建设上有了很多沉淀,比如 Dawn 脚手架、云查询、XCloud 等,在定制环境时要求变得更加苛刻。
通过在 Web 端前置云查询的 QTOKEN 授权体系,我们可以在 WebIDE 的终端环境拿到用户身份,甚至可以通过用户身份调用很多需要权限校验的接口。这极大的拓展了我们的可操作性,举个例子,通过用户身份可以很容易实现构建发布管控、日常错误收集、问题精准答疑等等:
同时镜像中集成了团队公共账号的一些公共权限,很多弱权限行为都通过统一公共账号管理和维护,比如:GitGroup 授权、npm package 发布、迭代关联工作项等等。
插件开发
基于 **IDE 封装的 IDE SDK 进行深度的 UI & 功能定制,如下图所示,封装了常用 dawn/命令行 操作:
在点击预览的时候我们做了很多优化处理:
- 由于插件运行在浏览器端,所以点击「预览」时通过 socket 向容器端发送指令查询当前可用端口。
- 排除 **IDE 及插件自身使用的端口,排除外部不可访问的(0.0.0.0),排除非 Node 进程开放的端口,剩下的基本上是我们的目标端口,实际使用下来体验也是比较好的。
- 通过内置的规则(仓库、人员信息、项目信息)来判断实际预览需要用到的域名,感谢 **IDE 团队的支持,目前我们可以在三个域名下进行预览开发。
对接 **IDE 的过程中,前端项目的有效预览问题我们这边算是做了些小小的贡献,推动了通过「泛域名解析」来完整的模拟本地预览体验。
本地方案:
- 启动 dev server
- 绑定 hosts local.foo.aliyun.com 来获取官网登陆状态联调接口
- 打开浏览器
WebIDE 方案 1:
- 容器运行时启动 dev server
- 绑定 hosts local.foo.aliyun.com 到容器的 IP
WebIDE 方案 2:
- 容器运行时启动 dev server
- 提供统一的域名 preview.ide.alibaba-inc.com 并通过 pathname 区分不同空间
WebIDE 方案 3:
- 容器运行时启动 dev server
- 提供可变的泛域名来隔离不同空间 [uniqueId]-[port].id*io.aliyun.com
方案 1 可以有效解决问题,但非常麻烦,需要用户手动绑定 Hosts 而且每次容器 IP 改变后都需要重新绑定,从产品的角度来说这个方案很不成熟,但也不失为一种降级方案。
方案 2 不能解决前端开发的问题,无法处理 HTML 中资源引入方式的多样性问题,比如 src="/index.js" 和 src="index.js" 行为就会不一致,很容易导致资源无法正常加载、页面无法正常预览。
方案 3 比较完美的解决了上述几个问题,但扩展性有所限制,每次新增一个业务域就要多申请一个泛域名。
最终,项目预览的效果如下图:
项目初始化
既然是 I2P 战役,自然少不了重中之重的 init 环节,本来在本地是很简单一行命令的事,在云端却不简单。
- 最开始的刀耕火种时代,我们自己维护了测试环境的 K8S 集群,使用 Jobs 来完成 init 操作。
- 后面由于太麻烦,迁移到了 ECI。
- 最后由于 ECI 没有走「镜像预热」,导致初始化时间太长(1-3 min),又从 ECI 迁移到了其他编排系统。
最终,这套 I2P 的成功实践也被复用到了其他 BU、其他团队,帮助其他业务场景快速实现「全流程在线化」。
场景化落地
从懵懂到笃定的过程中,我们搞清了这件事:找到你垂直的场景并发光发热。我们避免把 WebIDE 设想成一个大而全的系统,而是一个小而美的工具。下面是我们已经扎根的领域:
- XCloud VC 组件开发:中后台低代码物料
- 鸿蒙 ACE/国际站 组件开发:营销搭建物料
- Dawn 工程:服务于外包同学及其他快速开发场景
- 云查询 FaaS:Serverless 场景快速项目开发
每个不同领域在镜像、插件等层面做不同的兼容,整体入口收敛到 XCloud,最终完成 WebIDE 的场景化落地,同时也收到了许多肯定的赞许:
**战疫情,我们在行动
**
受疫情影响,很多同学不能正常复工,WebIDE 对于解决外包同学的开发环境问题显得尤为重要,我们也非常重视,积极改善功能、维持稳定、随时答疑,外包同学不再担心电脑安装各种环境的问题,从之前「几乎一整天都在装环境」到现在「打开浏览器 WebIDE 就能开发上线」,真正做到了「开箱即用」。
下图展示了从 XCloud 进入开发项目的过程:
最后
对文中内容有任何异议欢迎各位斧正。
阿里云中台前端团队大量 HC 等你来,欢迎联系:jitong.zjt@alibaba-inc.com
作者信息:赵吉彤,花名牧曈,阿里云智能-销售管理部前端工程师,负责前端基础设施建设。