不应该做的事情
Loopback 提供了一个方法MyModel.attachTo(似乎没有记录,但引用了它there)。
但由于是静态方法,它影响的是整个Model,而不是单个实例。
因此,要在每个请求的基础上进行此操作,您必须在调用数据源方法之前立即切换数据库,以确保两者之间没有任何异步启动。我认为这是不可能的。
这是一个使用操作挂钩的示例(并定义了所有数据源,包括datasources.json下面的dbRegion1)
不好,不要在下面。仅供参考
Region.observe('loaded', function filterProperties(ctx, next) {
app.models.Region.attachTo(app.dataSources.dbRegion1);
}
但是您很可能会在短时间内在您的 API 收到多个请求时遇到并发问题。
(另一种看待它的方式是服务器不再是真正的无状态,执行将不仅取决于输入,还取决于共享状态)。
钩子可能会为请求 2 设置 region2,而在钩子之后调用的方法期望为请求 1 使用 region1。如果在钩子和实际调用之间触发了异步,就会出现这种情况数据源方法。
所以最终,我认为你不应该那样做。我只是把它放在那里,因为有些人在其他 SO 帖子中推荐了它,但这很糟糕。
潜在选项 1
构建一个外部重新路由服务器,它将请求从 API 服务器重新路由到适当的区域数据库。
在您的 API 服务器中使用 loopback-connector-rest 来使用此微服务,并将其用作所有模型的单一数据源。这提供了对数据库选择的抽象。
那么当然还有实现微服务的问题,但是也许你可以找到一些除了loopback之外的其他支持数据库分片的ORM,并在那个微服务中使用它。
潜在选项 2
创建一个自定义环回连接器,作为MySQL 查询的路由器。根据查询内部传递的区域值,将查询重新路由到适当的数据库。
选项 3
使用更加分布式的架构。
编写一个特定于区域的服务器来持久化特定于区域的数据。
例如,运行 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);
});
});
也许这个选项是最容易做到的