文档结构  
翻译进度:已翻译     翻译赏金:0 元 (?)    ¥ 我要打赏

是的,请不要使用.

现如今构建实时应用程序已经变得很普遍。 在Crisp项目中,我们曾经在9个月的生产环境中使用Firebase。我们经历了从希望变成噩梦的过程,以下是我们的经历。

请注意,本文介绍的是使用Firebase实时数据库的生产环境方面内容,但我们依然认为此方案更适用于构建MVP、Hackathon项目或者一些简单的需求。

关于项目

我们为什么使用Firebase

Crisp是一个超级简单的、专注用户体验的在线聊天项目。我们想做一个经济有效的解决方案,因此我们决定使用Socket.IO服务去处理网站上在线聊天的实时数据,使用Firebase后台返回数据,所有数据通过AMQP分发。

第 1 段(可获 1.51 积分)

这种混合架构方式可以让我们只用3周时间做出一个MVP:完成在线聊天程序和后台,通过微服务让不同的人在相同的时间在线交流。这个瘦服务端的MVP程序,让我们可以专注UI和UX而不是服务端代码。

不幸的是

第一个月运行很好,然后我们在ProductHunt获得了精选项目展示。我们有了很大的用户增长,但问题也随之而来。

从海量的数据中,Firebase变成了一个噩梦,它拖慢执行速度。开发新功能变成了风险项目,并且往生产环境发布新内容时我们必须再三考虑。

第 2 段(可获 1.26 积分)

我们也同样发现Firebase的局限性,而当我们将流量扩展至60GB/月时,同样发现性能问题...

切换Firebase的10个理由

1 ) 面条代码(ps.指随意使用GOTO,并伴有异常,乱糟糟的线程控制等非结构化代码片段,详见维基百科)

瘦服务端,并不意味着代码少!那意味着所有服务端的逻辑现在转移到web端或者手机端上了。

在大多数应用中的开发过程中,你得先发送欢迎邮件,然后处理用户上传的图片(例如头像等),然后处理交易数据,最后才能使用核心商业功能。

但这些内容可能会因为使用Firebase而被黑掉,这意味着你必须在web端应用程序中编写更多的安全性代码,并且如果这些也需要在手机端应用程序中维护的话,那你就该做噩梦了。

第 3 段(可获 1.3 积分)

2 ) Firebase与微服务简直就像下地狱。。。

在Crisp项目中,我们在很多地方使用微服务,因为要查询数据库,获取用户信息,id等内容。

你可能会直接通过网络查询Firebase数据库,但如果数据在一个量级之上时应该避免这样做,因为实在是太慢了。

我们使用Redis缓存这些操作,那意味着我们必须同步所有数据。微服务承担着这个工作但是出现了内存问题,因为Firebase将数据缓存在内存中。

3 ) 价格问题

Server-less 端并不代表花钱也少,不不不。总有一天你会为懒惰付出代价。当收到这封邮件时你就必须得交钱了:

第 4 段(可获 1.35 积分)

Firebase付费层级有使用配额,如果超过了计划限额,则要加上超额费用。 你的Firebase,crisp-........,已经超过了它的计划限额,并且,由于我们的错误,我们没有收取超额费用。 我们将在下周修正此问题,这将导致您的帐户因任何超额使用而被收取费用。

[..]

非常感谢成为Firebase客户!

谢谢你的邮件。

每月支付100美元做那些你可以只花5美元就能在DigitalOcean服务器上做的事情,这值得你对server-less magic-less再三考虑。

第 5 段(可获 1.24 积分)

使用您自己的服务器代码,您将获得可维护性和生产力,您将拥有一个具有成本效益的代码库。

4)Firebase正在下载所有子树

假设你正在做一个Slack的应用程序,这意味着你将必须下载所有通道数据负载。

有些人会说,这可能是一些改进的分页,但使用Firebase,你不能分页,因为你不能得到查询数组的长度,你不能分页有序数组等...

5)你可能会有不一致

Firebase支持离线操作。 它的工作原理像“git commit”,但主要的问题是,如果你的客户端脱机然后在线,并且你有并发的一些输入(例如,共享记事本),你可能会有一些不一致,如合并问题。

第 6 段(可获 1.68 积分)

6 ) 数据迁移的问题

使用Firebase,你不能像传统的使用SQL数据库或者ORM、ODM框架那样简单的迁移数据,那意味着你必须在webapp里这样编写代码(更多的兼容性内容):

