最近在做一个新项目的技术选型,同时面临两个问题后端分布式协调用什么前端跨平台开发用什么。

这两个技术看起来完全不相关一个是后端分布式协调服务一个是前端跨平台开发框架,但是在我们的项目中都需要做选型,而且都面临一些选择的困惑,所以索性放在一起讨论分别分析它们的优缺点和选型考虑。

后端协调方面ZooKeeper是老牌的分布式协调服务成熟稳定用的人多,但是也有一些缺点,比如架构老旧性能瓶颈运维复杂等等现在也有一些新的替代品,比如etcdConsul等等到底该选哪个。

前端跨平台方面Flutter是Google推出的跨平台框架目前还是beta版(2018年10月Flutter 1.0还没发布预计年底发布)但是发展很快体验不错性能接近原生,但是也有一些问题,比如生态还不成熟学习成本Dart语言小众等等传统的跨平台方案,比如React NativeWeex也各有优缺点到底该选哪个。

本文分别分析了ZooKeeper和Flutter的优缺点适用场景以及,在我们的项目中的选型考虑希望能给大家一些参考。

一、ZooKeeper协调:老牌但可靠

先说说ZooKeeper这是后端分布式协调的老牌选手。

ZooKeeper是什么

ZooKeeper是Apache的一个分布式协调服务最初是Google的Chubby的开源实现后来贡献给Apache成为顶级项目它提供了分布式锁配置管理命名服务集群管理leader选举等等功能是很多分布式系统的基础组件,比如HadoopKafkaDubbo等等都用ZooKeeper做协调。

ZooKeeper的核心是一个树形的数据结构(ZNode)类似文件系统每个节点可以存数据也可以有子节点客户端可以对节点进行增删改查操作也可以注册Watcher监听节点的变化当节点变化时ZooKeeper会通知客户端实现分布式协调。

ZooKeeper的优点

  1. 成熟稳定:ZooKeeper存在了很多年(2008年左右开源)经过了大量生产环境的验证非常成熟稳定bug少可靠性高很多大公司都在用生产案例多。
  2. 功能丰富:ZooKeeper提供了丰富的分布式协调功能分布式锁配置管理命名服务集群管理leader选举队列等等基本能满足大部分分布式协调的需求。
  3. 一致性保证:ZooKeeper保证强一致性(CP)基于ZAB协议(ZooKeeper Atomic Broadcast)确保数据在集群中一致不会出现数据不一致的情况适合对一致性要求高的场景。
  4. Watcher机制:ZooKeeper的Watcher机制很强大客户端可以监听节点的变化当节点变化时ZooKeeper会主动通知客户端实现事件驱动的分布式协调很方便。
  5. 生态完善:ZooKeeper的生态很完善很多开源项目都支持ZooKeeper客户端也有,多种语言的实现JavaCPythonGo等等文档丰富社区活跃。

ZooKeeper的缺点

  1. 架构老旧:ZooKeeper的架构比较老旧是十几年前的设计,虽然稳定,但是也有一些历史包袱,比如ZAB协议复杂难维护性能在某些场景下不是最优。
  2. 性能瓶颈:ZooKeeper的写性能有瓶颈,因为所有写请求都要经过Leader然后同步到所有Follower写吞吐量有限大概每秒几万次写对于高并发写的场景可能不够。
  3. 运维复杂:ZooKeeper集群的运维比较复杂需要至少3个节点(奇数)才能保证高可用扩容缩容也比较麻烦需要注意脑裂数据同步等等问题对运维人员要求高。
  4. 不适合大规模存储:ZooKeeper的数据都存在内存中每个节点的数据量不能太大(建议每个ZNode不超过1MB总数据量不超过几个GB)不适合做大规模数据存储只适合存少量的协调数据。
  5. Watcher一次性:ZooKeeper的Watcher是一次性的触发一次就失效了需要重新注册对于需要持续监听的场景比较麻烦容易漏掉事件。
  6. 会话管理复杂:ZooKeeper的会话管理比较复杂客户端和服务端需要维持心跳会话超时的处理也需要小心临时节点的生命周期和会话绑定容易出问题。

