背景
EPICS 是一个专业控制硬件的软件框架。与粒子物理学家的其它发明一样,它在其它领域也发挥了极大的作用。
场景
EPICS 框架自带一整套完整的工具以满足传统的需求,但在互联网时代,它无法满足许多新的需求。
一个EPICS无法回答的简单问题是:如何在 web 前端和 IOC 之间建立通信?
技术考量
作为一个全新的系统,必须符合一个最基本的工程原理:尽量符合现有的标准。基于这个考虑,可以得出 3 个基本指南。
- 使用微服务组成全系统。每个微服务仅提供一个简单但明确的功能。
- 通信协议和数据结构尽量简单,且在最小必要的 scope 中保持一致。
- 使用标准协议,工作流和库
基于以上考虑,必须有一个介于来自 20 世纪的 IOC 和 21 世纪的 web 之间的代理服务器。
设计
数据流
数据流是所有软件系统的基石。因此必须先确定数据流。
如上图所示,web 服务与 IOC 质检的通信经过代理中转。代理服务器将 EPICS 协议与 web 协议互相转换。
通信协议
基于以上架构,代理需要处理 2 种协议:web 服务和 IOC。前者有许多标准化协议,后者只有 2 种:CA 和 PV。
因为 PV 仅支持 EPICS 7+版本,为了兼容旧版本,代理应首先支持 CA。
考虑到caget
和caput
都是无状态方法,但camonitor
必须长时间保持开启,面向 web 服务的通信协议必须支持两种情况。因此 web 端最火的基于 HTTP 的 REST 通信架构不能满足需求。经过考虑后,Facebook 创立的 GraphQL 是此情景下的最优解。
框架
CA 和 GraphQL 都不是极度简单的协议,因此不可能自己造轮子,必须找到现有的框架。基于上面选择的两个通讯协议,代理服务器必须同时支持 2 个不同的框架:
- 一个 GraphQL 服务器
- 一个 CA 客户端
最成熟的 GraphQL 服务器是 apollo-server。它也是唯一一个默认支持 Subscription 功能的服务器框架。
唯一的 CA 客户端是 EPICS-base 自带的动态库。
实现
开发代理服务器并不简单,因此我将详细介绍开发中遇到的问题。
可行性
开发的第一步是:设计是否可能实现?
这个问题可以分为 2 个子问题:
- 是否可能将 CA 客户端和 GraphQL 融合起来
- 代理服务器是否以与网络中任意位置的 IOC 通信
第一个小问题已经被this tool 和 this tool回答了. 感谢这两个工具的开发者!
第二个小问题可以简单地用上面的两个工具做测试以证实可行性。
建立 Apollo 服务器
GraphQL 对新手并不想看上其那么友好。网上有很多工具可以帮助新手建立第一个服务器。this 和 this对我的帮助最大。
最核心的问题是理解 resolver 的作用。它在 GraphQL 标准中有详细的定义,因此不同的工具可以紧密合作。我习惯用 TypeScript 开发,因此type-graphql最适合我的要求。其实 code-first 服务器更加符合我的口味,但 Apollo 服务器不支持。
在将caget
,caput
和camonitor
分别用Query
,Mutation
和Subscription
实现后,服务器已经搭建好了。
连接 IOC
现在是最难的部分。 因为 apollo-server 只能在 Node.js 中运行,使用 JS/TS 是唯一的选择。但是,node-epics已经多年没更新,无法适配最新版 Node。 因此我自己制作了一个fork.
在付出了一把头发后,这个工具制作完成。它与 IOC 的通信已经通过测试。
其它问题都是几天就解决,这个问题耗费了我一个星期,是本项目中最困难的。
部署
因为代理服务器基于一个特定的 Node 版本,最好将其与适配的 Node 一起发布。因此容器是最好的解决方案。
我个人推荐使用 Kubernetes 管理容器。