<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    2012年12月26日

    簡單的遠程調用實現

    最近看到一個遠程調用的簡單實現,于是加上自己的理解分享給大家。
    遠程調用是典型的CS模型,Server端提供服務,客戶端調用得到結果

    先看服務端提供服務的方法
     1 /**
     2      * 提供服務
     3      *
     4      * @param service 服務實現
     5      * @param port    端口(可以雙發約定)
     6      * @throws Exception
     7      */
     8     public static void provide(final Object service, final int port) throws Exception {
     9         //參數檢查
    10         if (service == null) {
    11             throw new IllegalArgumentException("The service can't be null!");
    12         }
    13         if (port > 65535) {
    14             throw new IllegalArgumentException("The host can't greater than 65535!");
    15         }
    16         //開啟一個ServerSocket接收請求
    17         ServerSocket serverSocket = new ServerSocket(port);
    18         //死循環等待請求
    19         while (true) {
    20             //接受到請求,獲取socket
    21             final Socket socket = serverSocket.accept();
    22             try {
    23                 //開啟一個線程處理
    24                 new Thread(new Runnable() {
    25                     @Override
    26                     public void run() {
    27                         try {
    28                             try {
    29                                 //重socket中獲取輸入流
    30                                 ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
    31                                 try {
    32                                     //獲取方法名
    33                                     String methodName = ois.readUTF();
    34                                     //獲取方法參數數組
    35                                     Class[] methodParameterTypes = (Class[]) ois.readObject();
    36                                     //獲取參數值數組
    37                                     Object[] arguments = (Object[]) ois.readObject();
    38                                     //根據方法名和方法參數獲取方法(根據方法名和方法參數可以唯一定位到一個方法)
    39                                     Method method = service.getClass().getMethod(methodName, methodParameterTypes);
    40                                     if (method == null) {
    41                                         throw new NoSuchMethodException();
    42                                     }
    43                                     //執行方法
    44                                     Object result = method.invoke(service, arguments);
    45                                     System.out.println("Method:" + methodName + ";Arguments:" + arguments + "  invoke!");
    46                                     //獲取socket輸出流
    47                                     ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
    48                                     try {
    49                                         //輸出結果
    50                                         oos.writeObject(result);
    51                                     } finally {
    52                                         oos.close();
    53                                     }
    54                                 } finally {
    55                                     ois.close();
    56                                 }
    57                             } finally {
    58                                 socket.close();
    59                             }
    60                         } catch (Exception e) {
    61                             //記個日志啥的
    62                             e.printStackTrace();
    63                         }
    64                     }
    65                 }).start();
    66             } catch (Exception e) {
    67                 //記個日志啥的
    68                 e.printStackTrace();
    69             }
    70         }
    71     }

    然后是消費的方法

    **
         * 消費服務
         *
         * @param clazz 接口類
         * @param host  發布服務機器的host
         * @param port  發布服務機器的port
         * @return
         */
        public static Object consume(final Class clazz, final String host, final int port) {
            //參數檢查
            if (clazz == null) {
                throw new IllegalArgumentException("The clazz can't be null!");
            }
            if (host == null || host.isEmpty()) {
                throw new IllegalArgumentException("The host can't be null or empty!");
            }
            if (port > 65535) {
                throw new IllegalArgumentException("The host can't greater than 65535!");
            }
            //生成代理,每次調用方法其實是調用遠程的服務
            Object proxy = Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{clazz}, new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] arguments) throws Throwable {
                    //建立socket鏈接
                    Socket socket = new Socket(host, port);
                    try {
                        //獲取輸出流
                        ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
                        try {
                            String methodName = method.getName();
                            Class[] methodParameterTypes = method.getParameterTypes();
                            //輸出要調用的方法名
                            oos.writeUTF(methodName);
                            //輸出要調用的方法參數列表
                            oos.writeObject(methodParameterTypes);
                            //輸出要調用的方法參數
                            oos.writeObject(arguments);
                            ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
                            try {
                                //獲取結果
                                Object result = ois.readObject();
                                //可能返回的對象是異常
                                if (result instanceof Throwable) {
                                    throw (Throwable) result;
                                }
                                return result;
                            } finally {
                                ois.close();
                            }
                        } finally {
                            oos.close();
                        }
                    } finally {
                        socket.close();
                    }
                }
            });
            return proxy;
        }

    一般端口可以雙方約定,而host可以采用configServer的方法解決,也就是開啟一個服務,當啟動一個服務的時候到configServer注冊一下(服務名+host),如果是多臺服務器提供服務,host就是一個list,調用方發起調用的時候首先到configServer根據服務名獲取host列表,然后選一個host發起調用!configServer的優點是可以做到很多控制,比如流量控制,權重控制,調用host列表維護(死掉就剔除,重試機制)等等,這樣調用方不用關心我調用的是哪臺機器,只用關心我調用哪個方法。但也有壞處,一旦configServer掛掉了.......(其實也可以通過MS或調用方本地緩存調用列表解決)。

    一般由調用方提供一個接口包(算是一個雙方的約定),接口類中定義了提供發提供的方法
    如我們發布一個簡單的服務
    1 public interface Girl {
    2     //提供服務
    3     String server(String name);
    4 }

    實現
    1 public class GirlImpl implements Girl{
    2     @Override
    3     public String server(String name) {
    4         return name+"亞美爹";
    5     }
    6 }
    發布服務
    這里你可以寫在一個main方法中,也可以配置一個Spring的bean,并配置init方法,然后在init方法中開啟
    1  Girl beautifulGirl=new GirlImpl();
    2         try {
                    //在本機的1111端口上開啟Girl的服務
    3             Utils.provide(beautifulGirl, 1111);
    4         } catch (Exception e) {
    5             e.printStackTrace();
    6         }
    消費
    1  try {
    2             //從此你就獲得了一個漂亮妹子,她可以給你提供各種服務
    3             Girl beautifulGirl= (Girl)Utils.consume(Girl.class, "127.0.0.1", 3333);
    4             //你可以來一個循環,或者來一個死循環,一直哈哈
    5             beautifulGirl.server("yourName");
    6         } catch (Exception e) {
    7             e.printStackTrace();
    8         }

    總結:
    其實遠程調用也就是獲取服務的一個代理,每當你調用服務的方法事,他都會想服務方傳去方法,方法參數列表,參數,前兩個用于唯一確定一個方法,后一個用于方法調用。
    這里實現的很簡答,當然還有很復雜的,比如Spring的實現,淘寶的HSF等等


    以上為個人理解,如果有錯的地方,歡迎指正。

    posted @ 2012-12-26 19:25 Evan.lee 閱讀(1964) | 評論 (0)編輯 收藏

    僅列出標題  
    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    導航

    統計

    常用鏈接

    留言簿

    隨筆檔案

    搜索

    最新評論

    主站蜘蛛池模板: 亚洲成av人片不卡无码| 亚洲av无码乱码国产精品| 亚洲综合成人婷婷五月网址| 一级毛片免费观看不卡的| 亚洲国产另类久久久精品| 久久这里只精品99re免费| 亚洲国产精品无码成人片久久| 人妻在线日韩免费视频| 亚洲三级电影网站| 成人免费黄色网址| 亚洲欧美日韩一区二区三区在线| 日韩电影免费在线观看视频| 美女视频黄频a免费| 中文字幕久久亚洲一区| 男女一边摸一边做爽的免费视频| 亚洲国产精品一区二区久久hs| 久久久高清日本道免费观看| 亚洲国产模特在线播放| 色吊丝最新永久免费观看网站| 深夜a级毛片免费视频| 亚洲夜夜欢A∨一区二区三区| 日本视频在线观看永久免费| 亚洲视频在线观看地址| 我要看WWW免费看插插视频| 午夜成人无码福利免费视频| 亚洲va久久久噜噜噜久久男同| 免费福利在线播放| 午夜在线亚洲男人午在线| 亚洲三区在线观看无套内射| 91香蕉国产线观看免费全集| 亚洲精品无码av片| 亚洲男人的天堂www| 成人免费视频软件网站| 99在线视频免费观看| 亚洲国产高清美女在线观看| 亚洲国产精品尤物yw在线 | 久久国产精品一区免费下载| 亚洲kkk4444在线观看| 亚洲中文久久精品无码| 四虎国产精品免费久久| 免费萌白酱国产一区二区三区|