public FeignLoadBalancer(
     ILoadBalancer lb, IClientConfig clientConfig, ServerIntrospector serverIntrospector) {
   super(lb, clientConfig);
   this.setRetryHandler(RetryHandler.DEFAULT);
   this.clientConfig = clientConfig;
   this.connectTimeout = clientConfig.get(CommonClientConfigKey.ConnectTimeout);
   this.readTimeout = clientConfig.get(CommonClientConfigKey.ReadTimeout);
   this.serverIntrospector = serverIntrospector;
 }
 @Test
 public void testFeignOptionsClientConfig() {
   Request.Options options = new Request.Options(1111, 22222);
   IClientConfig config = new RibbonClient.FeignOptionsClientConfig(options);
   assertThat(
       config.get(CommonClientConfigKey.ConnectTimeout), equalTo(options.connectTimeoutMillis()));
   assertThat(config.get(CommonClientConfigKey.ReadTimeout), equalTo(options.readTimeoutMillis()));
   assertEquals(2, config.getProperties().size());
 }
  @Override
  public void initWithNiwsConfig(IClientConfig clientConfig) {
    clientName = clientConfig.getClientName();
    vipAddresses = clientConfig.resolveDeploymentContextbasedVipAddresses();
    if (vipAddresses == null
        && ConfigurationManager.getConfigInstance()
            .getBoolean("DiscoveryEnabledNIWSServerList.failFastOnNullVip", true)) {
      throw new NullPointerException("VIP address for client " + clientName + " is null");
    }
    isSecure =
        Boolean.parseBoolean(
            "" + clientConfig.getProperty(CommonClientConfigKey.IsSecure, "false"));
    prioritizeVipAddressBasedServers =
        Boolean.parseBoolean(
            ""
                + clientConfig.getProperty(
                    CommonClientConfigKey.PrioritizeVipAddressBasedServers,
                    prioritizeVipAddressBasedServers));
    datacenter = ConfigurationManager.getDeploymentContext().getDeploymentDatacenter();
    targetRegion = (String) clientConfig.getProperty(CommonClientConfigKey.TargetRegion);

    // override client configuration and use client-defined port
    if (clientConfig.getPropertyAsBoolean(
        CommonClientConfigKey.ForceClientPortConfiguration, false)) {

      if (isSecure) {

        if (clientConfig.containsProperty(CommonClientConfigKey.SecurePort)) {

          overridePort =
              clientConfig.getPropertyAsInteger(
                  CommonClientConfigKey.SecurePort, DefaultClientConfigImpl.DEFAULT_PORT);
          shouldUseOverridePort = true;

        } else {
          logger.warn(
              clientName + " set to force client port but no secure port is set, so ignoring");
        }
      } else {

        if (clientConfig.containsProperty(CommonClientConfigKey.Port)) {

          overridePort =
              clientConfig.getPropertyAsInteger(
                  CommonClientConfigKey.Port, DefaultClientConfigImpl.DEFAULT_PORT);
          shouldUseOverridePort = true;

        } else {
          logger.warn(clientName + " set to force client port but no port is set, so ignoring");
        }
      }
    }
  }
 @Override
 public RibbonResponse execute(RibbonRequest request, IClientConfig configOverride)
     throws IOException {
   Request.Options options;
   if (configOverride != null) {
     options =
         new Request.Options(
             configOverride.get(CommonClientConfigKey.ConnectTimeout, this.connectTimeout),
             (configOverride.get(CommonClientConfigKey.ReadTimeout, this.readTimeout)));
   } else {
     options = new Request.Options(this.connectTimeout, this.readTimeout);
   }
   Response response = request.client().execute(request.toRequest(), options);
   return new RibbonResponse(request.getUri(), response);
 }
  /** Set necessary parameters from client configuration and register with Servo monitors. */
  @Override
  public void initWithNiwsConfig(IClientConfig clientConfig) {
    if (clientConfig == null) {
      return;
    }
    vipAddresses = clientConfig.resolveDeploymentContextbasedVipAddresses();
    clientName = clientConfig.getClientName();
    if (clientName == null) {
      clientName = "default";
    }
    try {
      maxAutoRetries =
          Integer.parseInt(
              clientConfig
                  .getProperty(CommonClientConfigKey.MaxAutoRetries, maxAutoRetries)
                  .toString());
    } catch (Exception e) {
      logger.warn("Invalid maxRetries set for client:" + clientName);
    }
    try {
      maxAutoRetriesNextServer =
          Integer.parseInt(
              clientConfig
                  .getProperty(
                      CommonClientConfigKey.MaxAutoRetriesNextServer, maxAutoRetriesNextServer)
                  .toString());
    } catch (Exception e) {
      logger.warn("Invalid maxRetriesNextServer set for client:" + clientName);
    }

    try {
      Boolean bOkToRetryOnAllOperations =
          Boolean.valueOf(
              clientConfig
                  .getProperty(
                      CommonClientConfigKey.OkToRetryOnAllOperations, okToRetryOnAllOperations)
                  .toString());
      okToRetryOnAllOperations = bOkToRetryOnAllOperations.booleanValue();
    } catch (Exception e) {
      logger.warn("Invalid OkToRetryOnAllOperations set for client:" + clientName);
    }
    tracer = Monitors.newTimer(clientName + "_OperationTimer", TimeUnit.MILLISECONDS);
    Monitors.registerObject("Client_" + clientName, this);
  }
