1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.ipc;
20
21 import java.util.Queue;
22 import java.util.concurrent.BlockingQueue;
23 import java.util.concurrent.LinkedBlockingQueue;
24 import java.util.concurrent.atomic.AtomicInteger;
25
26 import org.apache.commons.lang.ArrayUtils;
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.apache.hadoop.conf.Configuration;
30 import org.apache.hadoop.hbase.Abortable;
31 import org.apache.hadoop.hbase.HBaseInterfaceAudience;
32 import org.apache.hadoop.hbase.classification.InterfaceAudience;
33 import org.apache.hadoop.hbase.classification.InterfaceStability;
34 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.Action;
35 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MultiRequest;
36 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutateRequest;
37 import org.apache.hadoop.hbase.protobuf.generated.RegionServerStatusProtos;
38 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.RegionAction;
39 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.ScanRequest;
40 import org.apache.hadoop.hbase.protobuf.generated.RPCProtos.RequestHeader;
41 import org.apache.hadoop.hbase.util.ReflectionUtils;
42
43 import com.google.protobuf.Message;
44
45
46
47
48
49
50 @InterfaceAudience.LimitedPrivate({HBaseInterfaceAudience.COPROC, HBaseInterfaceAudience.PHOENIX})
51 @InterfaceStability.Evolving
52 public class RWQueueRpcExecutor extends RpcExecutor {
53 private static final Log LOG = LogFactory.getLog(RWQueueRpcExecutor.class);
54
55 public static final String CALL_QUEUE_READ_SHARE_CONF_KEY =
56 "hbase.ipc.server.callqueue.read.ratio";
57 public static final String CALL_QUEUE_SCAN_SHARE_CONF_KEY =
58 "hbase.ipc.server.callqueue.scan.ratio";
59
60 private final QueueBalancer writeBalancer;
61 private final QueueBalancer readBalancer;
62 private final QueueBalancer scanBalancer;
63 private final int writeHandlersCount;
64 private final int readHandlersCount;
65 private final int scanHandlersCount;
66 private final int numWriteQueues;
67 private final int numReadQueues;
68 private final int numScanQueues;
69
70 private final AtomicInteger activeWriteHandlerCount = new AtomicInteger(0);
71 private final AtomicInteger activeReadHandlerCount = new AtomicInteger(0);
72 private final AtomicInteger activeScanHandlerCount = new AtomicInteger(0);
73
74 public RWQueueRpcExecutor(final String name, final int handlerCount, final int maxQueueLength,
75 final PriorityFunction priority, final Configuration conf, final Abortable abortable) {
76 super(name, handlerCount, maxQueueLength, priority, conf, abortable);
77
78 float callqReadShare = conf.getFloat(CALL_QUEUE_READ_SHARE_CONF_KEY, 0);
79 float callqScanShare = conf.getFloat(CALL_QUEUE_SCAN_SHARE_CONF_KEY, 0);
80
81 numWriteQueues = calcNumWriters(this.numCallQueues, callqReadShare);
82 writeHandlersCount = Math.max(numWriteQueues, calcNumWriters(handlerCount, callqReadShare));
83
84 int readQueues = calcNumReaders(this.numCallQueues, callqReadShare);
85 int readHandlers = Math.max(readQueues, calcNumReaders(handlerCount, callqReadShare));
86
87 int scanQueues = Math.max(0, (int)Math.floor(readQueues * callqScanShare));
88 int scanHandlers = Math.max(0, (int)Math.floor(readHandlers * callqScanShare));
89
90 if ((readQueues - scanQueues) > 0) {
91 readQueues -= scanQueues;
92 readHandlers -= scanHandlers;
93 } else {
94 scanQueues = 0;
95 scanHandlers = 0;
96 }
97
98 numReadQueues = readQueues;
99 readHandlersCount = readHandlers;
100 numScanQueues = scanQueues;
101 scanHandlersCount = scanHandlers;
102
103 this.writeBalancer = getBalancer(numWriteQueues);
104 this.readBalancer = getBalancer(numReadQueues);
105 this.scanBalancer = numScanQueues > 0 ? getBalancer(numScanQueues) : null;
106
107 initializeQueues(numWriteQueues);
108 initializeQueues(numReadQueues);
109 initializeQueues(numScanQueues);
110
111 LOG.info(getName() + " writeQueues=" + numWriteQueues + " writeHandlers=" + writeHandlersCount
112 + " readQueues=" + numReadQueues + " readHandlers=" + readHandlersCount + " scanQueues="
113 + numScanQueues + " scanHandlers=" + scanHandlersCount);
114 }
115
116 @Deprecated
117 public RWQueueRpcExecutor(final String name, final int handlerCount, final int numQueues,
118 final float readShare, final int maxQueueLength,
119 final Configuration conf, final Abortable abortable) {
120 this(name, handlerCount, numQueues, readShare, maxQueueLength, 0,
121 conf, abortable, LinkedBlockingQueue.class);
122 }
123
124 @Deprecated
125 public RWQueueRpcExecutor(final String name, final int handlerCount, final int numQueues,
126 final float readShare, final float scanShare, final int maxQueueLength) {
127 this(name, handlerCount, numQueues, readShare, scanShare, maxQueueLength, null, null);
128 }
129
130 @Deprecated
131 public RWQueueRpcExecutor(final String name, final int handlerCount, final int numQueues,
132 final float readShare, final float scanShare, final int maxQueueLength,
133 final Configuration conf, final Abortable abortable) {
134 this(name, handlerCount, numQueues, readShare, scanShare, maxQueueLength,
135 conf, abortable, LinkedBlockingQueue.class);
136 }
137
138 @Deprecated
139 public RWQueueRpcExecutor(final String name, final int handlerCount, final int numQueues,
140 final float readShare, final int maxQueueLength,
141 final Configuration conf, final Abortable abortable,
142 final Class<? extends BlockingQueue> readQueueClass, Object... readQueueInitArgs) {
143 this(name, handlerCount, numQueues, readShare, 0, maxQueueLength, conf, abortable,
144 readQueueClass, readQueueInitArgs);
145 }
146
147 @Deprecated
148 public RWQueueRpcExecutor(final String name, final int handlerCount, final int numQueues,
149 final float readShare, final float scanShare, final int maxQueueLength,
150 final Configuration conf, final Abortable abortable,
151 final Class<? extends BlockingQueue> readQueueClass, Object... readQueueInitArgs) {
152 this(name, calcNumWriters(handlerCount, readShare), calcNumReaders(handlerCount, readShare),
153 calcNumWriters(numQueues, readShare), calcNumReaders(numQueues, readShare), scanShare,
154 LinkedBlockingQueue.class, new Object[] {maxQueueLength},
155 readQueueClass, ArrayUtils.addAll(new Object[] {maxQueueLength}, readQueueInitArgs));
156 }
157
158 @Deprecated
159 public RWQueueRpcExecutor(final String name, final int handlerCount, final int numQueues,
160 final float readShare, final float scanShare,
161 final Class<? extends BlockingQueue> writeQueueClass, Object[] writeQueueInitArgs,
162 final Class<? extends BlockingQueue> readQueueClass, Object[] readQueueInitArgs) {
163 this(name, calcNumWriters(handlerCount, readShare), calcNumReaders(handlerCount, readShare),
164 calcNumWriters(numQueues, readShare), calcNumReaders(numQueues, readShare), scanShare,
165 writeQueueClass, writeQueueInitArgs,
166 readQueueClass, readQueueInitArgs);
167 }
168
169 @Deprecated
170 public RWQueueRpcExecutor(final String name, final int writeHandlers, final int readHandlers,
171 final int numWriteQueues, final int numReadQueues,
172 final Class<? extends BlockingQueue> writeQueueClass, Object[] writeQueueInitArgs,
173 final Class<? extends BlockingQueue> readQueueClass, Object[] readQueueInitArgs) {
174 this(name, writeHandlers, readHandlers, numWriteQueues, numReadQueues, 0,
175 writeQueueClass, writeQueueInitArgs, readQueueClass, readQueueInitArgs);
176 }
177
178 @Deprecated
179 public RWQueueRpcExecutor(final String name, int writeHandlers, int readHandlers,
180 int numWriteQueues, int numReadQueues, float scanShare,
181 final Class<? extends BlockingQueue> writeQueueClass, Object[] writeQueueInitArgs,
182 final Class<? extends BlockingQueue> readQueueClass, Object[] readQueueInitArgs) {
183 super(name, Math.max(writeHandlers, numWriteQueues) + Math.max(readHandlers, numReadQueues),
184 numWriteQueues + numReadQueues);
185
186 this.writeHandlersCount = Math.max(writeHandlers, numWriteQueues);
187 this.numWriteQueues = numWriteQueues;
188
189 int numScanQueues = Math.max(0, (int) Math.floor(numReadQueues * scanShare));
190 int scanHandlers = Math.max(0, (int) Math.floor(readHandlers * scanShare));
191 if ((numReadQueues - numScanQueues) > 0) {
192 numReadQueues -= numScanQueues;
193 readHandlers -= scanHandlers;
194 } else {
195 numScanQueues = 0;
196 scanHandlers = 0;
197 }
198
199 this.readHandlersCount = Math.max(readHandlers, numReadQueues);
200 this.scanHandlersCount = Math.max(scanHandlers, numScanQueues);
201 this.numReadQueues = numReadQueues;
202 this.numScanQueues = numScanQueues;
203
204 this.writeBalancer = getBalancer(numWriteQueues);
205 this.readBalancer = getBalancer(numReadQueues);
206 this.scanBalancer = numScanQueues > 0 ? getBalancer(numScanQueues) : null;
207
208 LOG.info(name + " writeQueues=" + numWriteQueues + " writeHandlers=" + writeHandlersCount
209 + " readQueues=" + numReadQueues + " readHandlers=" + readHandlersCount + " scanQueues="
210 + numScanQueues + " scanHandlers=" + scanHandlersCount);
211
212 if (writeQueueInitArgs.length > 0) {
213 currentQueueLimit = (int) writeQueueInitArgs[0];
214 writeQueueInitArgs[0] = Math.max((int) writeQueueInitArgs[0],
215 DEFAULT_CALL_QUEUE_SIZE_HARD_LIMIT);
216 }
217 for (int i = 0; i < numWriteQueues; ++i) {
218 queues.add((BlockingQueue<CallRunner>) ReflectionUtils.newInstance(writeQueueClass,
219 writeQueueInitArgs));
220 }
221
222 if (readQueueInitArgs.length > 0) {
223 currentQueueLimit = (int) readQueueInitArgs[0];
224 readQueueInitArgs[0] = Math.max((int) readQueueInitArgs[0],
225 DEFAULT_CALL_QUEUE_SIZE_HARD_LIMIT);
226 }
227 for (int i = 0; i < (numReadQueues + numScanQueues); ++i) {
228 queues.add((BlockingQueue<CallRunner>) ReflectionUtils.newInstance(readQueueClass,
229 readQueueInitArgs));
230 }
231 }
232
233 @Override
234 protected int computeNumCallQueues(final int handlerCount, final float callQueuesHandlersFactor) {
235
236 return Math.max(2, (int) Math.round(handlerCount * callQueuesHandlersFactor));
237 }
238
239 @Override
240 protected void startHandlers(final int port) {
241 startHandlers(".write", writeHandlersCount, queues, 0, numWriteQueues, port,
242 activeWriteHandlerCount);
243 startHandlers(".read", readHandlersCount, queues, numWriteQueues, numReadQueues, port,
244 activeReadHandlerCount);
245 if (numScanQueues > 0) {
246 startHandlers(".scan", scanHandlersCount, queues, numWriteQueues + numReadQueues,
247 numScanQueues, port, activeScanHandlerCount);
248 }
249 }
250
251 @Override
252 public boolean dispatch(final CallRunner callTask) throws InterruptedException {
253 RpcServer.Call call = callTask.getCall();
254 return dispatchTo(isWriteRequest(call.getHeader(), call.param),
255 shouldDispatchToScanQueue(callTask), callTask);
256 }
257
258 protected boolean dispatchTo(boolean toWriteQueue, boolean toScanQueue,
259 final CallRunner callTask) {
260 int queueIndex;
261 if (toWriteQueue) {
262 queueIndex = writeBalancer.getNextQueue();
263 } else if (toScanQueue) {
264 queueIndex = numWriteQueues + numReadQueues + scanBalancer.getNextQueue();
265 } else {
266 queueIndex = numWriteQueues + readBalancer.getNextQueue();
267 }
268
269 Queue<CallRunner> queue = queues.get(queueIndex);
270 if (queue.size() >= currentQueueLimit) {
271 return false;
272 }
273 return queue.offer(callTask);
274 }
275
276 @Override
277 public int getWriteQueueLength() {
278 int length = 0;
279 for (int i = 0; i < numWriteQueues; i++) {
280 length += queues.get(i).size();
281 }
282 return length;
283 }
284
285 @Override
286 public int getReadQueueLength() {
287 int length = 0;
288 for (int i = numWriteQueues; i < (numWriteQueues + numReadQueues); i++) {
289 length += queues.get(i).size();
290 }
291 return length;
292 }
293
294 @Override
295 public int getScanQueueLength() {
296 int length = 0;
297 for (int i = numWriteQueues + numReadQueues;
298 i < (numWriteQueues + numReadQueues + numScanQueues); i++) {
299 length += queues.get(i).size();
300 }
301 return length;
302 }
303
304 @Override
305 public int getActiveHandlerCount() {
306 return activeWriteHandlerCount.get() + activeReadHandlerCount.get()
307 + activeScanHandlerCount.get();
308 }
309
310 @Override
311 public int getActiveWriteHandlerCount() {
312 return activeWriteHandlerCount.get();
313 }
314
315 @Override
316 public int getActiveReadHandlerCount() {
317 return activeReadHandlerCount.get();
318 }
319
320 @Override
321 public int getActiveScanHandlerCount() {
322 return activeScanHandlerCount.get();
323 }
324
325 protected boolean isWriteRequest(final RequestHeader header, final Message param) {
326
327 if (param instanceof MultiRequest) {
328 MultiRequest multi = (MultiRequest)param;
329 for (RegionAction regionAction : multi.getRegionActionList()) {
330 for (Action action: regionAction.getActionList()) {
331 if (action.hasMutation()) {
332 return true;
333 }
334 }
335 }
336 }
337 if (param instanceof MutateRequest) {
338 return true;
339 }
340
341
342
343
344
345
346 if (param instanceof RegionServerStatusProtos.ReportRegionStateTransitionRequest) {
347 return true;
348 }
349 if (param instanceof RegionServerStatusProtos.RegionServerStartupRequest) {
350 return true;
351 }
352 if (param instanceof RegionServerStatusProtos.RegionServerReportRequest) {
353 return true;
354 }
355 return false;
356 }
357
358 private boolean isScanRequest(final RequestHeader header, final Message param) {
359 return param instanceof ScanRequest;
360 }
361
362 protected boolean shouldDispatchToScanQueue(final CallRunner task) {
363 RpcServer.Call call = task.getCall();
364 return numScanQueues > 0 && isScanRequest(call.getHeader(), call.param);
365 }
366
367 protected float getReadShare(final Configuration conf) {
368 return conf.getFloat(CALL_QUEUE_READ_SHARE_CONF_KEY, 0);
369 }
370
371 protected float getScanShare(final Configuration conf) {
372 return conf.getFloat(CALL_QUEUE_SCAN_SHARE_CONF_KEY, 0);
373 }
374
375
376
377
378 private static int calcNumWriters(final int count, final float readShare) {
379 return Math.max(1, count - Math.max(1, (int)Math.round(count * readShare)));
380 }
381
382
383
384
385
386 private static int calcNumReaders(final int count, final float readShare) {
387 return count - calcNumWriters(count, readShare);
388 }
389 }