ZooKeeper的适用场景

ZooKeeper适合以下场景:

  • 对一致性要求高的分布式协调场景
  • 需要分布式锁leader选举配置管理集群管理的场景
  • 已经有ZooKeeper运维经验和基础设施的团队
  • 中低并发写的场景(写吞吐量要求不高)

不适合以下场景:

  • 高并发写的场景(写吞吐量要求很高)
  • 需要大规模数据存储的场景
  • 没有ZooKeeper运维经验的小团队
  • 需要简单易用的协调服务的场景

二、ZooKeeper vs etcd vs Consul

说到ZooKeeper就不得不提它的两个主要竞争对手etcd和,Consul这三个都是分布式协调服务各有优缺点。

etcd

etcd是CoreOS开发的分布式键值存储用Go语言写的基于Raft协议保证一致性现在是,Kubernetes的默认存储后端非常流行。

etcd的优点:

  • 架构新设计简洁基于Raft协议比ZAB简单易理解和维护
  • 性能好特别是读性能很高写性能也不错
  • 运维简单部署方便配置简单扩容缩容容易
  • HTTP/JSON API易用支持多种语言的客户端
  • 支持事务(v3 API)能实现复杂的原子操作
  • 和Kubernetes生态集成好,如果用K8setcd是自然的选择

etcd的缺点:

  • 相对ZooKeeper年轻一些生产案例少一些(不过现在也很多了特别是K8s生态)
  • 功能相对ZooKeeper少一些没有内置的分布式锁队列等等需要自己基于API实现
  • 大value的性能不好不适合存大数据

Consul

Consul是HashiCorp开发的服务网格解决方案用Go语言写的基于Raft协议提供了服务发现配置管理健康检查KV存储等等功能。

Consul的优点:

  • 功能全面服务发现健康检查KV存储多数据中心支持都内置了开箱即用
  • 运维简单部署方便配置简单
  • 服务发现和健康检查做的很好适合微服务架构
  • 支持多数据中心天然支持跨机房部署
  • HTTP API易用支持多种语言的客户端
  • 和HashiCorp生态(TerraformVault等等)集成好

Consul的缺点:

  • 一致性模型和ZooKeeperetcd不同默认是最终一致(可以配置强一致,但是性能会下降)
  • 性能相对etcd差一些特别是写性能
  • KV存储功能相对简单不支持事务(旧版本)
  • 相对ZooKeeper和etcd社区小一些

三者对比总结

特性ZooKeeperetcdConsul
一致性协议ZABRaftRaft
一致性模型强一致强一致默认最终一致
性能
功能丰富度高(服务发现强)
运维复杂度
生态大数据生态K8s生态HashiCorp生态
适用场景传统分布式协调K8s/云原生微服务服务发现

我们的选型考虑

我们的项目是一个云原生的微服务项目部署在Kubernetes上,所以协调服务的选型我们倾向于etcd因为:

  1. 和Kubernetes生态集成好K8s本身就用etcd我们可以复用基础设施
  2. 性能好运维简单适合我们的小团队
  3. 架构新设计简洁易维护易扩展

但是我们也有一些历史系统用的是ZooKeeper(比如KafkaDubbo)所以我们也需要维护ZooKeeper集群对于新的服务我们会优先用etcd对于依赖ZooKeeper的旧系统继续用ZooKeeper逐步迁移。

所以结论是不是非此即彼而是根据场景选择合适的工具传统大数据生态用ZooKeeper云原生K8s生态用etcd微服务服务发现用Consul各取所长。

三、Flutter跨平台:新锐但有潜力

说完了后端的ZooKeeper再说说前端的Flutter。

Flutter是什么

Flutter是Google推出的跨平台移动应用开发框架用Dart语言开发一套代码可以,同时编译成iOS和Android应用也支持Web和桌面(目前还在开发中)。

