PipyJS - 函数式网络编程语言
这篇文章主要介绍 Pipy 以及强大的 PipyJS - 没有垃圾回收开销、轻量级的函数式 JavaScript 解释引擎。
Pipy 概览
Pipy 是一个开源的、轻量级、高性能、模块化、可编程的云原生网络流处理器,适用于边缘路由、负载均衡和代理解决方案、API 网关、静态 HTTP 服务器、服务网格边车、策略即代码等应用场景。
技术术语有点多,我们继续深入了解一下。
轻量级
Pipy 的可执行文件只有 10MB 左右,没有任何外部依赖,仅需很少的内存就可以运行。
高性能
Pipy 是使用 C++ 并基于异步 I/O 库 Asio 开发的。
模块化
Pipy 的核心使用了模块化设计,提供了大量可复用的小模块(过滤器)。这些过滤器可以组装成管道,网络数据流经这些管道并被处理。
流处理器
Pipy 将网络流数据字节抽象成事件,以事件驱动的方式来操作网络流。提供了事件驱动管道的抽象,管道使用输入流、执行用户定义的转换并输出流。
可编程
Pipy 对外屏蔽了底层的细节,提供了类似拼图的编程方式来实现业务目标。Pipy 是通过强大的 PipyJS 实现的,也是接下来我们要详细介绍的。
为什么使用 JavaScript
就像标题介绍的,PipyJS 是基于 JavaScript 的。Pipy 决定使用类似 JavaScript 脚本语言是有原因的:
JavaScript 可能是世界上最广泛使用的语言
它的语法有 C 和 Java 的影子,因此对大多数程序员不陌生
Pipy 作为流处理器,意味着有大量的数据转换和重组的工作。通过 JavaScript 提供的很多强大的语法糖可以轻松搞定,比如展开语法、解构赋值、以及数组的 map()、reduce() 等操作
JSON 作为网络上最广泛使用的数据格式,JavaScript 提供了原生支持可以轻松操作
最后也是最最重要的,JavaScript 包含了“函数式编程”范式
Pipy 就像是一些彼此相连的管道一样。每个管道由一系列的过滤器组成,每个过滤器就像接收输入并返回特定结果的函数。对于这种设计模式,假如你的目标是保持连贯和简单,函数式编程语言是最适合 Pipy 的。
PipyJS 介绍
Pipy 通过自研的 PipyJS 组件来解析 JavaScript,该组件是 Pipy 代码库的一部分,但不依赖它。
PipyJS 是一个小且可嵌入的 JavaScript 引擎,专为高性能而设计,没有垃圾回收开销。它支持 ECMAScript 标准的子集,并且在某些方面进行了大胆的扩展。Pipy 拥抱纯函数式 JavaScript,在 PipyJS 中,万物皆表达式。
数据类型
与标准 JavaScript 一样, PipyJS 支持 4 种基本类型和结构数据的 对象 类型。
基本类型 Undefined:变量未初始化时的唯一值
undefinde
。布尔类型 Boolean:true
和false
。数字类型 Number:64 位双精度浮点数,如123
、0xabc
、3.1415926
、1e6
。字符串类型 String:Unicode 字符序列。结构化数据类型 Null 对象:唯一值
null
。用户定义的 POD(plain old data) ,如{ x: 1.2, y: 300 }
内置对象:比如 Array、RegExp。函数:比如(a, b) => a * a + b * b
。
操作符
PipyJS 支持所有的标准 JavaScript 操作符,包括一些在 ES2020 才引入的,比如 可选链操作符 和 空值合并运算符。
全局变量
全局变量在 PipyJS 中也叫做 上下文变量。这里的上下文概念等同于高并发网络编程中的连接,每个连接都有彼此独立的状态。在 PipyJS 中,为方便起见这些隔离的状态保存在全局变量中,这也是为什么有时我们称其上下文变量。这也很好理解为什么 PipyJS 全局变量与标准 JavaScript 不同,简单说就是在不同的连接中值不相同。这点上,有点像线程本地存储
全局变量通过内置的函数 pipy()
来定义,它通常是脚本中第一个调用的函数。
为了方便起见,全局变量使用下划线作为变量名的首字符,尽管不是语言强制的。
全局变量的作用范围是单个文件或者模块,多个模块间可通过 export()
和 import()
来共享。
为了方便起见,导出的全局变量名使用双下划线开头,但不强制。
本地变量
在 PipyJS 中,我们使用嵌套在局部变量函数范围内的函数参数作为本地变量。
假如想要上面的表达式执行后返回结果,则需要删除开头的
void
分支
在 PipyJS 中,万物皆表达式。不存在代码块或者流程控制,不能写 if 或者 for 语句。但这并不是说就不能写分支和循环了,而只是换了种形式:函数式。
简单分支可以使用逻辑运算符 &&
。
注意:上面是 PipyJS 分支语法,下面是标准 JavaScript 语法(下同)。
多选择分支可以将逻辑运算符 &&
和 ||
组合使用。
循环
可以使用 Array.forEach() 来实现简单有界的循环。
或者,对于通用条件循环,可以使用内置的函数 repeat()
。
派生 ECMAScript
PipyJS 专为速度设计,其结构对于编写高性能网络流处理逻辑至关重要。下面重点介绍 PipyJS 与标准 ECMAScript 的不同或者未实现的:
面向对象编程(OOP)结构 - 没有用户定义类型或者会构造器,没有原型系统
控制流
关键字
break
,case
,catch
,continue
,debugger
,default
,do
,else
,finally
,function
,for
,if
,return
,switch
,throw
,try
,while
,with
,yield
,class
,import
,export
,extends
,static
,super
类型系统 BigInt and SymbolStrings 内部存储为 UTF-8,在脚本中可以作为 UTF-32 来访问。比如
"😀".length
在标准 JavaScript 中是 2,但在 PipyJS 中是 1变量 - 没有用来声明变量的关键词
var
或者let
尽管 PipyJS 派生自标准 ECMAScript,但是通过函数式机制来填补空白。
如何使用
现在你应该对 PipyJS 有了一定的了解,接下来我们看下如何编写代码并运行。
首先下载对应平台的二进制文件,将下面的代码保存为 ”hello.js“。
然后使用刚刚下载的二进制文件执行该脚本。
这段脚本会监听 8080
端口,并返回信息 Hi, there!
。
总结
Pipy 是有 Flomesh 开源的、极其快速且轻量级的网络流量处理器,适用于多种场景。Pipy 正由全职的提交者和贡献者积极地开发和维护中,尽管还还是早期的版本,但已经过多个商业客户生产环境的实战测试。它的创建者和维护者 Flomesh.cn 提供了以 Pipy 为核心的商业级解决方案。
这篇文章对 Pipy 进行了简短的概述和高阶的介绍。在 GitHub 页面上可以找到教程和文档,也可以通过 Pipy 的管理控制台界面来访问。Pipy 社区非常欢迎贡献开发、尝试特定场景、或者提供简介和反馈。
版权声明: 本文为 InfoQ 作者【Flomesh】的原创文章。
原文链接:【http://xie.infoq.cn/article/4adbeaed8973a2442b96e31bb】。文章转载请联系作者。
评论