Microservices platform with Spring Cloud – part 3

Today we continue with our work on creating  microservices platform based on Spring Cloud.  In the previous post, we’ve seen how to achieve reliable communication between service. Now, we’re taking our system one step further, and we’ll see how we can allow outside world to access our services.

Normally, microservices are deployed on some kind of internal network within organization, and only some parts of the system are exposed to external clients. This way, you can protect sensitive parts of the system, and only allow access to selected endpoints from the outside. To achieve this goal, we will use Netflix Zuul, a component that will servce as a gateway to our system.

Official description of Zuul is “a gateway service that provides dynamic routing, monitoring, resiliency, security, and more“. So, it provides a lot of functionality which we will not cover in this post. In any case, I encourage you to try out various options that Zuul has to offer. It will give you insight into some common problems which you may face when developing distributed systems.

Creating API gateway

Spring Cloud support Zuul out of the box. As with other Netflix components, all we need to do to make use of Zuul, is to add some dependencies and annotations. For our case, we will use Zuul as a reverse proxy, meaning that it will provide a way to proxy client calls to services within internal network, ie. services which are not reachable from outside world.

For this example, we will assume that user service and messaging service are on our intranet, protected by a firewall. We want to expose /user  endpoint to public, but keep the rest of the services private. Following code samples show how we can configure Zuul to perform this task.

First, we’ll need to configure Maven POM. We will add required dependencies for Zuul:

After dependencies are configured, we need to annotate main application class with @EnableZuulProxy :

We will  configure to use config server:

And finally, we need to configure Zuul routes:

This configuration specifies that we want Zuul routes to start with /api/v1 . Next, we create a mapping users which will map requests starting with /users  to be forwarded to service user-service. This is the name under which service is registered with Eureka.

If you now run Zull server and send POST request to http://localhost:9000/api/v1/users , like we did in previous post, you can see in console that Zuul forwards this request to user service.

Full source code of this sample can be found in Github.

Request filters

Zuul provides much more functionality then just routing requests. One of the supported functions is processing incoming requests through filters. You can think of Zuul filters like servlet filters, in that they allow us to take an action on request before, during or after routing. We will showcase a sample Zuul filter here.

One of the common features in distributed systems is tagging each incoming request with a unique ID. This allows easy tracking of related requests as they invoke different services. Each related request is tagged with the ID of incoming request. To show this, we will  create simple Zuul filter which will add unique ID header to each incoming request.

Here we create a filter with type pre , which means that it is being run before routing. In run method, we do the actual work of adding request header which will be propagated to downstream services.

Now, we can rewrite our user service to read request ID:

We can use this ID for purposes like logging, metrics etc.

Note: This is naive approach to request correlation, and is shown here only to showcase possible application of Zuul filters. There are entire frameworks and libraries dedicated to this field. For example, Spring Cloud provides Sleuth as one possible solution. We will take more detailed look at these solutions later in this series.

Conclusion

In this post, we’ve seen the principle of configuring Zuul as an edge service, ie. entry point for our microservices platform. Zuul provides a lot more functionality, and I encourage you to try it out.

Next time, we will go deeper into logging configuration for our platform. Stay tuned for next post!

Other posts in this series

Leave a Reply

Your email address will not be published. Required fields are marked *