1 /* 2 * ==================================================================== 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * ==================================================================== 20 * 21 * This software consists of voluntary contributions made by many 22 * individuals on behalf of the Apache Software Foundation. For more 23 * information on the Apache Software Foundation, please see 24 * <http://www.apache.org/>. 25 * 26 */ 27 package org.apache.hc.client5.http.impl.classic; 28 29 import org.apache.hc.client5.http.HttpRoute; 30 import org.apache.hc.core5.pool.ConnPoolControl; 31 import org.apache.hc.core5.util.Args; 32 import org.slf4j.Logger; 33 import org.slf4j.LoggerFactory; 34 35 /** 36 * A backoff manager implementation that uses an exponential backoff algorithm to adjust the maximum 37 * number of connections per HTTP route. The algorithm reduces the number of connections in response 38 * to adverse events, such as connection failures, and gradually increases the number of connections 39 * when the route is operating without issues. 40 * 41 * <p>This implementation is specifically designed for managing connections in an HTTP route context 42 * and provides methods for probing and backing off connections based on the performance of the route. 43 * 44 * <p>The exponential backoff algorithm is primarily implemented in the {@code getBackedOffPoolSize} 45 * method, which calculates the new connection pool size based on the current pool size, growth rate, 46 * and the number of time intervals. 47 * 48 * @since 5.3 49 */ 50 public class ExponentialBackoffManager extends AbstractBackoff { 51 52 private static final Logger LOG = LoggerFactory.getLogger(ExponentialBackoffManager.class); 53 54 55 /** 56 * Constructs a new ExponentialBackoffManager with the specified connection pool control. 57 * 58 * @param connPerRoute the connection pool control to be used for managing connections 59 * @throws IllegalArgumentException if connPerRoute is null 60 */ 61 public ExponentialBackoffManager(final ConnPoolControl<HttpRoute> connPerRoute) { 62 super(connPerRoute); 63 64 } 65 66 /** 67 * Calculates the new pool size after applying the exponential backoff algorithm. 68 * The new pool size is calculated using the formula: floor(curr / (1 + growthRate) ^ t), 69 * where curr is the current pool size, growthRate is the exponential growth rate, and t is the time interval. 70 * 71 * @param curr the current pool size 72 * @return the new pool size after applying the backoff 73 */ 74 protected int getBackedOffPoolSize(final int curr) { 75 if (curr <= 1) { 76 return 1; 77 } 78 final int t = getTimeInterval().incrementAndGet(); 79 final int result = Math.max(1, (int) Math.floor(curr / Math.pow(1 + getBackoffFactor().get(), t))); 80 81 if (LOG.isDebugEnabled()) { 82 LOG.debug("curr={}, t={}, growthRate={}, result={}", curr, t, getBackoffFactor().get(), result); 83 } 84 return result; 85 } 86 87 public void setBackoffFactor(final double rate) { 88 Args.check(rate > 0.0, "Growth rate must be greater than 0.0"); 89 this.getBackoffFactor().set(rate); 90 } 91 92 }