Flutter的核心特点是自绘UI它不使用原生的UI组件而是自己实现了一套UI组件(Material Design和Cupertino)用Skia图形引擎渲染,所以UI在不同平台上表现一致性能也接近原生这和React NativeWeex等基于原生组件的跨平台框架不同。

Flutter目前(2018年10月)还是beta版最新是beta 6左右预计2018年年底发布1.0正式版,虽然还没正式发布,但是已经有不少公司在生产环境使用了,比如阿里巴巴腾讯等等都有Flutter的应用上线。

Flutter的优点

  1. 性能接近原生:Flutter自绘UI不经过JavaScript桥接(不像React Native)性能接近原生动画流畅60fps体验好这是Flutter最大的优势之一。
  2. UI一致性高:因为自绘UIFlutter的UI组件在iOS和Android上表现完全一致不会出现不同平台UI不一样的问题也不会,因为系统版本不同而有差异开发和测试都方便。
  3. 热重载:Flutter的热重载(Hot Reload)非常好用修改代码后秒级刷新不用重新编译安装大大提高了开发效率开发体验很好。
  4. 一套代码多端运行:Flutter一套代码可以,同时编译成iOS和Android应用节省开发成本和维护成本对于小团队来说很有吸引力。
  5. UI组件丰富:Flutter内置了丰富的UI组件Material Design和Cupertino(iOS风格)两套组件基本能满足大部分UI需求不用依赖第三方组件也能开发出漂亮的UI。
  6. Google背书:Flutter是Google的亲儿子Google在大力推广投入大发展快未来有保障,而且Google的新操作系统Fuchsia也是用Flutter做UI的未来想象空间大。
  7. Dart语言易学:Dart语言语法类似Java和JavaScript有,面向对象编程经验的开发者很容易上手学习成本不高。

Flutter的缺点

  1. 还没正式发布:目前(2018年10月)Flutter还是beta版还没发布1.0正式版API可能还会变化可能有一些bug和不稳定的地方用于生产环境有一定风险。
  2. 生态还不成熟:Flutter的生态还不成熟第三方库和插件相对React Native少一些一些常用的功能可能没有现成的库需要自己实现,或者通过Platform Channel调用原生代码增加了开发成本。
  3. Dart语言小众:Dart语言相对小众用的人不多招聘Dart/Flutter开发者比较难社区也相对小遇到问题可能不容易找到答案。
  4. 应用体积大:Flutter应用,因为包含了Flutter引擎和自绘UI所以安装包体积比原生应用大一些大概多几MB到十几MB对于对安装包大小敏感的应用可能是个问题。
  5. 不支持热更新:Flutter目前不支持热更新(CodePush)应用更新必须通过应用商店审核发布不能像React Native那样动态更新代码对于需要快速迭代热修复的应用可能不方便。
  6. Web和桌面支持还在开发:Flutter的Web和桌面支持还在开发中(Hummingbird项目和Flutter Desktop)目前还不成熟不能用于生产,所以Flutter目前主要还是移动端跨平台不是真正的全平台。
  7. 原生集成复杂:如果需要调用原生的功能,或者和现有原生应用集成(混合开发)Flutter的Platform Channel机制相对复杂调试也不方便混合开发的体验不是特别好。

Flutter的适用场景

Flutter适合以下场景:

  • 需要,同时开发iOS和Android应用的小团队节省成本
  • 对UI一致性和动画流畅度要求高的应用
  • 新项目从零开始没有历史包袱可以全面采用Flutter
  • 团队愿意尝试新技术有能力解决生态不完善的问题
  • 对应用体积和热更新要求不高的应用

不适合以下场景:

  • 需要大量调用原生功能,或者和复杂原生应用混合开发的项目
  • 对应用体积要求严格的应用
  • 需要热更新快速迭代的应用
  • 团队保守不愿意用beta版技术的项目
  • 需要Web和桌面支持的项目(目前还不成熟)

四、Flutter vs React Native vs 原生

说到Flutter就不得不提它的主要竞争对手React Native和,原生开发这三个是目前移动端开发的主要方案各有优缺点。