Example #6
0
 /**
  * Get the client configuration given the name or create one with clientConfigClass if it does not
  * exist. An instance of IClientConfig is created and {@link IClientConfig#loadProperties(String)}
  * will be called.
  */
 public static IClientConfig getNamedConfig(
     String name, Class<? extends IClientConfig> clientConfigClass) {
   IClientConfig config = namedConfig.get(name);
   if (config != null) {
     return config;
   } else {
     try {
       config = (IClientConfig) clientConfigClass.newInstance();
       config.loadProperties(name);
     } catch (Throwable e) {
       logger.error("Unable to create client config instance", e);
       return null;
     }
     config.loadProperties(name);
     IClientConfig old = namedConfig.putIfAbsent(name, config);
     if (old != null) {
       config = old;
     }
     return config;
   }
 }
Example #7
0
  /**
   * Utility method to create client and load balancer (if enabled in client config) given the name
   * and client config. Instances are created using reflection (see {@link
   * #instantiateInstanceWithClientConfig(String, IClientConfig)}
   *
   * @param restClientName
   * @param clientConfig
   * @throws ClientException if any errors occurs in the process, or if the client with the same
   *     name already exists
   */
  public static synchronized IClient<?, ?> registerClientFromProperties(
      String restClientName, IClientConfig clientConfig) throws ClientException {
    IClient<?, ?> client = null;
    ILoadBalancer loadBalancer = null;
    if (simpleClientMap.get(restClientName) != null) {
      throw new ClientException(
          ClientException.ErrorType.GENERAL,
          "A Rest Client with this name is already registered. Please use a different name");
    }
    try {
      String clientClassName =
          (String) clientConfig.getProperty(CommonClientConfigKey.ClientClassName);
      client = (IClient<?, ?>) instantiateInstanceWithClientConfig(clientClassName, clientConfig);
      boolean initializeNFLoadBalancer =
          Boolean.parseBoolean(
              clientConfig
                  .getProperty(
                      CommonClientConfigKey.InitializeNFLoadBalancer,
                      DefaultClientConfigImpl.DEFAULT_ENABLE_LOADBALANCER)
                  .toString());
      if (initializeNFLoadBalancer) {
        loadBalancer = registerNamedLoadBalancerFromclientConfig(restClientName, clientConfig);
      }
      if (client instanceof AbstractLoadBalancerAwareClient) {
        ((AbstractLoadBalancerAwareClient) client).setLoadBalancer(loadBalancer);
      }
    } catch (Throwable e) {
      String message =
          "Unable to InitializeAndAssociateNFLoadBalancer set for RestClient:" + restClientName;
      logger.warn(message, e);
      throw new ClientException(ClientException.ErrorType.CONFIGURATION, message, e);
    }
    simpleClientMap.put(restClientName, client);

    Monitors.registerObject("Client_" + restClientName, client);

    logger.info("Client Registered:" + client.toString());
    return client;
  }
