注目点は、迷子にしないでください。Java関連のテクノロジーと継続的に更新情報!!!
、RPCの紹介
彼らは最近、Hadoopの基礎となる通信はRPCによって達成されます。
RPC(リモートプロシージャコールプロトコル)、リモートコール:リモートプロシージャコール隠された内容の通信ネットワークが、あなたがコンピュータをプログラムするために別のコンピュータのサブルーチンコールを実行することを可能にする一般的な分散型ネットワーク通信プロトコルでありますこのプログラムの追加なしのユーザ対話するように。RPCで実装分散システム間のほとんどの通信
二、RPC要求手順
- クライアントは、サービスを呼び出す要求を送信します
- この方法は、ネットワークが要求を開始し、サービス側のアドレス、formatパラメータでカプセル化され、エージェントのクライアントスタブを呼び出します
- サーバにネットワークによって送信されたメッセージは、サーバ・スタブは、メッセージを受信し、対応するサービスコールをローカル反射をアンパック
- ローカルサービスの実行はサーバースタブに結果を返し、サーバスタブは、再度クライアントパッケージにメッセージを発生します
- 最終的な結果を得るために復号されたメッセージを受信したクライアントスタブ。
三、RPCフレームワークのアーキテクチャ
RPCフレームワーク、コンポーネントが必要に書きますか?
- シリアル化。シリアライゼーション主な役割は、ネットワークを介して永続ストレージまたは伝送に書き込むバイトのストリームにオブジェクトが構成されています。
- 一般的に、JDKの動的プロキシまたはCGLIBを使用してリモートプロキシオブジェクト、
- 代理店サービスは、レジストリの飼育係を公開します
- ネットワーク通信、イベント駆動型モードリアクトル
四、RPC例示的なフレーム
- サービスプロバイダは、サービス・インターフェース定義とサービス実装クラスを提供し、サーバ側で実行されています
- サービス出版社は、サーバー側で実行すると、ローカルサービスを担当してリモートサービス、リモート管理サービス、消費者に提供するサービスに公開
- 消費者サービスは、クライアント上で実行して、リモートプロキシオブジェクトを介してリモートサービスを呼び出します
サーバ・コード
サービスインタフェース:
//计算学生年龄和的接
public interface CalculateService {
String cal(Student sta, Student stb);
}
public class CalculateServiceImpl implements CalculateService {
@Override
public String cal(Student sta, Student stb) {
return "学生年龄之和:" + (sta.getAge() + stb.getAge());
}
}
サービスリリース
public class PublishUtilI {
//服务接口集合
private static List<Object> serviceList;
private static ThreadPoolExecutor executor = new ThreadPoolExecutor(5,10,10, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(10));
public static void publish(int port,Object... services) throws IOException {
serviceList= Arrays.asList(services);
ServerSocket server = new ServerSocket(port);
Socket client;
while (true) {
//阻塞等待请求
client = server.accept();
//使用线程池处理请求
executor.submit(new ServerHandler(client, serviceList));
}
}
}
リフレクションコールサービス
-
クライアントから送信されたサービス名を読み込み
-
サービスがリリースされるかどうかを確認
-
リリースされた場合は、対応するサービスコールサーバを反映
-
クライアントに結果を返します。
パブリッククラスServerHandlerはRunnableを実装して、{
プライベートソケットクライアント= NULLを。
プライベートリストserviceList = NULL;
公共ServerHandler(ソケットクライアント、リストサービス){
this.client =クライアント。
this.serviceList =サービス。
}
@Override
ます。public void実行(){
してみてください(
ObjectInputStreamの入力=新しいObjectInputStreamの(client.getInputStream());
ObjectOutputStreamの出力は=新しいObjectOutputStreamの(client.getOutputStream())
){
//读取客户端要访问那个サービス
クラスserviceClass =(クラス)input.readObject();
//找到该服务类
オブジェクトOBJ = findService(serviceClass)。
もし(OBJ == NULL){
output.writeObject(serviceClass.getName()+「服务未发现」)。
他{}
//メソッドを呼び出すためにリフレクションを使用して、結果を返す
文字列methodNameの= input.readUTF(); //読み出す符号化UTF文字列
//読み取りパラメータ型
クラス[] parameterTypesパラメータ=(クラス< <>? > [])input.readObject();
//読み取りパラメータ
オブジェクト[] =引数(オブジェクト[])input.readObject()
。メソッド、メソッドobj.getClass =()getMethod(methodNameの、parameterTypesパラメータ);
//反射メソッドの実行
; =(OBJ、引数)オブジェクトMethod.invoke結果
、output.writeObject(結果)
}
キャッチ(例外E){}
e.printStackTrace();
}
}
プライベートfindServiceオブジェクト(クラスserviceClass){
(対象物OBJのために: serviceList){
ブールisFather = serviceClass.isAssignableFrom(obj.getClass());
IF(isFather){
OBJを返します。
}
}
はnullを返します。
}
}
クライアントコード
public class Client {
public static void main(String[] args) {
CallProxyHandler handler = new CallProxyHandler("127.0.0.1", 1111);
CalculateService calculateService = handler.getService(CalculateService.class);
Student sta = new Student(1);
Student stb = new Student(2);
String result = calculateService.cal(sta, stb);
System.out.println(result);
}
}
リモートサーバーに公開サービスを呼び出すためにプロキシクラスを作成します。
public class CallProxyHandler implements InvocationHandler {
private String ip;
private int port;
public CallProxyHandler(String ip, int port) {
this.ip = ip;
this.port = port;
}
/**
* 获取代理对象
* @param clazz
* @param <T>
* @return
*/
@SuppressWarnings("all")
public <T> T getService(Class<T> clazz) {
return (T) Proxy.newProxyInstance(CallProxyHandler.class.getClassLoader(),
new Class<?>[] {clazz}, this);
}
/**
* 将需要调用服务的方法名,参数类型,参数按照一定格式封装发送至服务端
* 读取服务端返回的结果
* @param proxy
* @param method
* @param args
* @return
* @throws Throwable
*/
@SuppressWarnings("all")
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try (
Socket socket = new Socket(ip, port);
ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream input = new ObjectInputStream(socket.getInputStream())
) {
output.writeObject(proxy.getClass().getInterfaces()[0]);
output.writeUTF(method.getName());
output.writeObject(method.getParameterTypes());
output.writeObject(args);
output.flush();
Object result = input.readObject();
if (result instanceof Throwable) {
throw (Throwable) result;
}
return result;
}
}
}
このように、簡単なRPCサービス呼び出しフレームワークが完成されます。しかし、多くの問題があります。
- シリアライゼーションのJava運ぶ、効率が高くなく、HadoopのアブロいるProtobufを使用することができます
- ネットワーク通信のための網状フレームワークを使用し、高い並行性に対応できない、ネットワーク送信のためBIOの方法を使用
- レジストリの欠如は、登録サービスは、飼育係を管理するために使用することができます。
収集したいくつかのソース解析、ダボ、Redisの、ネッティー、飼育係、春、雲、分散されたデータを与え、共有、コメント、共有知識のJava毎日を次の