View Javadoc
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.annotation.Contract;
31  import org.apache.hc.core5.annotation.ThreadingBehavior;
32  import org.apache.hc.core5.pool.ConnPoolControl;
33  import org.apache.hc.core5.util.Args;
34  
35  /**
36   * <p>The {@code AIMDBackoffManager} applies an additive increase,
37   * multiplicative decrease (AIMD) to managing a dynamic limit to
38   * the number of connections allowed to a given host. You may want
39   * to experiment with the settings for the cooldown periods and the
40   * backoff factor to get the adaptive behavior you want.</p>
41   *
42   * <p>Generally speaking, shorter cooldowns will lead to more steady-state
43   * variability but faster reaction times, while longer cooldowns
44   * will lead to more stable equilibrium behavior but slower reaction
45   * times.</p>
46   *
47   * <p>Similarly, higher backoff factors promote greater
48   * utilization of available capacity at the expense of fairness
49   * among clients. Lower backoff factors allow equal distribution of
50   * capacity among clients (fairness) to happen faster, at the
51   * expense of having more server capacity unused in the short term.</p>
52   *
53   * @since 4.2
54   */
55  @Contract(threading = ThreadingBehavior.SAFE)
56  public class AIMDBackoffManager extends AbstractBackoff {
57  
58      /**
59       * Constructs an {@code AIMDBackoffManager} with the specified
60       * {@link ConnPoolControl} and {@link Clock}.
61       * <p>
62       * This constructor is primarily used for testing purposes, allowing the
63       * injection of a custom {@link Clock} implementation.
64       *
65       * @param connPerRoute the {@link ConnPoolControl} that manages
66       *                     per-host routing maximums
67       */
68      public AIMDBackoffManager(final ConnPoolControl<HttpRoute> connPerRoute) {
69          super(connPerRoute);
70      }
71  
72      /**
73       * Returns the backed-off pool size based on the current pool size.
74       * The new pool size is calculated as the floor of (backoffFactor * curr).
75       *
76       * @param curr the current pool size
77       * @return the backed-off pool size, with a minimum value of 1
78       */
79      protected int getBackedOffPoolSize(final int curr) {
80          if (curr <= 1) {
81              return 1;
82          }
83          return (int) (Math.floor(getBackoffFactor().get() * curr));
84      }
85  
86  
87      /**
88       * Sets the factor to use when backing off; the new
89       * per-host limit will be roughly the current max times
90       * this factor. {@code Math.floor} is applied in the
91       * case of non-integer outcomes to ensure we actually
92       * decrease the pool size. Pool sizes are never decreased
93       * below 1, however. Defaults to 0.5.
94       * @param d must be between 0.0 and 1.0, exclusive.
95       */
96      @Override
97      public void setBackoffFactor(final double d) {
98          Args.check(d > 0.0 && d < 1.0, "Backoff factor must be 0.0 < f < 1.0");
99          getBackoffFactor().set(d);
100     }
101 
102 }