Example #8
0
 /**
  * Create and register a load balancer with the name and given the class of configClass.
  *
  * @throws ClientException if load balancer with the same name already exists or any error occurs
  * @see #instantiateInstanceWithClientConfig(String, IClientConfig)
  */
 public static ILoadBalancer registerNamedLoadBalancerFromclientConfig(
     String name, IClientConfig clientConfig) throws ClientException {
   if (namedLBMap.get(name) != null) {
     throw new ClientException("LoadBalancer for name " + name + " already exists");
   }
   ILoadBalancer lb = null;
   try {
     String loadBalancerClassName =
         (String) clientConfig.getProperty(CommonClientConfigKey.NFLoadBalancerClassName);
     lb =
         (ILoadBalancer)
             ClientFactory.instantiateInstanceWithClientConfig(
                 loadBalancerClassName, clientConfig);
     namedLBMap.put(name, lb);
     logger.info("Client:" + name + " instantiated a LoadBalancer:" + lb.toString());
     return lb;
   } catch (Exception e) {
     throw new ClientException(
         "Unable to instantiate/associate LoadBalancer with Client:" + name, e);
   }
 }
  /**
   * This method should be used when the caller wants to dispatch the request to a server chosen by
   * the load balancer, instead of specifying the server in the request's URI. It calculates the
   * final URI by calling {@link #computeFinalUriWithLoadBalancer(ClientRequest)} and then calls
   * {@link #execute(ClientRequest)}.
   *
   * @param request request to be dispatched to a server chosen by the load balancer. The URI can be
   *     a partial URI which does not contain the host name or the protocol.
   */
  public T executeWithLoadBalancer(S request) throws ClientException {
    int retries = 0;
    boolean done = false;
    boolean retryOkayOnOperation = okToRetryOnAllOperations;

    retryOkayOnOperation = request.isRetriable();
    // Is it okay to retry for this particular operation?

    // see if maxRetries has been overriden
    int numRetries = maxAutoRetriesNextServer;
    IClientConfig overriddenClientConfig = request.getOverrideConfig();
    if (overriddenClientConfig != null) {
      try {
        numRetries =
            Integer.parseInt(
                ""
                    + overriddenClientConfig.getProperty(
                        CommonClientConfigKey.MaxAutoRetriesNextServer, maxAutoRetriesNextServer));
      } catch (Exception e) {
        logger.warn(
            "Invalid maxAutoRetriesNextServer requested for RestClient:" + this.getClientName());
      }
      try {
        // Retry operation can be forcefully turned on or off for this particular request
        Boolean requestSpecificRetryOn =
            Boolean.valueOf(
                ""
                    + overriddenClientConfig.getProperty(
                        CommonClientConfigKey.RequestSpecificRetryOn, "false"));
        retryOkayOnOperation = requestSpecificRetryOn.booleanValue();
      } catch (Exception e) {
        logger.warn("Invalid RequestSpecificRetryOn set for RestClient:" + this.getClientName());
      }
    }

    T response = null;

    do {
      try {
        S resolved = computeFinalUriWithLoadBalancer(request);
        response = executeOnSingleServer(resolved);
        done = true;
      } catch (Exception e) {
        boolean shouldRetry = false;
        if (e instanceof ClientException) {
          // we dont want to retry for PUT/POST and DELETE, we can for GET
          shouldRetry = retryOkayOnOperation && numRetries > 0;
        }
        if (shouldRetry) {
          retries++;
          if (retries > numRetries) {
            throw new ClientException(
                ClientException.ErrorType.NUMBEROF_RETRIES_NEXTSERVER_EXCEEDED,
                "NUMBER_OF_RETRIES_NEXTSERVER_EXCEEDED :"
                    + numRetries
                    + " retries, while making a RestClient call for:"
                    + request.getUri()
                    + ":"
                    + getDeepestCause(e).getMessage(),
                e);
          }
          logger.error(
              "Exception while executing request which is deemed retry-able, retrying ..., Next Server Retry Attempt#:"
                  + retries
                  + ", URI tried:"
                  + request.getUri());
        } else {
          if (e instanceof ClientException) {
            throw (ClientException) e;
          } else {
            throw new ClientException(
                ClientException.ErrorType.GENERAL,
                "Unable to execute request for URI:" + request.getUri(),
                e);
          }
        }
      }
    } while (!done);
    return response;
  }
  /**
   * Execute the request on single server after the final URI is calculated. This method takes care
   * of retries and update server stats.
   */
  protected T executeOnSingleServer(S request) throws ClientException {
    boolean done = false;
    int retries = 0;

    boolean retryOkayOnOperation = okToRetryOnAllOperations;
    if (request.isRetriable()) {
      retryOkayOnOperation = true;
    }
    int numRetries = maxAutoRetries;
    URI uri = request.getUri();
    Server server = new Server(uri.getHost(), uri.getPort());
    ServerStats serverStats = null;
    ILoadBalancer lb = this.getLoadBalancer();
    if (lb instanceof AbstractLoadBalancer) {
      LoadBalancerStats lbStats = ((AbstractLoadBalancer) lb).getLoadBalancerStats();
      serverStats = lbStats.getSingleServerStat(server);
    }
    IClientConfig overriddenClientConfig = request.getOverrideConfig();
    if (overriddenClientConfig != null) {
      try {
        numRetries =
            Integer.parseInt(
                ""
                    + overriddenClientConfig.getProperty(
                        CommonClientConfigKey.MaxAutoRetries, maxAutoRetries));
      } catch (Exception e) {
        logger.warn("Invalid maxRetries requested for RestClient:" + this.clientName);
      }
    }

    T response = null;
    Exception lastException = null;
    if (tracer == null) {
      tracer =
          Monitors.newTimer(this.getClass().getName() + "_ExecutionTimer", TimeUnit.MILLISECONDS);
    }
    do {
      noteOpenConnection(serverStats, request);
      Stopwatch w = tracer.start();
      try {
        response = execute(request);
        done = true;
      } catch (Exception e) {
        if (serverStats != null) {
          serverStats.addToFailureCount();
        }
        lastException = e;
        if (isCircuitBreakerException(e) && serverStats != null) {
          serverStats.incrementSuccessiveConnectionFailureCount();
        }
        boolean shouldRetry = retryOkayOnOperation && numRetries >= 0 && isRetriableException(e);
        if (shouldRetry) {
          retries = handleRetry(uri.toString(), retries, numRetries, e);
        } else {
          ClientException niwsClientException = generateNIWSException(uri.toString(), e);
          throw niwsClientException;
        }
      } finally {
        w.stop();
        noteRequestCompletion(
            serverStats, request, response, lastException, w.getDuration(TimeUnit.MILLISECONDS));
      }
    } while (!done);
    return response;
  }
 @Override
 public void initWithNiwsConfig(IClientConfig config) {
   this.appName = config.getClientName();
 }
 public DiscoveryEnabledNIWSServerList(String vipAddresses) {
   IClientConfig clientConfig = DefaultClientConfigImpl.getClientConfigWithDefaultValues();
   clientConfig.set(Keys.DeploymentContextBasedVipAddresses, vipAddresses);
   initWithNiwsConfig(clientConfig);
 }