Context
I m having two microservices :
User that manages users (crud operations)
Billing that manages billing informations, with a reference to a user
Actually, for me (tell if I m wrong) it's a good idea to store user informations into billing data using hateoas. So we can "walk through it" with an hyperlink in the response of the API right ?
We could obtain something like :
billing:{
// some informations
_links:{
owner:"http://80.80.80.80:7000/users/123456789"
}
}
Questions
How should I do, to create a new billing ? In fact, when somebody post a new billing on the microservice, he sends the user too. Does it mean that I need to have a UserEntity in my Billing service AND my User Service ? So the billing service will be able to marshall the request, meaning code duplication between the two services ? Or should I do something else ?
Then, is this the role of the front end (API consumer) to make 2 requests (one for billing, and one for the user related to the billing) to get the ressource ? Or should the BillingService get the User before responding to the front ?
I have seen in an article, that it's a good thing to use amqp / bus when dealing with microservice, to know if a ressource exists, or to check if it exists. Now we need a service container/registry to dynamically discover other services. In my case I use Zookeeper. But how can I do to tell Zookeeper "give me the location of the service(s) related to the ressource with hateoas links : http://80.80.80.80:7000/users/123456789" ? Am I missing an important information in my hateoas schema ?
How should I do, to create a new billing ? In fact, when somebody post
a new billing on the microservice, he sends the user too. Does it mean
that I need to have a UserEntity in my Billing service AND my User
Service ? So the billing service will be able to marshall the request,
meaning code duplication between the two services ? Or should I do
something else ?
The user that the billing service need is not the same one in the user service. Usually, the user's identity is all the consumer need to post a new billing. If the billing service need more information of the user, it may query from the user service. There may be some code duplicates here, but the code plays different roles in each service which means they can evolve without disrupting each other. Some questions may explain further here: Bounded contexts sharing a same aggregate, Handling duplication of domain logic using DDD and CQRS
Then, is this the role of the front end (API consumer) to make 2
requests (one for billing, and one for the user related to the
billing) to get the ressource ? Or should the BillingService get the
User before responding to the front ?
I think it brings the most flexibility to let API consumer navigate the links. What if the consumer is not interested in the owner detail?
I have seen in an article, that it's a good thing to use amqp / bus
when dealing with microservice, to know if a ressource exists, or to
check if it exists. Now we need a service container/registry to
dynamically discover other services. In my case I use Zookeeper. But
how can I do to tell Zookeeper "give me the location of the service(s)
related to the ressource with hateoas links :
http://80.80.80.80:7000/users/123456789" ? Am I missing an important
information in my hateoas schema ?
Not quite understand this one. If the consumer has the link like "http://80.80.80.80:7000/users/123456789" already, it can access the resource directly. Why should it ask the zookeeper? I think the zookeeper helps the billing service assemble the URI for owner. For example, the billing service tell the zookeeper "Give me the location of the service related to user resource".
Another solution would be that you store all the necessary information in both services. E.g., if you need data of the user within a billing, then just store all the data in the billings datastorage as well. The sync between both services you would do through a queue ( subscribe / publish ). This comes with pros and cons but in the end you end up having one synchronous http call, if you want receive the data for a specific billing.
Related
I am building a system based on microservices. It is a web application connected to different rest APIS. Now I want to implement the authorization system, (not authentication), so basically I want to be able to define, which users on the system can perform which actions.
So I am thinking to implement a role/permission system for that.
However, I have a dilemma about the two different architecture options that come to my mind, I and would like to know your thoughts, advices, pros and cons, to move forward with it.
There will be a specific microservice to handle the user permissions and roles, so basically this microservice will have access to two database tables making the association between the user and roles, and roles and permissions. This is the common part to the two solutions I have considered.
Now both options with pros and cons in my opinion:
1) Keeping for each microservice, a cache table with the user permissions specific to that microservice. So, every time a user wants to perform an action on that microservice (let's say, delete an order on the ordering microservice), the microservice will check that table, granting or not access to the user to perform the action.
Pros: every microservice is really a microservice, an independent service that can work totally autonomously of the rest of the system. If the main microservice handling the user permission crashes and it is not available, the rest of microservices will continue to work.
Cons: If I update the user permissions in the microservice that handles this, I need to send a message to all microservices to update their correspondent permissions tables.
2) Creating a API gateway microservice to act as a middleware between the frontend and the rest of microservices and use graphql in it. Frontend will no longer know about the rest of microservices, only will know about this one.
This microservice will intercept all request from the frontend, check with the user-permissions microservice if the user has permission to do the action, and if so, calling the correspondent microservice.
Pros: All the business logic to decide if the user has or not access is in a single microservice, instead of being duplicated across microservices. Also, authentication only needs to be implemented in the middleware microservice, no need to double check if the user is authenticated on the internal microservices as if we got there, is because we were succesfully authenticated previously.
No need to update cache tables in the internal microservices if the user roles or permissions are updated.
Cons: This defeats the definition of microservice architecture. I.e If the middleware microservice crashes, the whole system will be down.
I would like to know your thoughts!!
Thank you!
Assuming a resource X(http://example.com/a/foo/7) from rest-service A needs to hold a reference to a second resource Y(http://example.com/b/bar/1) from rest-service B.
How would one persist the reference?
Currently I'm storing the whole URI (as a string) of Y in the persistence layer of service A. Is this a common/valid approach?
It seems wrong to me to extract the id(1) out of Y's URI as I would implement assumptions about the URI structure of service B in service A. Is this correct?
How do you solve this problem?
Thx!
Lets discuss it with some actual business domain , then the answers will make sense.
So first example:
X represents Order Entity in Amazon Order Service, Y represent Customer in Customer Service.
Now while fetching the order from Amazon from Order Service, you also want to show some basic customer detail and link to customer Object to go to Customer Detail Page.
In this case what I would do is while creating the order copy some basic attributes of the customer in Order Entity (customerName , customerArea).
Also store customerId, customerType. And as the API for fetching customer is Public and also exposed to various internal services, Order Service will do a Service discovery and create URL and call. In these cases generally customer service will not stop supporting the old way (even if they are building a new one).
So storing just the id is a solution.
CASE 2:
Amazon Order Entity wants to store delivery details and delivery partner is some third party entity like DHL , then if DHL provides a URL to fetch the delivery updates to the order, in those cases I will just store the URL.
Generally I will prefer to store id and service type and some basic details to create a good customer experience and also avoid hitting one extra service api for getting the basic detail like customer name.
Storing direct URL makes sense when its a third party URL.
Also if you can give certain example of your business case like this, we can discuss better
IMO references should be stored as is. How you get the actual data from reference should not be part of the data but the logic which may change from time to time.
I will store them as reference of external reference (just to paint the picture that reference is out side our service) and coupled it with a logic to query the data.
URL is very volatile and may change. As a rule of thumb you should never keep urls in you database and should rely on service discovery to identify where the service is even if its within you own infra.
Its not an assumption, its a contract, which may changes and if it does, your service will be dependent service and has to make due changes
Also by your logic, even if you keep url, response to it is still a contract that both of you adhere to.
Would like to get some opinion on designing a system with subscription model using microservice architecture.
We implemented an identity server which authenticates and authorizes
users, and stores their subscription profile. (i.e. resources they can
access like which magazine and issues)
on the resources service, the subscription profile will be used to
filter their eligibility. example, if their subscription starts from
Year 2018, then this will take effect and return only year 2018 data
to the users via REST API.
Is this a standard/proper microservice architecture implementation? or any better ways to design this?
I'd argue no, especially if you want to embrace the principles of microservices - you're storing authorization and application domain specific data in your Identity server. Your IDP should only be concerned with authentication concerns.
I'd suggest a separate service or set of services for managing and retrieving this additional information that is linked to user entities in your IDP via a correlating ID (e.g. subject ID, email address, account code etc). This service would own its own data and be consumed by anything which needs to know about subscriptions and the like.
Are there any best practices to minimize the exchanged data between (internal) microservices when calling the API of a service (aka Need-to-Know)?
How to achive something like this:
There are three services:
User
Notification (let's assume just email)
Shipping
When the notification service needs the email address of a user it queries the API of the user service and should get the email (and NOT the full data set).
When the shipping service needs the shipping address of a user it queries the API of the user service and should get the shipping address (and NOT the full data set).
Question:
Should this be handled inside the user service with kind of an ACL (what service "XYZ" is allowed to see)?
Using JWT for authentication, there is a need to exchange keys at all, so during the setup-phase these ACLs could be discussed between the teams.
Should this be handled inside the user service with kind of an ACL
I think this is the best option. You could delegate the actual authorization to a separate service which the User service can call with the identity of the caller and the "claim" the caller is making (eg "I am allowed to see Email Address for User"). The claims can be evaluated on a per call basis.
However, is is arguable whether you actually need to query the user service at all. It would mean a change to your design but imagine for a minute that the Notifications service already knew about the user, for example the user ID and email address, then the notifications service would not need to query anything to be able to do it's job.
In order for the notifications service to have the user data already, it is necessary for that data to have been sent to the notifications service at some point in the past. A good time to do this would be when the user is first created, or any time a user details are changed. The best way to distribute this kind of information is in the form of an event message, although you could have the distribution based on an http POST to the notifications service.
Context
I have to create a RESTFul API which deal with :
Books
Category of books
The application is splitted like this :
Each client has an API key
Each user of a client can manage (get/post/put/delete) multiple books / categories of books related to the client he is linked to.
Following the REST principle, only the person that creates the ressource, "the ressource owner" can manage this ressource.
First problem
However, in this context, it's possible for a user to share a book to another user related to his ecosystem, meaning that he cans share informations only with the users that share the same API key (the same client).
Does it mean that I have to manage an owner_list in my book object ?
Second problem
I told in the before explanations that I have API keys corresponding to a certain client. Should I have a client_id stored in my user object ? Permitting me to quickly know and share informations between users corresponding to this client_id ?
Third problem
Admitting that I want to work with REST Hateoas, in a Java context. Looking at how hateoas work, it seems that I have to create a specific object that permit me to hyperlink my ressources, like (in JSON) : {hateoas:{key:"user", link:"/users/1234"}} ? Or does it exist something better ?
Last problem
Admitting that I want to work with microservices architecture, and that I have :
A user microservice (for authentication)
A book microservice
I know that I should send informations through AMQP protocol when I need an information from a different microservice.
So :
What kind of exchange / queue (topic, fanout etc...) should I use ?
What kind of information should I send over the network ? Because, okay, I know where the ressource is, with hateoas, but what should I put inside the "tunnel" to have a response ?