001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hdfs.server.namenode.ha; 019 020import java.io.Closeable; 021import java.io.IOException; 022import java.net.InetSocketAddress; 023import java.net.URI; 024 025import org.apache.hadoop.conf.Configuration; 026import org.apache.hadoop.fs.CommonConfigurationKeysPublic; 027import org.apache.hadoop.hdfs.DFSUtilClient; 028import org.apache.hadoop.hdfs.NameNodeProxies; 029import org.apache.hadoop.hdfs.client.HdfsClientConfigKeys; 030import org.apache.hadoop.hdfs.server.protocol.NamenodeProtocols; 031import org.apache.hadoop.ipc.RPC; 032import org.apache.hadoop.security.UserGroupInformation; 033 034import com.google.common.base.Preconditions; 035 036/** 037 * A NNFailoverProxyProvider implementation which works on IP failover setup. 038 * Only one proxy is used to connect to both servers and switching between 039 * the servers is done by the environment/infrastructure, which guarantees 040 * clients can consistently reach only one node at a time. 041 * 042 * Clients with a live connection will likely get connection reset after an 043 * IP failover. This case will be handled by the 044 * FailoverOnNetworkExceptionRetry retry policy. I.e. if the call is 045 * not idempotent, it won't get retried. 046 * 047 * A connection reset while setting up a connection (i.e. before sending a 048 * request) will be handled in ipc client. 049 * 050 * The namenode URI must contain a resolvable host name. 051 */ 052public class IPFailoverProxyProvider<T> extends 053 AbstractNNFailoverProxyProvider<T> { 054 private final Configuration conf; 055 private final Class<T> xface; 056 private final URI nameNodeUri; 057 private ProxyInfo<T> nnProxyInfo = null; 058 059 public IPFailoverProxyProvider(Configuration conf, URI uri, 060 Class<T> xface) { 061 Preconditions.checkArgument( 062 xface.isAssignableFrom(NamenodeProtocols.class), 063 "Interface class %s is not a valid NameNode protocol!"); 064 this.xface = xface; 065 this.nameNodeUri = uri; 066 067 this.conf = new Configuration(conf); 068 int maxRetries = this.conf.getInt( 069 HdfsClientConfigKeys.Failover.CONNECTION_RETRIES_KEY, 070 HdfsClientConfigKeys.Failover.CONNECTION_RETRIES_DEFAULT); 071 this.conf.setInt( 072 CommonConfigurationKeysPublic.IPC_CLIENT_CONNECT_MAX_RETRIES_KEY, 073 maxRetries); 074 075 int maxRetriesOnSocketTimeouts = this.conf.getInt( 076 HdfsClientConfigKeys.Failover.CONNECTION_RETRIES_ON_SOCKET_TIMEOUTS_KEY, 077 HdfsClientConfigKeys.Failover.CONNECTION_RETRIES_ON_SOCKET_TIMEOUTS_DEFAULT); 078 this.conf.setInt( 079 CommonConfigurationKeysPublic.IPC_CLIENT_CONNECT_MAX_RETRIES_ON_SOCKET_TIMEOUTS_KEY, 080 maxRetriesOnSocketTimeouts); 081 } 082 083 @Override 084 public Class<T> getInterface() { 085 return xface; 086 } 087 088 @Override 089 public synchronized ProxyInfo<T> getProxy() { 090 // Create a non-ha proxy if not already created. 091 if (nnProxyInfo == null) { 092 try { 093 // Create a proxy that is not wrapped in RetryProxy 094 InetSocketAddress nnAddr = DFSUtilClient.getNNAddress(nameNodeUri); 095 nnProxyInfo = new ProxyInfo<T>(NameNodeProxies.createNonHAProxy( 096 conf, nnAddr, xface, UserGroupInformation.getCurrentUser(), 097 false).getProxy(), nnAddr.toString()); 098 } catch (IOException ioe) { 099 throw new RuntimeException(ioe); 100 } 101 } 102 return nnProxyInfo; 103 } 104 105 /** Nothing to do for IP failover */ 106 @Override 107 public void performFailover(T currentProxy) { 108 } 109 110 /** 111 * Close the proxy, 112 */ 113 @Override 114 public synchronized void close() throws IOException { 115 if (nnProxyInfo == null) { 116 return; 117 } 118 if (nnProxyInfo.proxy instanceof Closeable) { 119 ((Closeable)nnProxyInfo.proxy).close(); 120 } else { 121 RPC.stopProxy(nnProxyInfo.proxy); 122 } 123 } 124 125 /** 126 * Logical URI is not used for IP failover. 127 */ 128 @Override 129 public boolean useLogicalURI() { 130 return false; 131 } 132}