It’s time for a new post teaching the basics of studio and how to implement microservices in nodejs.

On the past weeks we talked about the motivations and learned the basic microservice implementation using studio , now on part 3 we will learn how to distribute the services and add some plugins like realtime metrics.

Studio plugins are based on aspect-oriented programming , besides the weird name it is REALLy easy to use.

A plugin lets you add behavior that are not central to business logic, so with a plugin you can, track the time needed to execute a service call, adds a timeout to the service or event try again in case of errors among other possibilities, the sky is the limit.

Plugins must be the first thing you add on your code, and it is really simple to use, just add a line of code and you’re ready to go:

studio.use(SOME_PLUGIN);

The “use” methods accepts up to 2 parameters, the first one is the plugin itself and the second one is a filter for that plugin, the filter might be a function, a string, a regex or an array of filters, so the following code enables the SOME_PLUGIN plugin to the service named foobar:

studio.use(SOME_PLUGIN,'foobar');

Now lets go back to the code of the past week, lets change the all_services.js file to support 2 plugins, the retry plugin and the timer plugin, to do this we use the code above:

The timer plugin calculates the time to execute every service call, when adding this plugin it automatically binds to all started services, after calculating this time, it calls the function it received as parameter with time info. On this example we just want to log it to the console, but you could easily send it to StatsD or any other place.

Now running the code with the timer plugin it is going to print the time taken to execute the services.

Time taken to execute each service call

The retry plugin lets you decide to retry a service call in case of failure, so lets add a code on reddit_service.js to retry one time in case of failure.

The line 25 tells the service to retry 1 time the search in case of any failure on the searchForContent service.

Adding a plugin is just that simple, now you might be wondering how hard it would be to distribute your code…

Never forget:

“ A cluster is just another plugin”.

So lets distribute our application.

I’m going to create a cluster of 2 process on the same machine, just because most of the readers will have only one machine available, but i will also show the code to multiple machines.

So first, lets npm install the cluster plugin

npm install studio-cluster --save

Now we can change our all_services.js to add this plugin:

We have only 2 changes, first we required the studioCluster plugin, and added it using port 8001 to enable service communication. And then we removed the require of youtube_services, if we execute all_services.js now and hit http://localhost:3000/new it is going to print the following error on console:

Unhandled rejection ROUTE_NOT_FOUND: The route Youtube/fetch doesnt exists

So its telling us it wasn’t able to find a service named Youtube/fetch, but to fix this all we need to do is, add the cluster plugin on youtube_service.js:

We are using a different rpcPort, just because im running on the same machine, by default studio-cluster use the port 10120 to communication, so if you’re in different machines you don’t need to pass this parameter.

Now you can run youtube_service.js (you don’t need to stop all_services.js, they are going to find each other):

node youtube_service.js

Then when you hit http://localhost:3000/new again you will see your response with no error, running exactly like it was a single process.

Studio-cluster is built on top of primus and websockets, so it can handle reconnections, timeouts, unexpected crash or any other problem of communication, the cluster does the best effort possible to keep everything running no matter what.

But… What if you want to distribute your services across the globe?

It is important to learn how to distribute your application if you have several machines to use. If all those machines are on the same network and this network have a broacast feature, than no configuration is required:

studio.use(studioCluster());

If you’re running on multiple networks than studio cluster needs a redis server to handle the service discovery and the following code does the work:

var rpcPort = 10120;//any port

Studio.use(studioCluster({

rpcPort:rpcPort,

publisher:studioCluster.publisher.redis(rpcPort,'REDIS_ADDRESS')}

));

Its also important to notice that redis is used ONLY to service discovery, so the real service call is done through websocket and the cluster can handle unexpected crashes or any other issue.

I think now you agree with me when i say that is REALLY easy to distribute services using studio.

The final code for this post is available at:https://github.com/ericholiveira/example-studio-microservices/tree/pt3

See you next week.