Limbo: 简单访问远程数据库

简单高效的项目协做工具 Teambition 自诞生以来,一直致力于用技术重塑人们的工做方式,但愿为人们的工做方式带来最好的协做体验,除了 Teambition 以外,咱们还有日程管理工具 「今天」,这一次,咱们又有新的产品线 「简聊」 要上线了,正如它的slogan「简聊一下,轻松协做」所表达的,它是一款slack风格的,基于企业的简单聊天工具。虽然说简单,但倒是为效率和协做而生的企业IM工具,它继承了 Teambition 企业级基因,打通了项目协做工具 Teambition ,用户能够直接经过 Teambition 帐号登陆。它以话题为中心的群组讨论聊天模式,用slack的方式促进交流,将企业内沟通、任务、人员、文件等各类要素和流程打通。有利于基于目标向,提高专一度,完成任务,过滤出团队聊天中最有效的信息。若是有些话题讨论须要其余外部人员的参与,只须要发送邮件便可邀请对方加入话题讨论。node

欢迎你们试用咱们的 「简聊」,第一个版本上线不免颇有多不足,请你们踊跃提需求和意见,帮助咱们前进。git

许晶鑫是本次负责 「简聊」 开发的工程师,如下这篇文章是他在开发 「简聊」 这款应用的过程当中的经验谈。github


Limbo: 简单访问远程数据库

简聊一下 轻松协做

对于 nodejs 生态来讲,使用 mongoose 做为 Model 模块是再好不过的一件事,其一大特色就是简洁优雅的 Schema 定义,提供了每一个键值的类型验证,数据验证,索引声明,虚拟键,并自带实例化方法的扩展,大大节省了开发的成本。可是在考虑开放数据的时候,一切就显得不那么美好了。mongodb

在打造 「简聊」 这款应用的过程当中,咱们就实实在在的遇到了这样的问题。因为须要使用 Teambition 的用户和团队数据,而且当 「简聊」 更新了用户数据以后,在 Teambition 中能实时的将这些更新推送到用户那里。按照惯例,咱们最初使用的是 restful 接口。数据库

第一阶段,使用 restful 接口

restful 接口的应用面最广,可是仍然存在不少不足,好比接口在参数和结构上限制较多,在考虑修改接口 api 的时候,每每会顾虑客户端的兼容性,而一旦客户端程序有新的需求,则需等待接口的更新。另外一个麻烦的地方是须要作签名校验,对于内部的应用来讲,咱们彻底能够经过防火墙来控制特定 ip 对端口的访问,签名在此处就显得有点多余。后端

第二阶段,单独拆封 Schema

而后咱们想到了将 Schema 拆封成一个单独的仓库,nodejs 有良好的模块管理,在不一样的应用中,咱们只须要将这些模块引入进来,既作到同步更新,又作到 DRY。相对于 restful 接口的缺点就是,对于数据的调用入口过多,并且应用之间互相是不知情的。例如在 「简聊」 中有更新用户数据,在 Teambition 中就没法得知,并推送给其余客户端。api

第三阶段,远程过程调用(rpc)

这个阶段和 restful 接口其实相似,咱们在 Teambition 的后端进程中将一些接口方法暴露出来,这样咱们的客户端程序就能经过简单的 rpc 方式调用这些接口。例如咱们导出了 user.update 方法,在客户端代码中使用 rpc.call('user.update', params, callback) 便可调用相应的过程。这样的调用行为与使用本地代码无异,多是目前能找到的最简单直接的方式了。restful

第四阶段,rpc 与 mongoose 的结合

事情能够变得更简单,因为目的主要是为了操做数据库,因此咱们开发了一个模块 limbo,将 mongoose model 中全部方法暴露出来,以命名空间来划分,实现了在客户端与服务端程序一致的使用体验。tcp

例如咱们在服务端程序中使用 limbo 链接 mongodb,只须要作以下声明:(如下的代码都以 coffeescript 做为示例)mongoose

limbo = require 'limbo'

# 定义 Schema
UserSchame = (Schema) ->
  # 这里的 Schema 即 mongoose.Schema
  new Schema
    name: String
    email: String

# use 方法用做区分不一样数据库链接的命名空间,通常参数选择数据库名就行
db = limbo.use('test').connect('mongodb://localhost:27017/test').load 'User', UserSchema

使用方式就与 mongoose 一致了

user = db.user
# user 是一个 limbo 中用于封装 model 的一个对象,你能够直接使用 user.model 来直接调用 mongoose model
user.findOne _id: 'xxxx'
user.create name: 'xxx', email: 'yyy'

下面是 limbo 中最激动人心的地方,你能够导出一个 collection 中的全部方法到 rpc server 中,只须要经过一个简单的声明

limbo.use('test').bind(7001).enableRpc()

下面咱们就要提到如何在客户端程序中调用这些方法

# 在客户端也须要初始化一个 limbo 命名空间,须要与服务端一致,连接改成服务端的域名和端口号
db = limbo.use('test').connect('tcp://localhost:7001')

# 下面有两种方式来使用 rpc
# 1. 使用 call 方法
db.call 'user.findOne', _id: 'xxxx', ->
# 2. 使用方法链
db.user.findOne _id: 'xxxx', ->
# 第二种方式存在一个延迟,必需要在 limbo 与服务端程序握手成功以后才可使用,
# 不然会抛出一个对象不存在的异常,不过在通常的应用中,
# 初始化所需的时间都会长于这个连接所需时间,因此延迟能够忽略不计了

能够看出,上面的第二种方式与服务端在本地使用 mongoose 的方式如出一辙,这种黑魔法式的调用方式应该是广大码农喜闻乐见的。

limbo 另外一个值得称道的功能是能够在服务端程序监听这些远程调用的事件,这得益于 nodejs 的 event 对象,limbo 自己就继承于 EventEmitter 对象,因此咱们在每次远程调用后会触发一个事件给服务端程序,而在服务端只须要简单的监听这个事件便可

limbo.on 'test.user.findOne', (user) -> ...

正是这种 rpc 加事件反馈的机制,让 「简聊」Teambition 能够实现简单实时的数据交换。咱们将 limbo 托管在 github 上开源,是深知它还存在不少能够改进的地方,因此难免庸俗的说一句,欢迎 issue 和 pr~


最后,欢迎使用咱们的新产品 「简聊」 ,一款基于话题的轻量级协做应用。

相关文章
相关标签/搜索