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.DFSConfigKeys; 028import org.apache.hadoop.hdfs.NameNodeProxies; 029import org.apache.hadoop.hdfs.server.namenode.NameNode; 030import org.apache.hadoop.hdfs.server.protocol.NamenodeProtocols; 031import org.apache.hadoop.io.retry.FailoverProxyProvider; 032import org.apache.hadoop.ipc.RPC; 033import org.apache.hadoop.security.UserGroupInformation; 034 035import com.google.common.base.Preconditions; 036 037/** 038 * A NNFailoverProxyProvider implementation which works on IP failover setup. 039 * Only one proxy is used to connect to both servers and switching between 040 * the servers is done by the environment/infrastructure, which guarantees 041 * clients can consistently reach only one node at a time. 042 * 043 * Clients with a live connection will likely get connection reset after an 044 * IP failover. This case will be handled by the 045 * FailoverOnNetworkExceptionRetry retry policy. I.e. if the call is 046 * not idempotent, it won't get retried. 047 * 048 * A connection reset while setting up a connection (i.e. before sending a 049 * request) will be handled in ipc client. 050 * 051 * The namenode URI must contain a resolvable host name. 052 */ 053public class IPFailoverProxyProvider<T> extends 054 AbstractNNFailoverProxyProvider<T> { 055 private final Configuration conf; 056 private final Class<T> xface; 057 private final URI nameNodeUri; 058 private ProxyInfo<T> nnProxyInfo = null; 059 060 public IPFailoverProxyProvider(Configuration conf, URI uri, 061 Class<T> xface) { 062 Preconditions.checkArgument( 063 xface.isAssignableFrom(NamenodeProtocols.class), 064 "Interface class %s is not a valid NameNode protocol!"); 065 this.xface = xface; 066 this.nameNodeUri = uri; 067 068 this.conf = new Configuration(conf); 069 int maxRetries = this.conf.getInt( 070 DFSConfigKeys.DFS_CLIENT_FAILOVER_CONNECTION_RETRIES_KEY, 071 DFSConfigKeys.DFS_CLIENT_FAILOVER_CONNECTION_RETRIES_DEFAULT); 072 this.conf.setInt( 073 CommonConfigurationKeysPublic.IPC_CLIENT_CONNECT_MAX_RETRIES_KEY, 074 maxRetries); 075 076 int maxRetriesOnSocketTimeouts = this.conf.getInt( 077 DFSConfigKeys.DFS_CLIENT_FAILOVER_CONNECTION_RETRIES_ON_SOCKET_TIMEOUTS_KEY, 078 DFSConfigKeys.DFS_CLIENT_FAILOVER_CONNECTION_RETRIES_ON_SOCKET_TIMEOUTS_DEFAULT); 079 this.conf.setInt( 080 CommonConfigurationKeysPublic.IPC_CLIENT_CONNECT_MAX_RETRIES_ON_SOCKET_TIMEOUTS_KEY, 081 maxRetriesOnSocketTimeouts); 082 } 083 084 @Override 085 public Class<T> getInterface() { 086 return xface; 087 } 088 089 @Override 090 public synchronized ProxyInfo<T> getProxy() { 091 // Create a non-ha proxy if not already created. 092 if (nnProxyInfo == null) { 093 try { 094 // Create a proxy that is not wrapped in RetryProxy 095 InetSocketAddress nnAddr = NameNode.getAddress(nameNodeUri); 096 nnProxyInfo = new ProxyInfo<T>(NameNodeProxies.createNonHAProxy( 097 conf, nnAddr, xface, UserGroupInformation.getCurrentUser(), 098 false).getProxy(), nnAddr.toString()); 099 } catch (IOException ioe) { 100 throw new RuntimeException(ioe); 101 } 102 } 103 return nnProxyInfo; 104 } 105 106 /** Nothing to do for IP failover */ 107 @Override 108 public void performFailover(T currentProxy) { 109 } 110 111 /** 112 * Close the proxy, 113 */ 114 @Override 115 public synchronized void close() throws IOException { 116 if (nnProxyInfo == null) { 117 return; 118 } 119 if (nnProxyInfo.proxy instanceof Closeable) { 120 ((Closeable)nnProxyInfo.proxy).close(); 121 } else { 122 RPC.stopProxy(nnProxyInfo.proxy); 123 } 124 } 125 126 /** 127 * Logical URI is not used for IP failover. 128 */ 129 @Override 130 public boolean useLogicalURI() { 131 return false; 132 } 133}