Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get spring-cloud zuul to use a different circuit for different services

I'm attempting to use spring-cloud-starter-zuul. I have setup Eureka and registered a simple service I wrote as a Eureka client. I register two instances on two different hosts with two different application names so they are two different services in Eureka. My objective is to ensure that if serviceA is performing well and serviceB is performing poorly that proxying to serviceA is not affected by failure to proxy to serviceB.

If I run load test serviceA alone through zuul I'm able to maintain my 400 TPS throughput without a problem. If I then throw in serviceB and totally overload it and have it timing out all over the place, I would expect serviceA to continue at 400 while serviceB flounders, but instead serviceA drops to less than 50 TPS success rate and has a bunch of errors as well.

It appears that all of the RibbonCommands spawned by the RibbonRoutingFilter share the same circuit in hystrix, which makes no sense to me. Looking in the RibbonRoutingFilter where it creates the RibbonCommand, I don't see any way to configure it to use a different one.

In RibbonRoutingFilter:

    RibbonCommand command = new RibbonCommand(restClient, verb, uri,
            convertHeaders(headers), convertHeaders(params), requestEntity);

I have validated that the restClient is different for serviceA and serviceB, so they are using their own connection pool configuration as I've specified in the application.yml file, but there is still a ton of cross-contamination in service quality between serviceA and serviceB.

There appears to be another constructor for RibbonCommand that takes a "commandKey" as a first parameter, and the one I reference simply delegates to that one with a commandKey value of "default". I see no switches or options to override that in the RibbonRoutingFilter. To me this seriously compromises the viability of Zuul when used from the spring-cloud project.

Is there a way for me to configure this out of the box so that each service has its own circuit?

Applicable portions of my pom:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-parent</artifactId>
      <version>1.0.0.RC1</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

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

application.yml:

ribbon:
  ConnectTimeout: 5000
  ReadTimeout: 5000
  MaxAutoRetries: 0
  MaxAutoRetriesNextServer: 0
  OkToRetryOnAllOperations: false
  MaxHttpConnectionsPerHost: 200
  MaxTotalHttpConnections: 1000
echo1:
  ribbon:
    ActiveConnectionsLimit: 200
echo2:
  ribbon:
    ActiveConnectionsLimit: 400
spring:
  application:
    name: SpringCloudProxywall
server:
  port: 8080
zuul:
  routes:
    echo1:
      path: /echo1/**
      serviceId: echo1
      stripPrefix: false
    echo2:
      path: /echo2/**
      serviceId: echo2
      stripPrefix: false

My application class:

@Configuration
@ComponentScan
//@EnableCircuitBreaker  <-- is already included in EnableZuulProxy
@EnableZuulProxy
@EnableTurbine
@EnableHystrixDashboard
@EnableAutoConfiguration
public class SpringCloudProxywallApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringCloudProxywallApplication.class, args);
    }
}
like image 456
digitaljoel Avatar asked Jan 21 '15 23:01

digitaljoel


People also ask

What class would I use if I needed to share data between different Zuul filters?

To pass information between filters, Zuul uses a RequestContext . Its data is held in a ThreadLocal specific to each request. Information about where to route requests, errors, and the actual HttpServletRequest and HttpServletResponse are stored there.

How do I register multiple microservices in Eureka server?

First, you need to add the following dependencies in our build configuration file to register the microservice with the Eureka server. Now, we need to add the @EnableEurekaClient annotation in the main Spring Boot application class file.

When a circuit for a given route in Zuul is tripped?

When a circuit for a given route in Zuul is tripped you can provide a fallback response by creating a bean of type ZuulFallbackProvider . Within this bean you need to specify the route ID the fallback is for and provide a ClientHttpResponse to return as a fallback.

What can I use instead of Zuul?

Apigee, Eureka, Kong, HAProxy, and Istio are the most popular alternatives and competitors to Zuul.


1 Answers

I think if you use a snapshot that is already the default (different circuit per backend): https://github.com/spring-cloud/spring-cloud-netflix/issues/160.

like image 150
Dave Syer Avatar answered Oct 17 '22 16:10

Dave Syer