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 com.google.common.annotations.VisibleForTesting;
22 import com.google.protobuf.BlockingRpcChannel;
23 import com.google.protobuf.Descriptors;
24 import com.google.protobuf.Message;
25 import com.google.protobuf.RpcController;
26 import com.google.protobuf.ServiceException;
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.CellScanner;
31 import org.apache.hadoop.hbase.HConstants;
32 import org.apache.hadoop.hbase.ServerName;
33 import org.apache.hadoop.hbase.classification.InterfaceAudience;
34 import org.apache.hadoop.hbase.codec.Codec;
35 import org.apache.hadoop.hbase.codec.KeyValueCodec;
36 import org.apache.hadoop.hbase.security.User;
37 import org.apache.hadoop.hbase.security.UserProvider;
38 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
39 import org.apache.hadoop.hbase.util.Pair;
40 import org.apache.hadoop.hbase.util.PoolMap;
41 import org.apache.hadoop.io.compress.CompressionCodec;
42
43 import java.io.IOException;
44 import java.net.InetSocketAddress;
45 import java.net.SocketAddress;
46
47
48
49
50 @InterfaceAudience.Private
51 public abstract class AbstractRpcClient implements RpcClient {
52 public static final Log LOG = LogFactory.getLog(AbstractRpcClient.class);
53
54 protected final Configuration conf;
55 protected String clusterId;
56 protected final SocketAddress localAddr;
57
58 protected UserProvider userProvider;
59 protected final IPCUtil ipcUtil;
60
61 protected final int minIdleTimeBeforeClose;
62
63 protected final int maxRetries;
64 protected final long failureSleep;
65 protected final boolean tcpNoDelay;
66 protected final boolean tcpKeepAlive;
67 protected final Codec codec;
68 protected final CompressionCodec compressor;
69 protected final boolean fallbackAllowed;
70
71 protected final int connectTO;
72 protected final int readTO;
73 protected final int writeTO;
74
75
76
77
78
79
80
81
82 public AbstractRpcClient(Configuration conf, String clusterId, SocketAddress localAddr) {
83 this.userProvider = UserProvider.instantiate(conf);
84 this.localAddr = localAddr;
85 this.tcpKeepAlive = conf.getBoolean("hbase.ipc.client.tcpkeepalive", true);
86 this.clusterId = clusterId != null ? clusterId : HConstants.CLUSTER_ID_DEFAULT;
87 this.failureSleep = conf.getLong(HConstants.HBASE_CLIENT_PAUSE,
88 HConstants.DEFAULT_HBASE_CLIENT_PAUSE);
89 this.maxRetries = conf.getInt("hbase.ipc.client.connect.max.retries", 0);
90 this.tcpNoDelay = conf.getBoolean("hbase.ipc.client.tcpnodelay", true);
91 this.ipcUtil = new IPCUtil(conf);
92
93 this.minIdleTimeBeforeClose = conf.getInt(IDLE_TIME, 120000);
94 this.conf = conf;
95 this.codec = getCodec();
96 this.compressor = getCompressor(conf);
97 this.fallbackAllowed = conf.getBoolean(IPC_CLIENT_FALLBACK_TO_SIMPLE_AUTH_ALLOWED_KEY,
98 IPC_CLIENT_FALLBACK_TO_SIMPLE_AUTH_ALLOWED_DEFAULT);
99 this.connectTO = conf.getInt(SOCKET_TIMEOUT_CONNECT, DEFAULT_SOCKET_TIMEOUT_CONNECT);
100 this.readTO = conf.getInt(SOCKET_TIMEOUT_READ, DEFAULT_SOCKET_TIMEOUT_READ);
101 this.writeTO = conf.getInt(SOCKET_TIMEOUT_WRITE, DEFAULT_SOCKET_TIMEOUT_WRITE);
102
103
104 if (LOG.isDebugEnabled()) {
105 LOG.debug("Codec=" + this.codec + ", compressor=" + this.compressor +
106 ", tcpKeepAlive=" + this.tcpKeepAlive +
107 ", tcpNoDelay=" + this.tcpNoDelay +
108 ", connectTO=" + this.connectTO +
109 ", readTO=" + this.readTO +
110 ", writeTO=" + this.writeTO +
111 ", minIdleTimeBeforeClose=" + this.minIdleTimeBeforeClose +
112 ", maxRetries=" + this.maxRetries +
113 ", fallbackAllowed=" + this.fallbackAllowed +
114 ", bind address=" + (this.localAddr != null ? this.localAddr : "null"));
115 }
116 }
117
118 @VisibleForTesting
119 public static String getDefaultCodec(final Configuration c) {
120
121
122
123 return c.get(DEFAULT_CODEC_CLASS, KeyValueCodec.class.getCanonicalName());
124 }
125
126
127
128
129
130 Codec getCodec() {
131
132
133 String className = conf.get(HConstants.RPC_CODEC_CONF_KEY, getDefaultCodec(this.conf));
134 if (className == null || className.length() == 0) return null;
135 try {
136 return (Codec)Class.forName(className).newInstance();
137 } catch (Exception e) {
138 throw new RuntimeException("Failed getting codec " + className, e);
139 }
140 }
141
142
143
144
145
146
147 private static CompressionCodec getCompressor(final Configuration conf) {
148 String className = conf.get("hbase.client.rpc.compressor", null);
149 if (className == null || className.isEmpty()) return null;
150 try {
151 return (CompressionCodec)Class.forName(className).newInstance();
152 } catch (Exception e) {
153 throw new RuntimeException("Failed getting compressor " + className, e);
154 }
155 }
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173 protected static PoolMap.PoolType getPoolType(Configuration config) {
174 return PoolMap.PoolType
175 .valueOf(config.get(HConstants.HBASE_CLIENT_IPC_POOL_TYPE), PoolMap.PoolType.RoundRobin,
176 PoolMap.PoolType.ThreadLocal);
177 }
178
179
180
181
182
183
184
185
186 protected static int getPoolSize(Configuration config) {
187 return config.getInt(HConstants.HBASE_CLIENT_IPC_POOL_SIZE, 1);
188 }
189
190
191
192
193
194
195
196
197
198
199 Message callBlockingMethod(Descriptors.MethodDescriptor md, PayloadCarryingRpcController pcrc,
200 Message param, Message returnType, final User ticket, final InetSocketAddress isa)
201 throws ServiceException {
202 long startTime = 0;
203 if (LOG.isTraceEnabled()) {
204 startTime = EnvironmentEdgeManager.currentTime();
205 }
206 int callTimeout = 0;
207 CellScanner cells = null;
208 if (pcrc != null) {
209 callTimeout = pcrc.getCallTimeout();
210 cells = pcrc.cellScanner();
211
212 pcrc.setCellScanner(null);
213 }
214 Pair<Message, CellScanner> val;
215 try {
216 val = call(pcrc, md, param, cells, returnType, ticket, isa, callTimeout,
217 pcrc != null? pcrc.getPriority(): HConstants.NORMAL_QOS);
218 if (pcrc != null) {
219
220 if (val.getSecond() != null) pcrc.setCellScanner(val.getSecond());
221 } else if (val.getSecond() != null) {
222 throw new ServiceException("Client dropping data on the floor!");
223 }
224
225 if (LOG.isTraceEnabled()) {
226 long callTime = EnvironmentEdgeManager.currentTime() - startTime;
227 LOG.trace("Call: " + md.getName() + ", callTime: " + callTime + "ms");
228 }
229 return val.getFirst();
230 } catch (Throwable e) {
231 throw new ServiceException(e);
232 }
233 }
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248 protected abstract Pair<Message, CellScanner> call(PayloadCarryingRpcController pcrc,
249 Descriptors.MethodDescriptor md, Message param, CellScanner cells,
250 Message returnType, User ticket, InetSocketAddress addr, int callTimeout, int priority) throws
251 IOException, InterruptedException;
252
253
254
255
256
257
258 @Override
259 public BlockingRpcChannel createBlockingRpcChannel(final ServerName sn,
260 final User ticket, int defaultOperationTimeout) {
261 return new BlockingRpcChannelImplementation(this, sn, ticket, defaultOperationTimeout);
262 }
263
264
265
266
267 @VisibleForTesting
268 public static class BlockingRpcChannelImplementation implements BlockingRpcChannel {
269 private final InetSocketAddress isa;
270 private final AbstractRpcClient rpcClient;
271 private final User ticket;
272 private final int defaultOperationTimeout;
273
274
275
276
277
278 protected BlockingRpcChannelImplementation(final AbstractRpcClient rpcClient,
279 final ServerName sn, final User ticket, int defaultOperationTimeout) {
280 this.isa = new InetSocketAddress(sn.getHostname(), sn.getPort());
281 this.rpcClient = rpcClient;
282 this.ticket = ticket;
283 this.defaultOperationTimeout = defaultOperationTimeout;
284 }
285
286 @Override
287 public Message callBlockingMethod(Descriptors.MethodDescriptor md, RpcController controller,
288 Message param, Message returnType) throws ServiceException {
289 PayloadCarryingRpcController pcrc;
290 if (controller != null) {
291 pcrc = (PayloadCarryingRpcController) controller;
292 if (!pcrc.hasCallTimeout()){
293 pcrc.setCallTimeout(defaultOperationTimeout);
294 }
295 } else {
296 pcrc = new PayloadCarryingRpcController();
297 pcrc.setCallTimeout(defaultOperationTimeout);
298 }
299
300 return this.rpcClient.callBlockingMethod(md, pcrc, param, returnType, this.ticket, this.isa);
301 }
302 }
303 }