View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.client;
19  
20  import org.apache.hadoop.conf.Configuration;
21  import org.apache.hadoop.hbase.HConstants;
22  import org.apache.hadoop.hbase.ServerName;
23  import org.apache.hadoop.hbase.client.backoff.ExponentialClientBackoffPolicy;
24  import org.apache.hadoop.hbase.client.backoff.ServerStatistics;
25  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos;
26  import org.apache.hadoop.hbase.testclassification.SmallTests;
27  import org.apache.hadoop.hbase.util.Bytes;
28  import org.junit.Test;
29  import org.junit.experimental.categories.Category;
30  import org.mockito.Mockito;
31  
32  import static org.junit.Assert.assertEquals;
33  import static org.junit.Assert.assertTrue;
34  
35  @Category(SmallTests.class)
36  public class TestClientExponentialBackoff {
37  
38    ServerName server = Mockito.mock(ServerName.class);
39    byte[] regionname = Bytes.toBytes("region");
40  
41    @Test
42    public void testNulls() {
43      Configuration conf = new Configuration(false);
44      ExponentialClientBackoffPolicy backoff = new ExponentialClientBackoffPolicy(conf);
45      assertEquals(0, backoff.getBackoffTime(null, null, null));
46  
47      // server name doesn't matter to calculation, but check it now anyways
48      assertEquals(0, backoff.getBackoffTime(server, null, null));
49      assertEquals(0, backoff.getBackoffTime(server, regionname, null));
50  
51      // check when no stats for the region yet
52      ServerStatistics stats = new ServerStatistics();
53      assertEquals(0, backoff.getBackoffTime(server, regionname, stats));
54    }
55  
56    @Test
57    public void testMaxLoad() {
58      Configuration conf = new Configuration(false);
59      ExponentialClientBackoffPolicy backoff = new ExponentialClientBackoffPolicy(conf);
60  
61      ServerStatistics stats = new ServerStatistics();
62      update(stats, 100);
63      assertEquals(ExponentialClientBackoffPolicy.DEFAULT_MAX_BACKOFF, backoff.getBackoffTime(server,
64          regionname, stats));
65  
66      // another policy with a different max timeout
67      long max = 100;
68      conf.setLong(ExponentialClientBackoffPolicy.MAX_BACKOFF_KEY, max);
69      ExponentialClientBackoffPolicy backoffShortTimeout = new ExponentialClientBackoffPolicy(conf);
70      assertEquals(max, backoffShortTimeout.getBackoffTime(server, regionname, stats));
71  
72      // test beyond 100 still doesn't exceed the max
73      update(stats, 101);
74      assertEquals(ExponentialClientBackoffPolicy.DEFAULT_MAX_BACKOFF, backoff.getBackoffTime(server,
75          regionname, stats));
76      assertEquals(max, backoffShortTimeout.getBackoffTime(server, regionname, stats));
77  
78      // and that when we are below 100, its less than the max timeout
79      update(stats, 99);
80      assertTrue(backoff.getBackoffTime(server,
81          regionname, stats) < ExponentialClientBackoffPolicy.DEFAULT_MAX_BACKOFF);
82      assertTrue(backoffShortTimeout.getBackoffTime(server, regionname, stats) < max);
83    }
84  
85    /**
86     * Make sure that we get results in the order that we expect - backoff for a load of 1 should
87     * less than backoff for 10, which should be less than that for 50.
88     */
89    @Test
90    public void testResultOrdering() {
91      Configuration conf = new Configuration(false);
92      // make the max timeout really high so we get differentiation between load factors
93      conf.setLong(ExponentialClientBackoffPolicy.MAX_BACKOFF_KEY, Integer.MAX_VALUE);
94      ExponentialClientBackoffPolicy backoff = new ExponentialClientBackoffPolicy(conf);
95  
96      ServerStatistics stats = new ServerStatistics();
97      long previous = backoff.getBackoffTime(server, regionname, stats);
98      for (int i = 1; i <= 100; i++) {
99        update(stats, i);
100       long next = backoff.getBackoffTime(server, regionname, stats);
101       assertTrue(
102           "Previous backoff time" + previous + " >= " + next + ", the next backoff time for " +
103               "load " + i, previous < next);
104       previous = next;
105     }
106   }
107 
108   @Test
109   public void testHeapOccupancyPolicy() {
110     Configuration conf = new Configuration(false);
111     ExponentialClientBackoffPolicy backoff = new ExponentialClientBackoffPolicy(conf);
112 
113     ServerStatistics stats = new ServerStatistics();
114     long backoffTime;
115 
116     update(stats, 0, 95, 0);
117     backoffTime = backoff.getBackoffTime(server, regionname, stats);
118     assertTrue("Heap occupancy at low watermark had no effect", backoffTime > 0);
119 
120     long previous = backoffTime;
121     update(stats, 0, 96, 0);
122     backoffTime = backoff.getBackoffTime(server, regionname, stats);
123     assertTrue("Increase above low watermark should have increased backoff",
124       backoffTime > previous);
125 
126     update(stats, 0, 98, 0);
127     backoffTime = backoff.getBackoffTime(server, regionname, stats);
128     assertEquals("We should be using max backoff when at high watermark", backoffTime,
129       ExponentialClientBackoffPolicy.DEFAULT_MAX_BACKOFF);
130   }
131 
132   @Test
133   public void testCompactionPressurePolicy() {
134     Configuration conf = new Configuration(false);
135     ExponentialClientBackoffPolicy backoff = new ExponentialClientBackoffPolicy(conf);
136 
137     ServerStatistics stats = new ServerStatistics();
138     long backoffTime;
139 
140     update(stats, 0, 0, 0);
141     backoffTime = backoff.getBackoffTime(server, regionname, stats);
142     assertTrue("Compaction pressure has no effect", backoffTime == 0);
143 
144         long previous = backoffTime;
145     update(stats, 0, 0, 50);
146     backoffTime = backoff.getBackoffTime(server, regionname, stats);
147     assertTrue("Compaction pressure should be bigger",
148             backoffTime > previous);
149 
150     update(stats, 0, 0, 100);
151     backoffTime = backoff.getBackoffTime(server, regionname, stats);
152     assertEquals("under heavy compaction pressure", backoffTime,
153             ExponentialClientBackoffPolicy.DEFAULT_MAX_BACKOFF);
154   }
155 
156   private void update(ServerStatistics stats, int load) {
157     ClientProtos.RegionLoadStats stat = ClientProtos.RegionLoadStats.newBuilder()
158         .setMemstoreLoad
159             (load).build();
160     stats.update(regionname, stat);
161   }
162 
163   private void update(ServerStatistics stats, int memstoreLoad, int heapOccupancy,
164                       int compactionPressure) {
165     ClientProtos.RegionLoadStats stat = ClientProtos.RegionLoadStats.newBuilder()
166         .setMemstoreLoad(memstoreLoad)
167         .setHeapOccupancy(heapOccupancy)
168         .setCompactionPressure(compactionPressure)
169             .build();
170     stats.update(regionname, stat);
171   }
172 }