Founder and architect
Building applications using microservices is covered well in several publications. In this post my attempt is to cover few problems which do not get as much attention and discuss solution of each. Paying early attention to these areas would help you improve productivity, quality and build a flexible application. I will also show that it can save 25% or more in cost. These lessons are learnt by working on an open-source platform and working with few customers.
If you are building microservice based application, you would divide application in several microservices and use variety of technology stacks. An application may have 5–500 microservices depending on complexity. You may be using a mix of Java, .Net, Python, NodeJS, GO etc. based technology stacks. One important consideration that is often missed, how is a developer going to use these services in development environment for testing. Developers are the most productive when they are using IDE of choice on personal machines. It helps them write and debug code faster. It is impractical to run several services on personal machines for debugging and unit testing. Another issue that is highly debated what “should and should not” constitute shared code. People lean towards un-sharing. The third important consideration is creating reusable services which can acquire personality of slightly varying services through meta-data or scripting. The fourth issue is not critical for server side developers but for UI developers. It deals with how to slice a large UI into smaller pieces, develop each independently and automatically put them together at runtime.
In the following sections we will get into details of these four areas and discuss how to solve them.
In operational environment, you would probably have all microservices running on private or public cloud somewhere. But developers can’t reach to them due to network security reasons. Even if developers can create a secure tunnel to these services, it is lot of work and distraction from daily development. Break developers concentration and they have to “eat frog” before they start rolling.
How can a developer connect to services in cloud from his or her machine? You probably guessed it — “we need a gateway to services”. If you have one, sweet! If not then probably you would build it someday to expose your services to outside world. Why not do it now so your own developers become consumer of APIs. It would also help in abstraction, understanding of services and standardization. Having a gateway is not enough but it is the first required step.
In this case, the goal of a gateway is to provide close to deployment environment to developers. There are few more things you need to consider to create a true deployment environment on developer’s personal machine. In order to develop and debug, developers run few services (generally 2–3) locally and like to connect to rest in cloud. Thus, it is an environment that is a mix of services on developers’ machines and in cloud. It is achieved by changing IP addresses of endpoints of services, pulling few code repositories or containers. If you visualize it, you are creating an environment which is a slight variation of centrally available environment to everyone. What is the best way to achieve it?
This can be achieved if you design a light gateway which is lightweight and configurable, ideally through UI. Through UI developers can change IP addresses of services. If it simple enough developers can deployit on local machines to mediate between local and cloud services. This resulting structure is shown in the following diagram.
You would find several use-cases of reusing above design with gateway creatively. Let us take one more example. If you are developing an application which uses single sign-on (SSO), you can use operational environment to acquire access-token and use it in hybrid environment where you are running services on local machine and remote cloud. I intend to cover this as a separate blog later.
One of the benefits of microservice architecture is that changes in one service does not cause a ripple effect. Therefore, the idea is to make them completely independent of code changes in one to other. But it does not mean that you should not share code. It probably means that you need a proper version management for the shared code. The shared code can evolve. But a service using it can decide to migrate to the newer version or not. In fact, this is how we use the open source code. You will be using several open source libraries in your microservices. There is no reason you can’t treat your own shared code in the same way.
You can never go wrong by sharing. Let us say you have 10 services which could have used “X” common code. The worst case when you don’t share, all have 10X extra code. You begin by sharing the version 1 of “X”. “X” moved to version 2. Only 3 services would have moved to “X 2.0”. You would still have lots of code sharing. You can also have multiple layers of shared libraries. Some services may bypass higher level layers if they don’t need them. The following diagram shows layering of code with and without code sharing. If you properly plan code sharing, it is a big winner.
You can look for sharing code in these areas:
There are many opportunities in computer software where something is a variation of something else. In case of microservices too, you can find a common denominator and pull it out as a generic code which can be called “template-service”. If you follow a data driven design then it can morph into a special case using meta-data and some pluggable scripts. For example, let us say you have a service called Order Service. It will probably save data in database. There is a Shipment Service that is also saving data in the same data base. You can pull out common denominator code as Persistence Service which will take schemas and pluggable code as input. Another option is to deploy as three services: i) Order Service, ii) Customer Service and iii) Persistence Service. A data driven design of Persistence Service will be easier if you are using NoSQL DB than RDBMS. But you can do it in each case. You may find other benefits of such a design. For example, in this particular case, it separates the application logic from database logic; DB experts can optimize it independent of business service. This is one illustration and may not be quite possible in your case. But the overall idea is that if you can pull out infrastructure like code from multiple services into template-services then give it serious consideration. It will not be obvious. Once you get used to metadata and scripting programming model, you will start seeing several such opportunities. I intend to cover this in much greater details in a separate post.
Let us look at the HTML page served for a micro-application by the server. It would have the following content.
load open source css
load common css (common across all micro-applications)
load css specific to micro-application
Mostly empty, rendered using templates
load open source JS
load common JS (common across all micro-applications)
load JS specific to micro-application
You will notice that parts which change are micro-application specific CSS, JS and corresponding HTML templates. In integrated environment, previous micro-application code can be unloaded and new micr0-application code can be loaded without page refresh. A micro-application can be represented by URL which may have its name as path in the URL. Using a proper WEB server design, you can use path to plug in specific CSS, JS in barebone HTML page on the server side. For clarity and modularity, you can organize micro-application specific JS, CSS, HTML templates in separate directories. This decomposes your application on the UI side quite similar to the way that microservices do on the server side.
The above mentioned considerations lead to significant business benefits. Let us say a developer spends 4 hours a week struggling to connect to services. In a 6 month project with 10 developers it will mean 4 person months i.e. roughly 7%. Add to it frustrated developers working at lower productivity and quality, it can top 10%. If you have a solid plan for code sharing among microservices, it will lead to additional saving. Writing data driven, programmable services and be able to adopt them to some degree of variation will provide flexibility and save time-money in a short as well as long run. UI code can get spaghetti very easily as its volume grows. You can avoid it by breaking UI into smaller modules (or micro-applications in traditional WEB app sense). Let us say each of these contributes to 5% saving. All this adds up to 25%. You can use it towards building high value features, better UX or team rewards. The flexible and modular code base also opens up the door for innovations.
I intend to cover following topics more in details in separate posts.
1. Lightweight Gateway Design
2. Data Derive, Programmable Template-Service
3. UI Decomposition as Micro Applications
4. Developing Secure Microservices
Create your free account to unlock your custom reading experience.