如何做好 NodeJS 框架选型?
Posted 广吾的博客
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何做好 NodeJS 框架选型?相关的知识,希望对你有一定的参考价值。
作为一个有一定工作经验的工程师,工作中经常会遇到技术选型的问题。比如当我们在工作中需要使用到 NodeJS 时,第一个要解决的问题就是如何选择一个合适的框架。
不同的框架有不同的特点,如果我们仅仅从框架提供的能力出发,往往会迷失在对不同框架能力的对比中。如果能有一个清单,照着这个清单来考察每个框架,最终选出最符合要求的框架,那就真是太棒了!
我们今天就试图来讨论出一个检查清单,通过这个清单,我们可以找出最适合我们的框架。
我们的使用场景是什么?
使用场景是最重要的考虑因素。在选择框架之前,先搞清楚我们的诉求是什么。
下面是一些常见的需要考虑的点:
- 我们的应用是全栈应用还是只提供 API 服务? 如果只提供 API 服务的话,是 REST 接口还是 GraphQL 接口?
- 是否需要服务端渲染? 如果我们使用 React 或者 Vue 来开发页面的话,一些 NodeJS 框架本身提供了对这些 UI 框架的支持。
- 是否需要实时响应? 如果我们需要使用到 WebSockets,是选择一个支持 WebSockets 的框架,还是找一个社区维护的第三方库来集成到框架中?
- 是否支持 TypeScript? 我们是否要用 TypeScript 来开发应用?有些框架是使用 TypeScript 开发的,有些框架只提供了类型声明,而有些框架只有社区第三方维护的类型声明。即使我们不使用 TypeScript 开发,类型声明也可以通过编辑器提示给我们带来巨大的帮助。
框架的风格
有些框架除了处理 HTTP 请求和响应以外,还提供了类似于校验、日志、认证、数据库抽象以及依赖注入等其他丰富的功能。这些框架通常对开发者有一些额外的要求,比如要按照框架要求的形式来组织代码才能使用框架的一些能力。
有一些框架只提供处理 HTTP 请求和响应的基本能力。其他能力需要开发者自行实现或者从框架的生态中自行获取。使用这些框架的开发者自由度很高,可以自由组织代码形式。但是当需要一些其他功能时,开发者需要额外付出精力来筛选合适的社区实现。
还有一些框架采取了中庸的形式,即除了提供 HTTP 请求和响应的基本能力以外,还提供了稍许功能,比如日志和校验等。
选择哪种风格的框架,可以从上面列出的使用场景出发,也可以从个人和团队的风格偏好出发。
文档
丰富的文档至关重要。没有人会想一边开发业务,一边通过阅读框架的代码来了解框架的能力。如果一个框架没有文档,我们应该拒绝使用。对于有文档的框架,我们如何评价文档的质量呢?
可以从下面几点出发:
- 是否可以方便的查找? 比如文档的结构是否容易理解?是否提供搜索功能?
- 文档是否有意义? 文档很重要,有用的文档更重要。没有用的文档写的再多也没有意义。
- 当写代码的时候,这些文档是否能派上用场? 阅读和理解如果做一件事是一回事,动手做一件事是另一回事。在我们写代码的时候,文档是否可以直接明确的帮助我们?
实用的样例
说的再多不如写一个样例给我。阅读文档有时候会让我们迷失方向,如同坠入一团雾中。如果有一些官方提供的实用样例的话,对理解框架以及解决实际问题的帮助就很大。官方提供的样例通常也会是解决某一个具体问题的最佳实践。
通常,我们可以在框架源代码的 examples
目录中找到样例,有些框架还会有一个专门的仓库来存放各种各样的样例。
社区生态
一个框架的社区生态非常重要。在选择框架的时候,观察下框架是否有讨论组之类的东西。参与其中的人是否友好、是否乐于帮助他人等。
框架是否流行不能决定我们是否选择这个框架。但是我们在选择框架的时候,要了解是否有其他开发者也在使用。如果我们选择了一个被广泛使用的框架,那么我们通常可以找到其他开发者开发的类库(中间件或者插件等)。
一个仓库的 star 数量某种意义上能够代表框架的受欢迎程度。但是却不能准确的表达框架的使用情况,我们可以从框架的下载量着手。虽然有一些框架被其他类库内置使用,导致下载量很高,但是一定程度上可以说明框架在市面上的使用程度。我们可以在 npm trends 上看到框架的下载量变化。
项目的健康程度
当我们决定选择一个框架的时候,我们还需要确保这个框架在可见的未来时间内依然能够得到有效的维护。
我们可以从下面几个方面来考察项目的健康程度:
- 版本发布频率 即使一个框架的功能已经非常完善了,安全更新和问题修复依然十分重要。因此在面对已经暂停维护或者很长时间没有发版的项目的时候,需要慎重考虑。
- 官方在 issue 的活跃程度 如果一个项目的 issue 里官方成员的参与程度很低,可能在暗示这个项目已经不再维护了。相反,如果一个项目的 issue 很少,有可能说明社区对这个框架的使用程度很低。
- Pull request 一个健康的项目,通常都会有一些近期刚提交的 pull request。如果一个项目有很多很好的 pull request 没有合并,可能说明这个项目已经不再维护了。
- 贡献者 如果一个框架的贡献者只有一两个人,说明社区对这个框架的关注度不高。同时较少的贡献者,会给框架的长期维护带来不确定性。一个健康的框架,应该有很多贡献者参与进来。
- 项目依赖 一个有着很多依赖的框架,可能受攻击的地方也很多。同时,太多的依赖也可能给开发调试带来很多问题。我们可以通过 npmgraph 这个工具才查看一个项目的依赖情况。
这里有一些评价一个项目健康度的工具可以使用:
- Synk Open Source Advisor 这个工具会从多方收集一个包的数据,然后给出这个包的打分。
- GitHub 仓库的 "Insights" Tab 页 GitHub 上每个仓库中的这个 Tab 提供了这个仓库近期的活动情况,包括发版、pull request、issue 和贡献者等。
- Moiva 这是一个开源工具,与上面两个工具提供的能力相同。但是这个工具允许我们同时对比多个框架。
总结
在选择一个 NodeJS 框架的时候,我们有很多方面需要考虑。但是最后也是最重要的一点是,我们在使用这个框架的时候,是否享受使用它的过程。如果不是,那么即使框架解决了一些问题,我们也会非常难受。
选择一个靠谱的 NodeJS 框架有时候非常棘手,希望这个检查列表能给正在做框架选型的人一些帮助。
常见面试知识点、技术解决方案、教程,都可以扫码关注公众号“众里千寻”获取,或者来这里 https://everfind.github.io 。
Kubernetes网络自学系列 | 如何做好技术选型:容器组网方案沙场点兵
素材来源:《Kubernetes网络权威指南》
一边学习一边整理内容,并与大家分享,侵权即删,谢谢支持!
附上汇总贴:Kubernetes网络自学系列 | 汇总_COCOgsta的博客-CSDN博客
2.6 如何做好技术选型:容器组网方案沙场点兵
当前主流的容器网络虚拟化技术有Linux bridge、Macvlan、IPvlan、Open vSwitch、flannel、Weave、Calico等。而容器网络最基础的一环是为容器分配IP地址,主流的方案有本地存储+固定网段的host-local,DHCP,分布式存储+IPAM的flannel和SDN的Weave等。
任何一个主流的容器组网方案无非就是网络虚拟机+IP地址分配,即Linux bridge、Macvlan、IPvlan、Open vSwitch、flannel、Weave、Calico等虚拟化技术和host-local、DHCP、flannel、Weave任取两样的排列组合。以Macvlan+DHCP为例,这种方案一般通过以下步骤初始化一个容器网络:
(1)创建Macvlan设备。
(2)DHCP请求一个IP地址。
(3)为Macvlan设备配置IP地址。
而路由+IPAM初始化容器网络的步骤为:
(1)向IPAM请求一个IP地址。
(2)在主机和/或网络设备上创建veth设备和路由规则。
(3)为veth设备配置IP地址。
正如前文提到的。目前业界主流的容器解决方案大致可以分为“隧道方案”和“路由方案”,而这些方案其实都可以归结为容器网络的虚拟化方案。
2.6.1 隧道方案
隧道网络也称为overlay网络,有时也被直译为覆盖网络。其实隧道方案不是容器领域新发明的概念,它在IaaS网络中应用得也比较多。overlay网络最大的优点是适用于几乎所有网络基础架构,它唯一的要求是主机之间的IP连接。但overlay网络的问题是随着节点规模的增长,复杂度也会随之增加,而且用到了封包,因此出了网络问题定位起来比较麻烦。
典型的基于overlay的网络插件有:
·Weave:源自Weaveworks,包括Weave Net、Weave Scope和Weave Flux。Weave Net是一种用于构建和部署Docker容器的网络工具;
·Open vSwitch(OVS):基于VXLAN和GRE协议,但是性能方面损失比较严重;
·flannel:源自CoreOS,支持自研的UDP封包及Linux内核的VXLAN协议。
flannel的想法很好:每个主机负责一个网段,在这个网段里分配一个IP地址。访问另外一台主机时,通过网桥到达主机上的IP地址,这边会有一个设备,程序会把你发的包读出来,去判断你的目的地址是什么,归哪台机器管。flannel的UDP封包协议会在原始的IP包外面加一个UDP包,发到目的地址。收到之后,会把前面的UDP包扔掉,留下来的就是目标容器地址。这个方法有几个问题,第一个问题是要做封包的操作。第二个问题是每个主机上的容器是固定的,容器的不同主机之间的迁移必然带来IP的变化。使用UDP封包的一个比较大的问题是性能较差,我们会在后面的章节专门说明。
Weave和flannel用到的封包技术特点类似,不过使用的是VXLAN。另外,Weave的思路是共享IP而非绑定。在传输层先找到目的地址,然后把包发到对端,节点之间互相通过协议共享信息。
使用UDP进行封包的时候性能损失在50%以上,使用VXLAN也会有20%~30%的损耗。
2.6.2 路由方案
回过头来想一下,我们为什么要封包?其实它是改包,主要解决的问题是同一个问题,即在容器网络里,主机间不知道对方的目的地址,没有办法把IP包投递到正确的地方。传统的三层网络是用路由来互相访问的,不需要封包。至于路由规则怎么维护?传统的网络解决方案是利用BGP部署一个分布式的路由集群,如图2-7所示。
图2-7 传统BGP分布式路由集群方案
通过路由来实现,比较典型的网络插件有:
·Calico:源自Tigera,基于BGP的路由方案,支持很细致的ACL控制,对混合云亲和度比较高;
·Macvlan:从逻辑和Kernel层来看,是隔离性和性能最优的方案,基于二层隔离,需要二层路由器支持,大多数云服务商不支持,因此混合云上比较难以实现;
·Metaswitch:容器内部配一个路由指向自己宿主机的地址,这是一个纯三层的网络不存在封包,因此性能接近原生网络。
路由方案的另一个优点是出了问题也很容易排查。路由方案往往需要用户了解底层网络基础结构,因此使用和运维门槛较高。
在容器里怎么实现基于路由的网络呢?以Calico为例,Calico是一个纯三层网络方案。不同主机上的每个容器内部都配一个路由,指向自己所在的IP地址;每台服务器变成路由器,配置自己的路由规则,通过网卡直接到达目标容器,整个过程没有封包。
那么,路由交换是不是很难呢?用传统的BGP技术就可以实现。这个协议在大规模应用下是一个很好的场景,而且BGP有一个自治域的概念。在这个场景下会有一个问题,路由之间的信息交换实际上基于TCP,每两个之间都有一个TCP连接,规模大了维护这些连接的开销会非常高,具体解决方法我们会在后面的章节介绍。
Calico的设计灵感源自通过将整个互联网的可扩展IP网络原则压缩到数据中心级别。Calico在每一个计算节点,利用Linux Kernel实现高效的vRouter来负责数据转发,而每个vRouter通过BGP把自己节点上的工作负载的路由信息向整个Calico网络传播。小规模部署可以直接互联,大规模下可通过指定的BGP Route Reflector完成。保证最终所有的容器之间的数据流量都是通过IP路由的方式完成互联的。
Calico网络拓扑图如图2-8所示。
图2-8 Calico网络拓扑图
2.6.3 容器网络组网类型
关于容器网络对overlay和underlay的分类,常见的非主机网络(host network)的容器组网类型有L2 overlay、L3 overlay、L2 underlay和L3 underlay。主机网络前面章节中已有介绍,下面将分别介绍L2 overlay、L3 overlay、L2 underlay和L3 underlay。
1.overlay网络
overlay网络是在传统网络上虚拟出一个虚拟网络,承载的底层网络不再需要做任何适配。在容器的世界里,物理网络只承载主机网络通信,虚拟网络只承载容器网络通信。overlay网络的任何协议都要求在发送方对报文进行包头封装,接收方剥离包头。
L2 overlay
传统的二层网络的范围有限,L2 overlay网络是构建在底层物理网络上的L2网络,相较于传统的L2网络,L2 overlay网络是个“大二层”的概念,其中“大”的含义是可以跨越多个数据中心(即容器可以跨L3 underlay进行L2通信),而“二层”指的是通信双方在同一个逻辑的网段内,例如172.17.1.2/16和172.17.2.3/16。
VXLAN就是L2 overlay网络的典型实现,其通过在UDP包中封装原始L2报文,实现了容器的跨主机通信。
L2 overlay网络容器可在任意宿主机间迁移而不改变其IP地址的特性,使得构建在大二层overlay网络上的容器在动态迁移时具有很高的灵活性。
L3 overlay
L3 overlay组网类似L2 overlay,但会在节点上增加一个网关。每个节点上的容器都在同一个子网内,可以直接进行二层通信。跨节点的容器间通信只能走L3,都会经过网关转发,性能相比于L2 overlay较弱。牺牲的性能获得了更高的灵活性,跨节点通信的容器可以存在于不同的网段中,例如192.168.1.0/24和172.17.16.0/24。
flannel的UDP模式采用的就是L3 overlay模型。
L3 overlay网络容器在主机间迁移时可能需要改变其IP地址。
2.underlay网络
underlay网络一般理解为底层网络,传统的网络组网就是underlay类型,区别于上文提到的overlay网络。
L2 underlay
L2 underlay网络就是链路层(L2)互通的底层网络。IPvlan L2模式和Macvlan属于L2 underlay类型的网络。
L3 underlay
在L3 underlay组网中,可以选择IPvlan的L3模式,该模式下IPvlan有点像路由器的功能,它在各个虚拟网络和主机网络之间进行不同网络报文的路由转发工作。只要父接口相同,即使虚拟机/容器不在同一个网络,也可以互相ping通对方,因为IPvlan会在中间做报文的转发工作。
IPvlan的L3模式,flannel的host-gw模式和Calico的BGP组网方式都是L3 underlay类型的网络。
2.6.4 关于容器网络标准接口
笔者认为Docker 1.9以后讨论容器网络方案,不仅要看实现方式,还要看网络模型的“站队”,例如,用Docker原生的CNM,还是CoreOS,或是CNI呢?毕竟,云原生时代,标准为王!
1.CNM阵营
支持CNM标准的网络插件有:
·Docker Swarm overlay;
·Macvlan&IP network drivers;
·Calico;
·Contiv。
Docker Libnetwork的优势就是Docker原生与Docker容器生命周期结合紧密,缺点是与Docker耦合度过高。
2.CNI阵营
支持CNI标准的网络插件:
·Weave;
·Macvlan;
·flannel;
·Calico;
·Contiv;
·Mesos CNI。
CNI的优势是兼容其他容器技术(例如rkt)及上层编排系统(Kubernetes&Mesos),而且社区活跃势头迅猛,再加上Kubernetes主推,迅速成为容器网络的事实标准。
2.6.5 小结
(1)flannel仅仅作为单租户的容器互联方案是很不错的,但需要额外的组件实现更高级的功能,例如网络隔离、服务发现和负载均衡等。
(2)Weave自带DNS,一定程度上能解决服务发现的问题,但因隔离功能有限,作为多租户的联通方案还稍欠缺。
(3)Calico和Weave都使用了路由协议作为控制面,而自主路由学习在大规模网络端点下的表现其实是未经验证的,以笔者的网络工作经验看,大规模端点的拓扑计算和收敛往往需要一定的时间和计算资源。有意思的是,Calico在CNM和CNI两大阵营都扮演着比较重要的角色,既有着不俗的性能表现,又提供了良好的隔离性和ACL,但其基于三层转发的设计对物理网络架构可能会有一定的侵入性。
以上是关于如何做好 NodeJS 框架选型?的主要内容,如果未能解决你的问题,请参考以下文章
《Kubernetes网络权威指南》读书笔记 | 如何做好技术选型:容器组网方案沙场点兵