我的应用程序的用户在地理位置上分散,数据存储在不同的区域。每个地区都有自己的数据中心和数据库服务器。
我想包含一个路由值来指示用户想要访问和连接的区域,如下所示:
/ api / region / 1 / locations /
/ API /区域/ 2 /位置/
/ API /区域/ 3 /位置/
根据传入的区域,我想更改正在使用的连接字符串。我认为这可以在中间件链中的某个地方执行,但不知道在哪里/如何。任何帮助表示赞赏!
答案 0 :(得分:2)
Loopback提供了一种方法MyModel.attachTo
(似乎没有记录,但是对它的引用是there)。
但由于它是一个静态方法,它会影响整个模型,而不是单个实例。
因此,为了在每个请求的基础上工作,必须在调用数据源方法之前切换数据库,以确保在它们之间没有任何异步启动。我不认为这是可能的。
这是一个使用操作挂钩的示例(并在dbRegion1
中定义所有数据源,包括datasources.json
)
不好,不要在下面。仅供参考
Region.observe('loaded', function filterProperties(ctx, next) {
app.models.Region.attachTo(app.dataSources.dbRegion1);
}
但是,当您的API在短时间内收到多个请求时,您很可能面临并发问题。
(另一种看待它的方式是服务器不再是真正无状态的,执行不仅取决于输入,还取决于共享状态)。
钩子可以为请求2设置region2
,而钩子之后调用的方法期望对请求1使用region1
。如果钩子和钩子之间触发了异步,则会出现这种情况。实际调用数据源方法。
所以最终,我认为你不应该这样做。我只是把它放在那里,因为有些人在其他SO帖子中推荐它,但它只是糟糕。
构建外部重新路由服务器,该服务器将请求从API服务器重新路由到相应的区域数据库。
使用API服务器中的loopback-connector-rest
来使用此微服务,并将其用作所有模型的单个数据源。这提供了对数据库选择的抽象。
当然,仍然存在实现微服务的问题,但也许您可以找到一些其他ORM而不是支持数据库分片的环回,并在该微服务中使用它。
创建一个自定义环回连接器,用作MySQL
查询的路由器。根据查询中传递的区域值,将查询重新路由到相应的DB。
使用更分散的架构。 编写特定于区域的服务器以保留区域特定的数据。 例如,运行3个不同的服务器,每个服务器都为一个区域配置。 + 1个用于路由的公共服务器
然后为面向用户的单个REST api服务器构建路由中间件。 基本示例:
var express = require('express');
var request = require('request');
var ips = ['127.0.0.1', '127.0.0.2'];
app.all('/api/region/:id', function (req, res, next) {
console.log('Reroute to region server ' + req.params.id);
request(ips[req.params.id], function (error, response, body) {
if (err) return next(err);
next(null, body);
});
});
也许这个选项最容易做到