Microservices based Cloud Native Application - Part III

Preview:

This is the third post in the series of Microservices based application development.

The entire series could be found here:

Microservices based Cloud Native Application - Part I

Microservices based Cloud Native Application - Part II


Microservices based Cloud Native Application - Part III


Overview:


Continuing from previous posts, in this post, I'm going to write about a few challenges which I faced while implementing the Microservices and how did I address them. This might hopefully help other folks who might run into similar issues.


Challenges faced while implementing Microservices:


Issue 1:


While using Zuul API, I was getting the following exception, when the angular JS application, invoked the Zuul service.

com.netflix.zuul.exception.ZuulException: Forwarding error

at org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.forward(RibbonRoutingFilter.java:132)
at org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.handleException(RibbonRoutingFilter.java:157) 
at org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.run(RibbonRoutingFilter.java:78)

We also got the following exception:
com.netflix.discovery.shared.transport.TransportException: Cannot execute request on any known server

Root Cause:

The root cause of both of the above exceptions were same:

The zuul server was failing to register with Eureka server as an Eureka Client.
After analyzing the logs, we found that while communicating with the Eureka Server, there was a mismatch in the API interface signatures. Looked like a version mismatch between Eureka client in Zuul and the Eureka server!

And it was indeed. 

Solution:

In the pom.xml of individual microservices, we were using Eureka clients as:

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
            <version>1.0.6.RELEASE</version>
</dependency>
Clearly, this might lead to confusions and issues, if different microservices define different versions of Eureka client, than the one defined in Eureka server.

To fix this and to bring in consistency in Eureka versions in all microservices, we removed the versioning from individual pom's and introduced dependency management in the parent pom (the pom of the parent project for all microservices).

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Brixton.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
As mentioned above, we used Brixton release and it automatically pulls the correct version of the dependencies defined in the child poms.

So the pom.xml of individual microservices for Eureka client will look like the below. Notice there is no version!

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>



Issue 2:

While inovking the Zuul APIs from the Angular JS application, the API calls were failing with CORS (Cross Origin Resource Sharing)issue as below:
"No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:63342' is therefore not allowed access".


Root Cause:

The reason for above issue is that, the angular app was running on a domain 'http://pronet-profile-web.cfapps.io/' and the Zuul App was running on a domain 'http://pronet-edge.cfapps.io/'. Notice that the sub domains are different. This was causing the CORS issue. 

Solution:

Add CORS filter in the Zuul server. Generally Spring recommends adding of an annotation "@CrossOrigin" on the spring boot microservice. However, this solution somehow did not work on the Zuul application (having @EnableZuulProxy annotation).

As an alternate fix, we added the the below filter to the Zuul application to enable CORS:

@Bean
  public CorsFilter corsFilter() {
      final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource= new UrlBasedCorsConfigurationSource();
      final CorsConfiguration corsConfig = new CorsConfiguration();
      corsConfig.setAllowCredentials(true);
      corsConfig.addAllowedOrigin("*");
      corsConfig.addAllowedHeader("*");
      corsConfig.addAllowedMethod("OPTIONS");
      corsConfig.addAllowedMethod("HEAD");
      corsConfig.addAllowedMethod("GET");
      corsConfig.addAllowedMethod("PUT");
      corsConfig.addAllowedMethod("POST");
      corsConfig.addAllowedMethod("DELETE");
      corsConfig.addAllowedMethod("PATCH");
      urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfig);
      return new CorsFilter(urlBasedCorsConfigurationSource);
  }
Note that you need to add the "OPTIONS" method as well.


Issue 3:

While inovking the Zuul APIs from the Angular JS application, the API calls were failing with the below error:
The 'Access-Control-Allow-Origin' header contains multiple values 'http://localhost:63342, http://localhost:63342', but only one is allowed.

Root Cause:
On analyzing this, we found that the individual microservices had a "@CrossOrigin" annotation. We already have a CORS filter on the Zuul server (Fix for Issue 2 above.)
 Adding another filter on the microservice layer, duplicates the CORS filter and hence we were gettting that error.

Solution:

 Removing the @CrossOrigin annotation from the individual microservices solved the issue.

Comments

  1. Thanks for sharing an informative blog keep rocking bring more details.I like the helpful info you provide in your articles. I’ll bookmark your weblog and check again here regularly. I am quite sure I will learn much new stuff right here! Good luck for the next!
    Web Designing Training Institute in Chennai | web design training center in chennai | web designing course in chennai with placement
    Mobile Application Development Courses in chennai
    Data Science Training in Chennai | Data Science courses in Chennai

    ReplyDelete
  2. Your explanation way is too good and I like your nice post. You are providing the information was very useful for me and also I learn huge details from your blog.

    Java Training in Chennai

    Java Course in Chennai

    ReplyDelete
  3. You just have to type in the PIN number after scratching the cardboard on the playing site’s payments web page. No actual payment data is required to make a safe transaction at a on line casino website. Another advantage of e-wallets is that 우리카지노 they're simply accessible by way of mobile phones, making them a perfect possibility for secure on line casino playing. However, want to} verify before making any transaction via e-wallets as might possibly} incur fees, that means e-wallets might value you significantly if you’re transacting large quantities of cash.

    ReplyDelete

Post a Comment

Popular posts from this blog

Pivotal Cloud Foundry (PCF) Integration with Elastic Cloud Storage (ECS)

Restful code example using Spring MVC

Spring Integration - Bulk processing Example