Little domain presentation
I m actually having two microservices :
User - managing CRUD on users
Billings - managing CRUD on billings, with a "reference" on a user concerned by the billing
Explanation
I need, when a billing is called in a HTTP request, to send the fully billing object with the user loaded. In that case, and in this specifical case, I really need this.
In a first time, I looked around, and it seems that it was a good idea to use message queuing, for asynchronicity, and so the billing service can send on a queue :
"who's the user with the id 123456 ? I need to load it"
So my two services could exchange, without really knowing each other, or without knowing the "location" of each other.
Problems
My first question is, what is the aim of using a service registry in that case ? The message queuing is able to give us the information without knowing anything at all concerning the user service location no ?
When do we need to use a service registration :
In the case of Aggregator Pattern, with RESTFul API, we can navigate through hateoas links. In the case of Proxy pattern maybe ? When the microservices are interfaced by another service ?
Admitting now, that we use proxy pattern, with a "frontal service". In this case, it's okay for me to use a service registration. But it means that the front send service know the name of the userService and the billing service in the service registration ? Example :
Service User registers as "UserServiceOfHell:http://80.80.80.80/v1/"
on ZooKeeper
Service Billing registers as "BillingService:http://90.90.90.90/v4.3/"
The front end service needs to send some requests to the user and billing service, it implies that it needs to know that the user service is "UserServiceOfHell". Is this defined at the beginning of the project ?
Last question, can we use multiple microservices patterns in one microservices architecture or is this a bad practice ?
NB : Everything I ask is based on http://blog.arungupta.me/microservice-design-patterns/
A lot of good questions!
First of all, I want to answer your last question - multiple patterns are ok when you know what you're doing. It's fine to mix asynchronous queues, HTTP calls and even binary RPC - it depends on consistency, availability and performance requirements. Sometimes you can see a good fit for simple PubSub and sometimes you need to have distributed lock - microservices are different.
Your example is simple: two microservices need to exchange some information. You chose asynchronous queue - fine, in this case they don't really need to know about each other. Queues don't expect any discovery between consumers.
But we need service discovery in other cases! For example, backing services: databases, caches and actually queues as well. Without service discovery you probably hardcoded the URL to your queue, but if it goes down you have nothing. You need to have high availability - cluster of nodes replicating your queue, for example. When you add a new node or existing node crashed - you should not change anything, service discovery tool should understand that and update the registry.
Consul is a perfect modern service discovery tool, you can just use custom DNS name for accessing your backing services and Consul will perform constant health checks and keep your cluster healthy.
The same rule can be applied to microservices - when you have a cluster running service A and you need to access it from service B without any queues (for example, for HTTP call) you have to use service discovery to be sure that endpoint you use will bring you to the healthy node. So it's a perfect fit for Aggregator or Proxy patterns from the article you mentioned.
Probably the most confusion is caused by the fact that you see "hardcoded" URLs in Zookeeper. And you think that you need to manage that manually. Modern tools like Consul or etcd allows you to avoid that headache and just rely on them. It's actually also achievable with Zookeeper, but it'll require more time and resources to have similar setup.
PS: please remember about the most important rule in microservices - http://martinfowler.com/bliki/MonolithFirst.html
Related
I have a SaaS based multi-tenant monolith application (built with Django), that I want to divide into microservices based architecture. But I am not sure how to divide the application into correct partitions. And on what aspects should I take care of?
In case of monolith application, it's easy to understand that I have a tenant model that decides the schemas but how this will be done in microservices if I want each service to be multi-tenant? Or should I even make the services multi-tenant?
If you're already using OAuth and/or generating JWTs for user authentication/authorization, I'd recommend any new services that need tenant scoping to require a user access token be provided in requests just like your Django app. This lets you standardize how credentials and tenant scoping is expected to be passed, and verifying JWTs is a pretty easy process to implement.
That being said, it's also important to point out that you shouldn't require that services use access tokens or have any kind of tenant scoping at all. Not only is it possible that specific services don't require tenant scoping, but it's also possible that they might want to define a tenant differently from the main Django app (e.g. a simple tenant_id). For example, a payments service that only accepts a dollar amount and a credit card doesn't care what the tenant is and would be perfectly safe to call from the main Django application (of course you should prevent public access to the service too).
The best way to think about how new services should be designed is in a vacuum - without care for how other services are designed or how they store their data. Your service was built to perform a task and it defines for itself what parameters it needs to perform that task, how it executes that task, and how it stores the data it needs for future tasks. This independence from the design of other microservices in the stack is part of the power of designing service-oriented systems. It allows creators to pick the right tools for the job, and allows them to create meaningful features without needing to collaborate with dozens of team members that they often don't know.
Hope this helps, and good luck.
This conceptual question has crept into my mind after becoming more familiar with AWS. In general, I’m curious if there is a best-practice and/or convention as to when an API provider should group endpoints into a new, separate API (vs. lumping the endpoints into an existing API).
To illustrate, let’s say a Service creates digital wallet coupons on behalf of Manufacturers, to be redeemed by Consumers at a bunch of Mom & pop stores — some of the activities the Service might engage in include:
Receiving data from the Manufacturers (in order to build the digital coupons)
Providing a mechanism for Consumers to find and download coupons
Providing a way for the Mom & pop stores’ payment terminals to validate the coupons
And, oh by the way, the Service might also be required to ...
Implement a variety of endpoints, based on technologies involved (e.g., PassKit with Apple Wallet)
So?
With AWS, it’s easy to modularize one’s backend (e.g., have an RDS instance for the database, run a few lambda functions for microservices, etc.) and load balance it all. API Gateway adds to this in that each endpoint can point to different things (lambda functions, EC2 instances via HTTP proxy, etc.).
Consequently, one approach might be to define one API in AWS API Gateway and have all the endpoints underneath it:
API: “Master”
/coupon
POST = create a new one (for Manufacturers)
PUT = update an existing one (for Manufacturers)
GET = retrieve one (for Consumers)
/coupon/validate
POST = verify it’s still valid (Mom & Pop store use-case)
/apple-wallet
/{version}
/passes
... per documentation
/devices
... per documentation
But would it make more sense for the Service to shave off the /apple-wallet endpoint and create an entirely new, separate API?
Alternatively, if the Service was going to publish documentation for public developers to use, would it make sense to move the Manufacturer-relevant endpoints into a separate API altogether?
Since AWS makes the effort of splitting endpoints so simple via API Gateway, are there any standard practices for when you should (or should not)?
Thank you for any insights / opinions!
My two cents. Think about your end-user for your APIs. You will have different developer end-users for each API set.
Your ideal situation will have each developer end-user only seeing the APIs that are relevant to them. So you should split your APIs into different Gateways according to the end-users
In the theoretical situation you describe:
Create an API for Manufacturers so they can integrate with you to create coupons. If you do the integration internally it will be the corporate sales and presales people who talk to the manufacturers
The users for the Service and End User coupons might end up being the
same app developers that create an interface for both stores and
users. So create a coupon API for them
Separating both should also give you security benefits as you will protect the knowledge of your Manufacturer API from the users who might try to hack it
We currently run a Java backend which we're hoping to move away from and switch to Node running on AWS Lambda & Serverless.
Ideally during this process we want to build out a fully service orientated architecture.
My question is if our frontend angular app requests the current user's ordered items to get that information it would need to hit three services, the user service, the order service and the item service.
Does this mean we would need make three get requests to these services? At the moment we would have a single endpoint built for that specific request, which can then take advantage of DB joins for optimal performance.
I understand the benefits SOA, but how to do we scale when performing more compex requests such as this? Are there any good resources I can take a look at?
Looking at your question I would advise to align your priorities first: why do you want to move away from the Java backend that you're running on now? Which problems do you want to overcome?
You're combining the microservices architecture and the concept of serverless infrastructure in your question. Both can be used in conjunction, but they don't have to. A lot of companies are using microservices, even bigger enterprises like Uber (on NodeJS), but serverless infrastructures like Lambda are really just getting started. I would advise you to read up on microservices especially, e.g. here are some nice articles. You'll also find answers to your question about performance and joins.
When considering an architecture based on Lambda, do consider that there's no state whatsoever possible in a Lambda function. This is a step further then stateless services that we usually talk about; they generally target 'client state' that does not exist anymore. But a Lambda function cannot have any state, so e.g. a persistent DB-connection pool is not possible. For all the downsides, there's also a lot of stuff you don't have to deal with which can be very beneficial, especially in terms of scalability.
I think I know the answer to this one, but I have just spotted someone doing exactly the opposite - who is a very skilled developer, were they just having a bad day?
Q: Is it OK to call a service from within a service in an SOA architected system?
I suspect not, but i'll ask anyway...
I can't think of any reason why not. I can think of multiple reasons why a service could call another service. I've architected and implemented multiple services that do this. I'm also aware of other architectures that set up this sort of system.
Definitely yes. This SOA pattern is commonly called choreography where one web service processes and then passes the message to another down a processing pipeline. Google it and you will find some good references.
Another case may be more technical reason like routing, where you have frontend webservices that routes your messaged to different backend services based on security policy, content, bridge different technology or transport protocol etc.
The answer to this is as always "it depends..." let me explain what I mean.
Calling another service in a SOA is of course a totally acceptable thing to do, it is at the heart of SOA to be able to compose new things out of existing services.
The more important part is how you call the services, consider a SOA system where multiple services collaborate in a call chain call each one enlisting the other in the transactional scope. Doing this sort of thing without careful planning will have a massive impact on your systems performance. The same call chain designed using well partitioned services that are scoped at the correct unit of work suffers less.
Consider system robustness, in a typical architecture one service tends to become more popular than others and lands up having many other services calling it. A failure of this one service brings down the entire system due to all the other services being dependent on the call to this one service.
Consider the difference between synchronous and asynchronous calls, when do you use what? That is the impact of each?
How do you design and partition services to limit the cost of crossing the service boundary on each call?
Lots of questions, but if you look around there are many places to find answers, I suggest starting with these.
I would suggest you read articles by Thomas Erl and Roger Sessions, this will give you a firm handle on what SOA is all about.
Building a SOA
SOA Design Pattern
Achieving integrity in a SOA
Why your SOA should be like a VW Beetle
SOA explained for your boss
WCF Service Performance
think about the architectural goal of "separation of concerns". instead of each service knowing how to do everything, it can rely on other specialized services for shared pieces of functionality
I have some different scenario. What if you want to implement service level clustering in your SOA? For example, say persistence service is resides on one machine and is responsible for handling all persistence tasks in the cluster. So, on other machine which needs persistence functionality, need to connect to the that machine only(ignore fail over factor).
Now while login, if User service has instance of Persistence service directly, then you will not be able to implement service level clustering.
We have our SOA middleware and I called service from each other directly. But when we implemented service level clustering using JMS/ActiveMQ, we faced the problem for those interconnected services.
Could someone please direct me to some good documentation or feedback here on what are best practices for implementing web services in an application that handles different concerns? For example, should I create different services, one that handles security, (AuthService), one that handles data-entry for customer service reps, (CRUDService), BillingService and so on or should I just encapsulate all these "services" into one, e.g. ApplicationService? Basically, I am asking if it is bad design to create multiple services (files) within one application. Can some of you note on your experiences or what you've experienced?
Also, let's say three of the listed services from above connect to the same database, but are actually hitting totally different concerns, e.g. one is for all transactions like CRUD, and the other one is for purely reporting purposes. Should I create two services here, one CRUDService and the other for ReportingService? Is it bad to create two different database connections via these 2 services? Or how can I share the same database connection with different services?
I think there is a tendency among publicly available services to just dump everything into one service. Which, may not be a bad idea for a publicly available API. It just makes it easier for developers. However, for any project i work on, i try to break things down into logical groups. This way your client doesn't need to be inheriting functionality it may not need. Updating services would also be a slightly easier task because you're only affecting a certain subset of your web service framework and not everything. So if your service contract breaks and your clients no longer support it, they may still be able to use other parts of your system, but not that particular one. Where as if you break a contract on your aggregated service, everything fails. Finally, if you have to implement something like a fail-over support, you have more flexibility to choose which service requires more fail-over nodes, allowing you to better manage your resources allocation.
If you want best practices take a look to the SOA Design Pattern Catalog