React Native

React Native是Facebook推出的跨平台框架用JavaScript和React开发一套代码可以,同时运行在iOS和Android它是基于原生组件的通过JavaScript桥接调用原生UI组件。

React Native的优点:

  • 成熟稳定已经发布多年生产案例多很多大公司都在用
  • 生态完善第三方库和插件非常丰富大部分功能都有现成的库
  • JavaScript开发者多招聘容易社区大遇到问题容易找到答案
  • 支持热更新(CodePush)可以动态更新代码不用通过应用商店
  • 和React生态集成好,如果团队已经用React做Web开发技术栈统一

React Native的缺点:

  • 性能不如Flutter和原生,因为有JavaScript桥接复杂动画和大量UI的场景可能卡顿
  • UI一致性不如Flutter因为基于原生组件不同平台和,系统版本UI表现可能不一样
  • JavaScript桥接的存在导致原生交互复杂调试麻烦
  • 版本升级经常有breaking change升级痛苦
  • 应用体积也比较大

原生开发

原生开发就是用iOS的Swift/Objective-C和,Android的Java/Kotlin分别开发两套应用。

原生开发的优点:

  • 性能最好体验最佳能充分发挥平台的能力
  • 生态最完善所有新功能都是先支持原生
  • 调试和工具链最成熟开发体验好
  • 没有跨平台框架的限制能做任何事情

原生开发的缺点:

  • 成本高需要两套团队两套代码开发和维护成本都高
  • 迭代慢两个平台分别开发发布周期长
  • 对小团队不友好很难,同时维护两个平台

三者对比总结

特性FlutterReact Native原生
性能接近原生中等最好
UI一致性低(平台差异)
生态成熟度中(发展快)最高
开发成本低(一套代码)低(一套代码)高(两套代码)
热更新不支持支持不支持(iOS)
应用体积较大较大
学习成本中(Dart)低(JS/React)高(两门语言)
适用场景新应用/UI要求高已有React团队/需热更新对性能要求极高

我们的选型考虑

我们的项目是一个新的移动应用从零开始团队之前,主要做Web开发有React经验,但是也愿意尝试新技术。

我们对UI和动画的要求比较高希望应用流畅漂亮两个平台体验一致我们的应用不需要热更新(内容通过API动态获取不需要更新代码)对应用体积也不是特别敏感。

综合考虑我们倾向于选择Flutter因为:

  1. 性能接近原生UI一致性高符合我们对体验的要求
  2. 热重载开发体验好提高开发效率
  3. 一套代码两个平台节省成本适合我们的小团队
  4. Google背书发展快未来有保障
  5. 我们愿意尝试新技术有能力解决生态不完善的问题

但是我们也会注意风险,因为Flutter还没正式发布我们会先做一个小的MVP验证Flutter的可行性和团队的适应度没问题再全面采用,同时我们也会关注Flutter 1.0的发布及时升级。

所以结论是对于我们的新项目我们选择Flutter但是会谨慎验证控制风险。

五、写在最后

以上就是我们在项目中对ZooKeeper和Flutter的选型分析和考虑,虽然这两个技术完全不相关,但是选型的思路是相通的。

技术选型没有绝对的好坏,只有适合不适合每个技术都有自己的优缺点和适用场景关键是根据自己的项目需求团队情况未来规划综合考虑选择最适合自己的技术而不是盲目追新,或者固守老技术。

对于ZooKeeper它,虽然老旧,但是成熟稳定在传统大数据生态中依然有不可替代的地位而etcdConsul等新选手在云原生微服务场景下更有优势根据场景选择就好。

对于Flutter它,虽然还年轻没正式发布,但是发展快体验好潜力大对于新的移动应用是一个值得考虑的选择,但是也要注意风险谨慎验证不要盲目上生产。

最后用一句话结束这篇文章:"技术选型没有银弹,只有适合深入理解每个技术的优缺点结合自己的场景做出最适合的选择才是正确的选型之道。"

愿大家都能选到适合自己的技术做出优秀的产品。