I am reading a project used microservice. But it seems different from normal microservice.
all microservices deployed in the same docker container, but each microservice has its own HTTP server listened to a random port. normal microservice usage should deploy one microservice on one server.
use only one database, not one microservice one database.
So i have questions as follows.
Is this a distributed system?
What Pros and cons compared with Single Application Service(already seperated to several modules based on DDD) and normal microservice?
Your described application doesn't seem like a matured microservice-based architecture.
Having a common database is not a problem, but it depends how you use it. If you have clear responsibilities and don't access the data of other services, it can be a nice way to reduce administrative overhead for multiple databases. On the other hand the database might become a point of failure. So there is a trade-off to be considered. However, if you directly access data of other microservices and there is no clear concept of responsibility for data, I'd say it is an anti-pattern or a smell. You give up the criteria of independent deployability (data model changes will break consumers).
In the described deployment scenario in one docker container this criteria of independent deployability is not given at all, as well as horizontal scalability. I'd strongly advice against it if you want to reap the benefits of microservices. Otherwise you will end up with the drawbacks of both world: a distributed deployment monolith.
I could imagine the described architecture is in a migration phase towards real microservices (docker container each service), but hasn't matured yet.
Related
So I started reading some things about different software architectures and inevitably came across Microservices Architecture. Yet, I am wondering about the way these achitectures differ from each other. In a monolythical approach I would e.g. modify a POM.XML to take my different layers and pack them into one application to deploy it. I'd say this might even be the most common way to set up a simple application.
Now as I understood Microservices, you seperate each service from each other and let them run independently. For me that means, that every service is deployed on its own (so you basically got a tomcat running with quite a lot of .war-files on it. But I think I miss the difference to a monolythical application.
I am going to try to set an (quite common) example:
You got a frontend (e.g. Angular) with a Spring-Boot Backend communicating via REST-Services. Now I take a POM.XML and do the following steps:
build the Frontend-Application
include the necessary JS-files into my Spring-Application
create WAR-file from the project
As a result I got one single WAR-file that I can deploy but got two Services included: Backend and Frontend. Yet, I would call it a monolythical approach.
Now when I would include the Angular-Application into my tomcat and deploy a WAR-file of my Spring-Boot part of the application (without integrated frontend). That way I would have two deployed services running on the same server interacting with each other that can be replaced without touching each other. By definition I would not call it a monolythical approach (same code, different deployment) but a Microservice-architecture, right? But this can not be the case since literally every article I read told me the same advantages and disadvantages for architectures and I cannot see any difference except for the possibility to exchange frontend and backend (which I have in both cases, yet in one I would need to redeploy the full application in the first case).
Microservices are set just set of guide lines that talk about how to design your application so that it is scalable, manageable and adapts to fast development pace. It is not just about how you are deploying your application.
Over the years, we have learned that when you try build one big application as monolith, initially it gives you pace, different modules in your monolith has complete visibility of each other and can access things, tweak things around as they wish, even one change that should affect one module may migrate into other classes, where it should not have been. While it helps you prototype, but code becomes less and less maintainable. You can ofcourse put in effort to make sure your code remains clean, but that effort grows as app grows.
Also you as developer are required to know whole product and it is difficult to work in silo, without worrying about the whole architecture, which makes it difficult for new people to join and make changes.
Next when you deploy, specially now a day, scale is important, and you need to adapt to traffic. All your modules will not expect high traffic 24/7. But if you have monolith, even if one module is being used by 100 of users your application have to scale for 100 of users.
Microservices just pulls in info from this, and defines some guidelines
You should breakdown your app based on biz domains. Every service is responsible for one aspect only. They talk to other via contract (API or events) and as long as contract stands you can do what you want within your service. New dev need to learn just one service to start with.
Scaling becomes easy, because if you have load on one service only that will scale. Other modules deployed independently can scale as the load specific to them.
By keeping it small you can build fast, make changes in rapid way. No shared database make sure that you take a call on what you want to save, how you want to save and how you want to change.
For you case, just deploy it the way you think its best. But if you start to grow, you have some 50 odd services (or that size project) you will see benefits of divide and conquer.
Spliting Frontend from Backend is not the best/canonical example of microservices deployments; this is the equivalent of having layers in a monolith. Thing better about how you'd split your monolith by (sub)domain into modules, each module having frontend and backend responsibilities; then each module can become a microservice, if needed.
The canonical MS architecture for a web-based app is a Gateway that assembles (in paralel!) HTML responses from different MSs. So, individual MS would respond with HTML, CSS and JS instead of JSON or other incomplete form of data. This is Tell Don't Ask principle applied to MSs. This gives you a real MS, in which you can very easily replace one MS with another.
If the Gateway cannot assemble the individual responses in parallel because they depend one another then the splitting is wrong and you need to refactor.
The biggest notable difference between a modular monolith and microservices is that microservices run in separate processes.
If you create your monolith using location transparency, then you could deploy components as microservices without touching others' components code. For example if you use CQRS, you could deploy a Readmodel as a microservice just by using cut/paste on your code, from monolith to microservice.
I have created a simple blogging application using Spring Boot and RESTful APIs. I have connected the same to a MySQL database to run some SQL queries like those for adding a blog, deleting a blog, etc.
My questions are as follows:
Does it mean that I have used a microservice architecture? When does an architecture become a microservice? (I ask because many similar websites call an application as microservice-based. Other than the main application, e.g., currency exchange instead of blogging, I see no other difference; for e.g., this one - it does have many more aspects, but they are not contributing to its microservice-ness, IMHO).
Can I call an application as horizontally scalable if I am using microservice-based architecture?
Note: The tutorial I followed is here and the GitHub repo is here.
First of all: those aren't exact yes/no questions. I'll give you my opinion, but others will disagree.
You have created what most people would agree qualifies as a Microservice. But a Microservice does not make a Microservice architecture, in the same way that a tree doesn't make a forest.
A Microservice architecture is defined by creating a greater application that consists of several distributed components. What you have done is created a monolith (which is absolutely fine in most cases).
Almost every talk about Microservices that I have attended has featured this advice: start with a monolith, evolve to microservices once you need it.
Regarding the last question: your application is horizontally scalable if it is stateless. If you keep any session state, it can still be horizontally scalable, but you'll need a smart LB managing sticky sessions or distributed sessions. That's when things get interesting, and when you can start thinking about a Microservice architecture.
Common problems are: how can I still show my customers my website, if the order database, cart service, payment provider etc. are down. Service discovery, autoscaling, retry strategies, evolving Rest apis, those are common problems in a Microservice architecture. The more of them you use and need, the more you can claim to have a Microservice architecture.
Not at all. The use of microservices is an advanced architecture pattern that is hard to implement right, but that gives useful benefits in huge projects. This should not be of any concern to a small project, unless you want to test this particular architectural style.
Breaking an application in smaller chunk does increase its scalability, as resources can be increased on a smaller scale. However, statelesness, among other properties, are also key components to a scalable architecture.
First of all, what you showed us dont looks like microsservice at all.
You can say that you have an application that uses microsservices architecture when it is formed by microsservices(oh rly?) with independent functionalities and that can be scalable. Scale one service, means that you will run multiple instances (possible in multiple hosts) and it will be transparent for other services.
A good example to ilustrate that is a web store microsservice based composed by 4 microsservices:
Sale Microsservice
Product Microsservice
Messaging Microsservice
Authentication Microsservice
In a blackfriday event, for example, which theoretically will occur a lot of purchases, you can scale only the Sale Microsservice, saving resources from the other three (of course this means using a bunch of other technologies like proxy, LB ...). If you were using a monolithic architecture would need to scale all your application.
If you are using correctly a microsservice architecture, yes, you can say that your application is horizontally scalable.
We currently have a big monolithic J2EE application (weblogic / DB2). It is a typical OLTP application. We are considering to split this application into 2 applications where each application has its own database which is not directly accessible by the other application. This also means that each application need to expose an interface for the functionality that is needed by the other application.
So what are potentially the major benefits of splitting such an existing application into 2 applications ?
Most of applications using 10% of code during 90% of the time.
The core idea of the micro-services which is modern SOA. You are able to elastically scale the critical part of your application in the micro-service specific special cloud. Cloud is an elastic cluster, where each node is a virtual server (XEN or VMware etc.). Cloud can extend or shrink nodes count automatically according to the load factor, without manual attention.
With the classic monolithic applications, you need to scale a whole monolithic application. Usually such application use a large amount of RAM, as well as require strong hardware or strong and expensive virtual server. Another disadvantage of monolithic - if you need to release a new business feature, release cycle will be really long, since you've done a modification to the huge and complicated code-base with a code entropy. It will require time/budget expensive regression testing. But you have a benefit - different application parts (subsystems and modules) can be integrated much easier comparative to the SOA approach, off cause if you have good application design.
On another side - you can split your application logic to the set of small applications, such application called a micro-service. For instance you have one micro-service responsible for UI only - i.e. only Spring MVC with Angluar.js, another micro-service for business logic and persistence, and one more micro-service for obtaining data from social networks. All those services are interconnected with each other using some web-services usually RestFull, but can be SOAP or something like Google Protocol Buffers RPC etc. So now you are able to auto-scale only UI micro-service, which is expected to be performance critical, without touching business logic and social network micro-services. And you are able to update UI micro-service even once a weak, since UI only testing is not so expensive like business logic testing. But there is a disadvantage - cluster structure became more complicated, and require stronger team to maintain it (usually automate with some Chef or Docker based scripts). It is also hardly to implement subsystem integrations and you need to think about your system design more carefully.
So, if you have a huge and complicated system which is hi-loaded (like Amazon.com, Ebay, Facebook or stackoverflow). SOA approach gives you an opportunity to save some money on infrastructure and hardware. But it will be more expensive in development. And if you system is very simple, i.e. internet cafe site with a few pages - monolithic approach is preferred.
If scalability isn't your concern, then I'd be pointing at the following benefits:
Increased change velocity - shorter time for a feature to get from the idea phase to production (lower complexity for developers)
Lower cost of testing (smaller scope to test)
Improved quality (again, smaller scope to test)
We can't weigh advantages and disadvantages without looking what that application is all about, what are business rules, how you are dividing application and how two applications share business rules.
Dividing an application into two application is not just diving java classes into two groups. It require depth analysis from different perspective. Hope this helps.
Starting a new project an e-commerce, that basically consists of two, main separated projects: a core application and a web client.
Core app would act as a service provider, the back-end for the web client (or other clients), exposing all its functionality in REST-ful web service/JSON.
Web client would act as a front-end and a service consumer for the core app.
Both project are mainly based on: Spring, Apache CXF, Maven, and either Tomcat or Jetty.
Git as VCS. CouchDB as the DB. Also a distributed caching system like Memcached.
The principle is to design the project (both core and web) in a way to be scalable and distributable on several nodes on the internet.
Perhaps the subject is too big and complex to discuss in one topic; the idea is to put the main headlines that would assist on making the right decisions before going on with the implementation.
The questions:
Based on the technology stack above, what could possibly be missing or worth adding?
Any books, materials or case studies recommendation that touch on the subject?
On the server side, you should structure your URLs and application state in such a way that they can either be generated statically and served via a web server like apache, or dynamically generated and served by the app server. Static content generation can be a pretty effective, reasonably straightforward way to improve performance. Having your API points to be implementation agnostic is generally a good practice anyways.
High Performance Websites has some great stuff. Also, check out Squid for HTTP caching.
Take a look at CQRS principles. Even though great scalability is only side effect of applying CQRS, it ideally fits for cloud computing which main goal is to provide elastic scalability. Here is a awesome video from Greg Young's class.
PS. Despite most of materials are based on .NET stack, these principles are cross-platform.
#Ellead:Go through Tomcat clustering (session replication) :http://tomcat.apache.org/tomcat-6.0-doc/cluster-howto.html
Just take care of singleton objects in spring (keep in mind singleton is per JVM)
You did not mentioned performance and load testing - you should measure performance of your application and scalability too:
How is a single node coping wih high load ?
What performance gainyou get by adding a single node ?
Do no expect or guess anything and start as soon as possible - that alone will save you fortune.
For REST-based solution look at Apache httpd and mod_jk for load-balancing.
I'm new to this and is looking at Apache Camel, Spring Integration and even Terracotta.
I'm looking at sharing of common data like user/groups/account/permission and common business data like inventory/product details/etc.
Any example will be really appreciated.
How about database-level integration?
Have both applications access the same relational database. Those are built for that kind of task.
To do that, the two applications can use a shared library (of which for the sake of simplicity each one will have a copy in their WEB-INF/lib).
You should consider creating a full blown EAR instead, if you want this to be web container independent.
As different web applications have different classloaders you cannot just create an object in one web app which is immediately usable by another. Hence you need to have a common classloader which knows about the classes in common, and - to be 100% compliant - these classes may not be in either web apps WEB-INF/lib. This is hard to get right, and the result is fragile.
Therefore consider migrating to a web container which can deploy EAR's instead as they may contain several web applications sharing objects. I believe a good choice for starting would be JBoss.
I'm looking at sharing of common data like user/groups/account/permission and common business data like inventory/product details/etc.
Common data like users, groups, and permissions belong in a central LDAP or database. These are part of your Spring Security solution, and all apps can share those regardless of whether they're on the same app server or not.
It can be argued that common business data like inventory, product details, etc. should be "owned" by a single service. It's the only one that can modify the data. Others can get access by querying the service, but it's the one that manages CRUD operations on those tables.
If you do this, you keep objects and systems from being coupled at the database level. You're trading looser coupling for increased network latency.
In theory, every application has its own memory space, but off the top of my head I can think of a number of methods for sharing information between applications.
If the amount of shared information is small, perhaps a direct approach is best. set up a communication channel (web services are a bit of an overkill, but a good example) and have the applications request info from each other.
If there is massive sharing, perhaps the two applications should be reading from the same database or local file. Mind you, This brings up synchronization issues, and gets you into the realm of lockings and blockings. Tread lightly in this realm...
If your new an idea may be to build the classes to handle the common data and just build a separate servlet for each application.
This will at least get you started and more familiar with the technologies.