if (user && user.new_subdocument && user.new_subdocument.new_property) {  
//Do stuff
}

像这样的代码,到处都是.

6 ) 奇妙的关系。。。

用NoSQL处理数据关系是很困难的,可是用Firebase处理数据关系简直是屁眼疼。。。

比如,一个用户隶属一个组,一个组拥有多名用户.

user:

{
    name : "John Doe",
    team_ids : [...]
}
第 7 段(可获 0.99 积分)

team:

{
    name : "Acme Inc",
    user_ids : [...]
}

意思是用户必须等待team/ids填充并且team必须等待user/ids填充。。。这个例子很简单,但请想象一下面条般的关系数据。。。

7 ) 充满bug的队列

为了处理服务端代码和微服务,Firebase引入了队列机制用来共享服务端的操作和防止并发问题 (例如: 防止重复发送邮件).

这个功能Firebase团队没有很好的开发维护,并且有好几个bug,像同步问题,锁问题等等。

第 8 段(可获 1.05 积分)

9 ) 你的数据可不是你的

你只拥有“快”,而不拥有托管在服务器上的数据,因为你没办法导出用户数据,电邮地址,密码哈希。

当我们有上百兆托管数据时我们也不能导出他们。而只能用过邮件联系Firebase。

:从Firebase后台是不能导出数据的,但可以通过联系Firebase团队导出e-mail/password数据。

10 ) 不支持复杂条件查询

查询数据库的某个字段的某个属性有时候不可行。

例如,你想做个Slack那样的app,用Firebase你就没法统计得到未读消息的条数。解决办法是在客户端统计所有未读消息的条数。但那对于app来说是个很大的性能问题。

第 9 段(可获 1.58 积分)

不能执行相应的操作去获取激活的用户列表,或者批量操作更新具有某些字段的文档。

中奖了) 你也不能为你的产品创建一个API

现在,大多数app都提供开发API,但在Firebase上那是不可能的。

第一种方法可能是描述数据架构,跟用户解释如何查询,或者封装一个类库,但这不是标准做法而且这很难维护。

第二种方法是做一个HTTP封装,但最好的方式是使用自己的API配合自己的数据库,我们就是这么做的。

关于迁移数据

架构问题

第 10 段(可获 1.26 积分)

我们已经决定迁移到REST API。为了简单些,我们使用了一款“老式”数据库,它能处理大概90%的工作。它是关系型的,模型化的,并且用它可以完美的建立一个高防御的、简单的、可维护的API。

剩下的10%,我们决定使用MongoDB在高可伸缩的情况下存储消息和会话。使用UUIDv4作为主键,同时存放于MongoDB和自己的SQL数据库中,对所有人是透明的(跨应用程序!?)。

所有的CRUD操作通过REST HTTP层执行,其他的更新操作通过Websocket层执行。

更新操作通过AMQP转发,之后通过Socket.IO微服务进行同步,并且认证层会过滤你订阅的内容。

第 11 段(可获 1.5 积分)

简单、有效和可持续性。我们可以自由地切换到其他的socket.io引擎,从MongoDB迁移到别的东西。

开始编码吧

从 Paw (a Postman like app, for Mac)开始创建API,模拟所有节点,然后将他们揉进真实代码环境中。.我们使用Node.JS,但你也可以使用PHP,Ruby或者喜欢哪个就用哪个。

同时,我们删除了所有Webapp中的Firebase逻辑代码使其逻辑清晰,并且使用API进行所有的网络操作。

这两个部分花了大约三个星期,然后是迁移脚本,迁移测试和生产迁移。

第 12 段(可获 1.45 积分)

停下来歇歇

这种迁移使我们能够再次专注于执行时间和一些其他的产品中的事。

  • Web应用程序的加载时间让一些用户(处理多个会话)从20秒变成了2.5秒
  • 得益于MongoDB,出现了像搜索、分页等功能
  • 前端代码再次变得简单
  • 开发手机APP也变得简单了
  • 得益于良好架构和ORM数据迁移变得简单
  • 在需要时(比如申请折扣等),我们可以更加投入的编写查询数据库脚本。 如果你看到这句话,在Crisp你将得到30%的优惠。
  • 现在有了开发者API

感谢阅读,现在,要使用Firebase的话,还是再考虑一下吧!

第 13 段(可获 1.45 积分)

文章评论