strongloop/loopback - Change connection string based on route value

梦想的初衷 提交于 2020-06-28 04:17:09

问题


My application's users are geographically dispersed and data is stored in various regions. Each region has it's own data center and database server.

I would like to include a route value to indicate the region that the user wants to access and connect to, as follows:

/api/region/1/locations/

/api/region/2/locations/

/api/region/3/locations/

Depending on the region passed in, I would like to change the connection string being used. I assume this can be performed somewhere in the middleware chain, but don't know where/how. Any help is appreciated!


回答1:


What should not be done

Loopback provides a method MyModel.attachTo (doesnt seem to be documented, but a reference to it is made there ).

But since it is a static method, it affects the entire Model, not a single instance.

So for this to work on a per-request basis, you must switch the DB right before the call to the datasource method, to make sure nothing async starts in between. I don't think this is possible.

This is an example using an operation hook (and define all datasources, include dbRegion1 below in datasources.json)

Bad, don't that below. Just for reference

Region.observe('loaded', function filterProperties(ctx, next) {
   app.models.Region.attachTo(app.dataSources.dbRegion1);
}

But then you will most likely face concurrency issues when your API receives multiple requests in a short time.

(Another way to see it is that the server is no longer truly stateless, execution will not depend only on inputs but also on a shared state).

The hook may set region2 for request 2 while the method called after the hook was expecting to use region1 for request 1. This will be the case if something async is triggered between the hook and the actual call to the datasource method.

So ultimately, I don't think you should do that. I'm just putting it there because some people have recommended it in other SO posts, but it's just bad.

Potential option 1

Build an external re-routing server, that will re-route the requests from the API server to the appropriate region database.

Use the loopback-connector-rest in your API server to consume this microservice, and use it as a single datasource for all your models. This provides abstraction over database selection.

Then of course there is still the matter of implementing the microservice, but maybe you can find some other ORM than loopback's that will support database sharding, and use it in that microservice.

Potential option 2

Create a custom loopback connector that will act as router for MySQL queries. Depending on region value passed inside the query, re-route the query to the appropriate DB.

Option 3

Use a more distributed architecture. Write a region-specific server to persist region-specific data. Run for instance 3 different servers, each one configured for a region. + 1 common server for routing

Then build a routing middleware for your single user-facing REST api server. Basic example:

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);
  });
});

Maybe this option is the easiest to do



来源:https://stackoverflow.com/questions/39887093/strongloop-loopback-change-connection-string-based-on-route-value

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!