之前文章已經介紹過RPC及一個RPC架構Thrift,現在再介紹一下Hadoop的RPC實作。
被調用方(也可稱為服務端)的業務代碼中必須有一個接口,而業務的具體實作寫在 此接口的實作類中(jdk的動态代理必須要有接口的),而通過org.apache.hadoop.ipc.RPC(在hadoop-common-2.2.0.jar包中)的一系列方法來釋出服務供調用方調用:
LoginService接口:
public interface LoginService {
public static final long versionID = 1L;
public String login(String username, String password);
}
注意,接口中要指定靜态的、final的成員變量versionID,否則到時候用戶端調用的時候會報異常。
接口實作類LoginServiceImpl:
public class LoginServiceImpl implements LoginService {
public String login(String username, String password) {
return username + " logged in successfully";
}
}
接口實作類隻需重寫接口的方法。
啟動服務的代碼,需要寫在某個類的main方法中,任意類,甚至可以是上述接口實作類:
public static void main(String[] args) throws HadoopIllegalArgumentException, IOException {
Builder builder = new RPC.Builder(new Configuration());
builder.setBindAddress("192.168.1.6").setPort(10000).setProtocol(LoginService.class)
.setInstance(new LoginServiceImpl());
builder.build().start();
}
首先是建立了一個org.apache.hadoop.ipc.RPC的内部類Builder的執行個體(構造方法Builder(Configuration config),此Configuration類是org.apache.hadoop.conf.Configuration,也在hadoop-common.jar包中,此處隻需new出來一個Configuration對象即可),然後用這個執行個體設定一些必須的屬性(socket通信的服務端設定的屬性),有ip位址、端口号、協定(這裡的協定指的就是接口)、接口執行個體(即接口實作類對象)。最後,調用Builder執行個體的build()方法得到org.apache.hadoop.ipc.RPC.Server對象,調動該Server對象的start()方法即啟動了服務,或者說是釋出了服務。
調用方(也可以稱為用戶端)也必須有和服務端一樣的一個接口,代碼一緻,且所在包也需得一緻(實測如果包名不一緻的話,會報org.apache.hadoop.ipc.RpcServerException): Unknown protocol 異常):
LoginService接口:
public interface LoginService {
public static final long versionID = 1L;
public String login(String username, String password);
}
調用服務代碼:
@Test
public void test1() throws IOException {
LoginService proxy = RPC.getProxy(LoginService.class, 1L, new InetSocketAddress("192.168.1.6", 10000),
new Configuration());
String result = proxy.login("yangmi", "123");
System.out.println(result);
}
主要就是利用org.apache.hadoop.ipc.RPC的getProxy(Class<T> protocol,long clientVersion,InetSocketAddress addr, Configuration conf)方法(此方法裡的protocol也就是接口,clientVersion也就是接口代碼中配置的versionID的值,InetSocketAddress執行個體可以通過InetSocketAddress(String hostname, int port)構造器new出來。)獲得接口對象(其實是個代理對象),然後調用此對象的業務方法的效果就等同于直接調服務端業務方法的效果一樣。
至此,就完成了Hadoop的RPC。