Open lius opened 8 years ago
You are right, there isn't too much documentation out there yet and we created https://github.com/feathersjs/feathers/issues/157 a little while ago to keep track of that. Here are some of my thoughts on the two topics you mentioned:
Let's assume we initially have a server with two services, maybe something like
app.use('/users', memory())
.use('/todos', memory());
The users service is getting more traffic than the one server can handle so we want to move it to another system by creating another app for it:
// server1
app.use('/users', memory());
// server2
app.use('/todos', memory());
For the /todos
service to now communicate with the remote service we can use Feathers as the client to connect to it (Websockets are fast and bidirectional so why not use them for server-to-server communication?):
// server2
const client = require('feathers/client')
const socketClient = require('feathers-socketio/client');
const io = require('socket.io-client');
const socket = io('http://other-server.com');
const otherApp = client().configure(socketClient(socket));
app.use('/todos', memory())
.use('/users', otherApp.service('users'));
This would basically transparently pass the user service to the remote service through a websocket connection. Anything using the original /users
endpoint won't have to change anything.
As for authentication, there is many different options. In the above scenario the easiest way would be for server1
to just whitelist the other servers IP address since server2
is still the only point of communication for the clients. Eventually server2
could just become a gateway that handles user authentication and then just passes service calls through to other servers (which don't have to worry about authentication other than checking the origin IP address).
Thanks for the response! Do you plan to cover this topic on official docs (maybe a sub-section of Guides)? Let me know if I can contribute in this regard.
Definitely. And we could definitely use some help. Maybe lets gather first what we'd like to see in a guide and then make some demo applications?
💯 @daffl is bang on. This is something that I am planning on tackling officially over the next month or so as I have committed to giving a presentation on it.
@daffl The approach you mentioned using feathers-client on a backend microservice allows bidirectional communication via streaming data, since socket.io is used. Feathers already has semantic/API for this scenario? I'm thinking on a situation where a microservice publish a event for other interested microservices, not a browser client.
Yes but why couldn't the other interested services also use websockets? We are thinking of adding other providers (e.g. for different messaging services) but for now websockets seem to be fast enough and it isn't written anywhere that they can only be used in the browser.
@daffl @ekryski as feathers applications become distributed, we would also need to address issues such as at-least-once delivery (acks), idempotency, transactions, backpressure (queues), etc. have you considered something like "feathers-service-worker?".. ie. external processes that consume events from durable amqp (ie rabbitmq) queue or redis (using ie kue)?
@daffl I think I did not understand well before your answer. As long as the interested services uses web sockets to subscribe to the producer service, using regular events API to publish new events on producer it's enough to implement this in feathers, right?
I agree with @justingreenberg, another issue to be addressed is replaying requests when the responsible microservices goes offline (crash, updates, etc). Technically, this would be address by using message queues too.
Any progress on this? I'd really love to see some documentation / a working example. Especially in regards to how authentication is handled.
@imns we are working on this. I started working on example and splitting an app up and we realized there are some limitations with how auth is set up. So we're currently refactoring auth to better support this. Should be about a week for that to land.
Oh man, I could use this so bad right now :D
Just out of curiosity are you reworking auth to work with multiple front-ends as well? I think a lot of larger apps now-a-days use a microservice on the backend, but also break their front-end apps up.
If you have a few extra bucks, I think this book could be considered recommended reading: https://www.amazon.com/Building-Microservices-Sam-Newman/dp/1491950358/ref=sr_1_1?ie=UTF8&qid=1469071253&sr=8-1&keywords=Microservices
Guys, any updates on this? Thank you.
@juanpujol the latest information will always be in this ticket. Thanks for checking, though.
(marcfawzi here)
I've not read the entire thread but I assume that we'll be able to use a database per service (in the Micreoservices architecture having this separation is crucial to maintaining the abstraction. Else, if all services share the same database what prevents folks from defining relations across service models (a violation of the microservices abstraction) instead of composing services using the uniform service API?
Nothing really prevents that, I'd say it's on you not to do that. It will only really be a problem if you define your models and relationships at the ORM level. I don't think that getting relationships at the service level by calling out to another services violates the microservice abstraction.
Yeah exactly what I meant. I tend to think that segregation of services where each service has its own db is a sure way to force composition via the service interface rather than at the ORM level.
But Feathers is more general than a Microservices framework, so all good here. Thanks David! This keeps looking better and better the more I dig into it! Great work all around!
Just thought I would mention this here are it solves some of the problems that come up with using Feathers in a micro services environment. It is only the first implementation but if you have anything to contribute feel free to here https://github.com/zapur1/feathers-rabbitmq/issues/1
@zapur1 that looks promising... I've posted a comment to get the discussion started
You can use also use https://github.com/feathersjs/feathers-sync with rabbitMQ, Redis, or MongoDB as the message brokers in between services to keep them all in sync.
@ekryski feathers-sync
solves a bit of a different problem, what if you only want a event to be received once within the realm of a named service(not a Feathers service but a microservices style service)? If you had multiple instances of a single service receiving events from a single API app each one will receive the event likely duplicating the actions that are taken when that event is received across multiple instances of the exact same code.
@ekryski I just had a look at the repo again and zapur1/feathers-rabbitmq solves the exact problem you mention in "Caveats"
if i connect a service 1 to service 2 by socketClient , so if my service 2 have multi instance , how can i implement load balance :(
If I create a separate serverside app that connects via socketClient what's the best way to authenticate so that any of the services are available regardless of any restrictions that have been set up.
I add my 2 cents on this with https://github.com/kalisio/feathers-distributed, it aims at deploying N feathers apps holding different services talking together, so that you can develop each one independently. It is different from https://github.com/feathersjs/feathers-sync which aims at deploying N feathers apps holding the same services as far as I understand. All of this raises a set of questions like:
@daffl on the example that you gave involving server 1 and server 2, how would you secure the /users
service in server 2? If we had that service defined in server 2 we could use hooks in the specific service hook file, but since we're doing app.use('/users', otherApp.service('users'));
, how would we make sure that calls to that service from server 2 would only be done if the user authenticated first?
EDIT:
Nvm, I think I have an idea: we could do something like const usersService = app.service('users')
and then usersService.hooks(hooks)
where hooks has the auth hooks required to secure the endpoint right?
I wrote more about how distributed authentication could be done in https://stackoverflow.com/questions/41076627/evaluating-featherjs-authentication-needs/41095638#41095638:
There are several ways of splitting up services each with their own advantages and drawbacks. One generally important thing for Feathers is that there are no sessions, just JSON web tokens. JWTs are stateless and can be read by any server that shares the same secret so there does not have to be a central session store. The two main options I can think of are:
I'm trying to find a practical/recommend way to extract services, separating them into their own instances, following microservices-style. In this matter, there is an interesting statement on the landing page of feathers:
But, I still could not find information about how to deal with this use case in feathers.
In practical terms, I'm focusing initially on two basic topics:
Thanks in advance!