自行实现 dotnet core rpc

前言

小李:“胖子,上头叫你对接本人的数目好了未曾?”

胖子:“这是你的事,你都不提供数据源,笔者咋接?”

小李:“你想要什么样的数据源?”

胖子:“作者想要一个调用简单题的!”

小李:“笔者那几个数据源是在linux平台使用docker封装公布的,webapi的怎么?”

胖子:“也行,那项目工期快用完了,你得提供api封装sdk,其他我那边对品质有须要的!”

小李:“webapi多好,基于json各种平台都能联网,质量还不易的!”

胖子:“作者只关切自个儿的作业,不是自家的业务代码,多一行笔者都不想码,不然没定时完毕算你的!其它用webapi到时候必要量第一次全国代表大会,到时候端口用完了,连接不了那锅也得你背!”

小李:“我@##¥%*#¥@#&##@……”

直面胖子这一个理由,小李心里面尽管三万只草泥马在跑马,可是项目只怕要成功是不?其余胖子说的也客观!小李作为二个在C#下侵淫多年老手,不慢想出八个主意——rpc!首先当然是选wcf,这几个巨硬的商号级产品在快捷支付上除了配备上坑爹了有个别,针对顾客端的过渡真的极度快。小李留心一商量wcf
service 发掘日前在linux下玩不了,心里面又是了一阵@##¥%*#¥@#&##@……

胖子:“小李纠结啥,要不就弄个三方的搞一下算了,即使出事了,你恐怕都曾经离任了,怕啥……”

瞧着胖子一脸猥琐的表情,小李那是二个气呀,就怪自已日常牛逼吹上天,那时候怎么好怂呢,一咬牙:“你放心,误不了你的事!”。小李一边回复,心里面初阶妄想着自行达成多少个成效简易,质量高效,使用轻巧的rpc了。

  上边小李与胖子的景色,在支付的时候也是卓绝案例,回到正题来:本身认为rpc首即便:调用方法及参数连串化、socket传输、调用方法及参数反系列化、映射到地头并利用与央浼同样流程回复客户端的一套方案。当中关键点轻易深入分析器重有:系列化与反类别化、高品质tcp、远程方法反转、顾客端代码生成多少个地点;tcp照旧选用iocp好了,别的接着一一深入分析。

RPC实现原理(HSF、dubbo) 从头开头(一),hsfdubbo

前言

 

阔别了非常久腾讯网,尽管看了在此以前写的许多事物感到好天真,可是依然感觉应该把一部分和好认为可行的事物和豪门享受。废话十分的少说,今后始于走入正题。

前边的四年专门的学业经历,呆过了一部分大商家,每种在大公司呆过的人应当清楚,在多少个重型应用中穿梭的加码业务和效果与利益,还会有基于质量的思量,使得许多基础服务必须进行模块化,进而让各子系统方便使用并不是各种系统再次再落到实处一套,也足以使也许成为瓶颈的根基意义能够独自实行扩充,例如(以电商系统举个例子)客户音讯保管、交易管理骨干、商品质量管理理理基本等等。
 在rpc前行中期,服务开展模块块现在,各样子系统、模块落成的本领五光十色,如:hessian、WebService、Socket、http等进行相互调用,各类子系统里头的交互方式和艺术不统一,使得各系统间很难很好的三结合。並且这一个主意还波及超时、加密解密、参数的传递等各个难点。
 在这种场馆下,hsf、dubbo这种高品质rpc中间件出现了。
 将来自己就已最轻巧易行的诀要从头开端讲起在那之中的规律。

本人将分为八个多级为我们实行解剖

一、RPC完结原理(HSF、dubbo) 从头初步(一)

二、RPC达成原理(HSF、dubbo)发表叁个劳动与订阅贰个劳动**(三)**

***三、RPC实现原理(HSF、dubbo)**zookeeper进行集群配置管理(二)*

四、RPC完结原理(HSF、dubbo)netty替换java socket(四)

*五、待补充*

NO.1  TCP传输左券

怎么选用TCP作为传输左券?HTTP在TCP的上一层,位于应用层,TCP位于网络层,以越往底层越快的规律,小编就不过多解释为什么选拔tcp作为传输左券了。
那么在品种中大家怎么使用tcp实行调用呢?直接上个例子代码:

socket服务端:

 

import java.net.*;
import java.io.*;

/**
 * socket编程之:简单socket server
 * 
 * @author chengwei.lcw 2016-11-27
 */
public class SocketServer {
    private ServerSocket serverSocket;
    private Socket socket;
    private BufferedReader in;
    private PrintWriter out;

    public SocketServer() {
        try {
            serverSocket = new ServerSocket(9999);
            while (true) {
                // 此处会阻塞,后面会讲到nio的作用 
                socket = serverSocket.accept();
                in = new BufferedReader(new InputStreamReader(
                        socket.getInputStream()));
                out = new PrintWriter(socket.getOutputStream(), true);
                String line = in.readLine();
                // 打印出来看看结果
                System.out.println("line:" + line);

                // 返回给client端,通知我已收到数据
                out.println("you input is :" + line);
                out.close();
                in.close();
                socket.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new SocketServer();
    }
}

 

scoket客户端:

 

import java.io.*;
import java.net.*;

/**
 * socket编程之:简单socket client
 * 
 * @author chengwei.lcw 2016-11-27
 */
public class SocketClient {
    private Socket socket;
    private BufferedReader in;
    private PrintWriter out;

    public SocketClient() {
        try {
            socket = new Socket("127.0.0.1", 9999);
            in = new BufferedReader(new InputStreamReader(
                    socket.getInputStream()));
            out = new PrintWriter(socket.getOutputStream(), true);
            // 向服务端写数据
            BufferedReader line = new BufferedReader(new InputStreamReader(
                    System.in));

            out.println(line.readLine());
            line.close();
            // 打印出来服务端发回来的回执
            System.out.println(in.readLine());

            in.close();
            out.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new SocketClient();
    }
}

先运营server,再起步client,输入参数,回车,两个第二次对话完结。

小结总计:

日前例子中大家运用了正规化io
socket,这里的非常的多时候会堵塞,如accept()、read()时都会卡住。测验的时候可以让客户端睡眠几秒,在那中间运转第3个客商端,那一年第三个客商端未产生前,第四个客商端是被封堵在accept()中的。
 这种状态能够给各种顾客端都独立分配贰个线程,不过这么创建过多的线程,只怕会严重影响服务器的性质。
第三种缓和方案正是使用NIO
非阻塞的通讯形式,jdk1.4自此已经引进了那一个效用,那样能够使得服务器即使开动贰个线程就可以管理全体的客户端socket须求。netty正是依赖NIO的高质量框架,相比较jdk
nio做了过多革新,修复了有个别毛病。  (这里不对netty与jdk
nio做过多废话,那不在我们谈谈原理细节里,假如大家对那上头风乐趣,我会单独写篇小说实行深度批注)

 

NO.2 种类化情势

在真正的项目中,相当多时候大家传的都以协和定义的类。在长途通信中,类的传导大家要求对类举办连串化和反系列化。连串化的点子有三种,如二进制、xml、soap。大家就以用的最多的二进制实行举个例子:

socket服务端:

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * socket编程之:传输对象server
 * 
 * @author chengwei.lcw 2016-11-27
 */
public class SocketObjectSever {

    private ServerSocket serverSocket;
    private ObjectInputStream in;
    private ObjectOutputStream out;

    public SocketObjectSever() {
        try {
            serverSocket = new ServerSocket(9999);

            while (true) {
                // 此处会阻塞,后面会讲到nio的作用
                Socket socket = serverSocket.accept();

                in = new ObjectInputStream(socket.getInputStream());
                out = new ObjectOutputStream(socket.getOutputStream());

                // 接收server端传来的数据,并转为Student
                Student student = (Student) in.readObject();
                // 重写了toString()方法,打印出来看看
                System.out.println("Server: " + student);

                // 返回给client端,通知我已收到数据
                out.writeObject("yes client, I receive");
                out.flush();

            }

        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new SocketObjectSever();
    }

}

 

socket客户端:

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;


/**
 * socket编程之:传输对象client
 * 
 * @author chengwei.lcw 2016-11-27
 */
public class SocketObjectClient {
    private Socket socket;
    private ObjectInputStream in;
    private ObjectOutputStream out;

    public SocketObjectClient() {
        try {
            socket = new Socket("127.0.0.1",9999);
            out = new ObjectOutputStream(socket.getOutputStream());
            in = new ObjectInputStream(socket.getInputStream());

            /*
             * 建一个student对象,用于传输
             */
            Student s = new Student("chengwei.lcw", 28);

            // 把对象写到管道中,client端进行接收
            out.writeObject(s);
            out.flush();

            String receive = (String) in.readObject();
            System.out.println("Client Receive :"+receive);

            in.close();
            out.close();
            socket.close();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new SocketObjectClient();
    }

}

 

另外定义八个要传输的类:

import java.io.Serializable;

/**
 * socket编程之:要进行传输的类,需要继承Serializable接口
 * 
 * @author chengwei.lcw 2016-11-27
 * 
 */
public class Student implements Serializable {

    private static final long serialVersionUID = 1L;
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String toString() {
        return "name=" + this.name + ", age=" + this.age; 
    }
}

依然先运行server,再起步client,server端调节台出口:

Server: name=chengwei.lcw, age=28

如此那般甘休,咱们的socket能够传输对象了。

此间我们选择的体系化方式为java直接开展类别化,而hessian类别化比Java系列化高效相当多,生成的字节流也要短非常多,因为hessian在类别化时会把字节流举办削减。在后头的晋级换代版中自己会接纳hessian体系化的法子开展体系化。

 

协作社里还应该有事,而且自个儿不精晓这一个是否各位朋友想见见的剧情,忙完明日作者会继续拓宽增加补充。
何地有讲的窘迫的企盼我们来更正。

 

从头初叶(一),hsfdubbo 前言
阔别了比较久今日头条,即便看了从前写的广大事物感到好天真,可是如故感到应该把一…

类别化与反体系化

  系列化与反种类化这些选二进制平时比json的好,ms版的BinaryFormatter
通用性强,不过他的天性、model的号子写法等估摸又要被喷了;找到Expression连串化,结果或然走的好像于soap
xml这一套,想想算了:本地点法调用都以微秒级的,io都以纳秒级其余,socket的三遍就传这么传这么大学一年级堆,就算局域网也伤不起呀,想轻量化提高质量都难,自行完成三个简易的好了。

  1 /****************************************************************************
  2 *Copyright (c) 2018 Microsoft All Rights Reserved.
  3 *CLR版本: 4.0.30319.42000
  4 *机器名称:WENLI-PC
  5 *公司名称:Microsoft
  6 *命名空间:SAEA.RPC.Serialize
  7 *文件名: SerializeUtil
  8 *版本号: V1.0.0.0
  9 *唯一标识:9e919430-465d-49a3-91be-b36ac682e283
 10 *当前的用户域:WENLI-PC
 11 *创建人: yswenli
 12 *电子邮箱:wenguoli_520@qq.com
 13 *创建时间:2018/5/22 13:17:36
 14 *描述:
 15 *
 16 *=====================================================================
 17 *修改标记
 18 *修改时间:2018/5/22 13:17:36
 19 *修改人: yswenli
 20 *版本号: V1.0.0.0
 21 *描述:
 22 *
 23 *****************************************************************************/
 24 using SAEA.RPC.Model;
 25 using System;
 26 using System.Collections.Generic;
 27 using System.Text;
 28 
 29 namespace SAEA.RPC.Serialize
 30 {
 31     /// <summary>
 32     /// rpc参数序列化处理
 33     /// </summary>
 34     public class ParamsSerializeUtil
 35     {
 36         /// <summary>
 37         /// len+data
 38         /// </summary>
 39         /// <param name="param"></param>
 40         /// <returns></returns>
 41         public static byte[] Serialize(object param)
 42         {
 43             List<byte> datas = new List<byte>();
 44 
 45             var len = 0;
 46             byte[] data = null;
 47 
 48             if (param == null)
 49             {
 50                 len = 0;
 51             }
 52             else
 53             {
 54                 if (param is string)
 55                 {
 56                     data = Encoding.UTF8.GetBytes((string)param);
 57                 }
 58                 else if (param is byte)
 59                 {
 60                     data = new byte[] { (byte)param };
 61                 }
 62                 else if (param is bool)
 63                 {
 64                     data = BitConverter.GetBytes((bool)param);
 65                 }
 66                 else if (param is short)
 67                 {
 68                     data = BitConverter.GetBytes((short)param);
 69                 }
 70                 else if (param is int)
 71                 {
 72                     data = BitConverter.GetBytes((int)param);
 73                 }
 74                 else if (param is long)
 75                 {
 76                     data = BitConverter.GetBytes((long)param);
 77                 }
 78                 else if (param is float)
 79                 {
 80                     data = BitConverter.GetBytes((float)param);
 81                 }
 82                 else if (param is double)
 83                 {
 84                     data = BitConverter.GetBytes((double)param);
 85                 }
 86                 else if (param is DateTime)
 87                 {
 88                     var str = "wl" + ((DateTime)param).Ticks;
 89                     data = Encoding.UTF8.GetBytes(str);
 90                 }
 91                 else if (param is byte[])
 92                 {
 93                     data = (byte[])param;
 94                 }
 95                 else
 96                 {
 97                     var type = param.GetType();
 98 
 99                     if (type.IsGenericType || type.IsArray)
100                     {
101                         data = SerializeList((System.Collections.IEnumerable)param);
102                     }
103                     else if (type.IsGenericTypeDefinition)
104                     {
105                         data = SerializeDic((System.Collections.IDictionary)param);
106                     }
107                     else if (type.IsClass)
108                     {
109                         var ps = type.GetProperties();
110 
111                         if (ps != null && ps.Length > 0)
112                         {
113                             List<object> clist = new List<object>();
114 
115                             foreach (var p in ps)
116                             {
117                                 clist.Add(p.GetValue(param));
118                             }
119                             data = Serialize(clist.ToArray());
120                         }
121                     }
122                 }
123                 len = data.Length;
124             }
125             datas.AddRange(BitConverter.GetBytes(len));
126             if (len > 0)
127             {
128                 datas.AddRange(data);
129             }
130             return datas.Count == 0 ? null : datas.ToArray();
131         }
132 
133 
134         private static byte[] SerializeList(System.Collections.IEnumerable param)
135         {
136             List<byte> list = new List<byte>();
137 
138             if (param != null)
139             {
140                 List<byte> slist = new List<byte>();
141 
142                 foreach (var item in param)
143                 {
144                     var type = item.GetType();
145 
146                     var ps = type.GetProperties();
147                     if (ps != null && ps.Length > 0)
148                     {
149                         List<object> clist = new List<object>();
150                         foreach (var p in ps)
151                         {
152                             clist.Add(p.GetValue(item));
153                         }
154 
155                         var clen = 0;
156 
157                         var cdata = Serialize(clist.ToArray());
158 
159                         if (cdata != null)
160                         {
161                             clen = cdata.Length;
162                         }
163 
164                         slist.AddRange(BitConverter.GetBytes(clen));
165                         slist.AddRange(cdata);
166                     }
167                 }
168 
169                 var len = 0;
170 
171                 if (slist.Count > 0)
172                 {
173                     len = slist.Count;
174                 }
175                 list.AddRange(BitConverter.GetBytes(len));
176                 list.AddRange(slist.ToArray());
177             }
178             return list.ToArray();
179         }
180 
181         private static byte[] SerializeDic(System.Collections.IDictionary param)
182         {
183             List<byte> list = new List<byte>();
184 
185             if (param != null && param.Count > 0)
186             {
187                 foreach (KeyValuePair item in param)
188                 {
189                     var type = item.GetType();
190                     var ps = type.GetProperties();
191                     if (ps != null && ps.Length > 0)
192                     {
193                         List<object> clist = new List<object>();
194                         foreach (var p in ps)
195                         {
196                             clist.Add(p.GetValue(item));
197                         }
198                         var clen = 0;
199 
200                         var cdata = Serialize(clist.ToArray());
201 
202                         if (cdata != null)
203                         {
204                             clen = cdata.Length;
205                         }
206 
207                         list.AddRange(BitConverter.GetBytes(clen));
208                         list.AddRange(cdata);
209                     }
210                 }
211             }
212             return list.ToArray();
213         }
214 
215         /// <summary>
216         /// len+data
217         /// </summary>
218         /// <param name="params"></param>
219         /// <returns></returns>
220         public static byte[] Serialize(params object[] @params)
221         {
222             List<byte> datas = new List<byte>();
223 
224             if (@params != null)
225             {
226                 foreach (var param in @params)
227                 {
228                     datas.AddRange(Serialize(param));
229                 }
230             }
231 
232             return datas.Count == 0 ? null : datas.ToArray();
233         }
234 
235         /// <summary>
236         /// 反序列化
237         /// </summary>
238         /// <param name="types"></param>
239         /// <param name="datas"></param>
240         /// <returns></returns>
241         public static object[] Deserialize(Type[] types, byte[] datas)
242         {
243             List<object> list = new List<object>();
244 
245             var len = 0;
246 
247             byte[] data = null;
248 
249             int offset = 0;
250 
251             for (int i = 0; i < types.Length; i++)
252             {
253                 list.Add(Deserialize(types[i], datas, ref offset));
254             }
255 
256             return list.ToArray();
257         }
258 
259         /// <summary>
260         /// 反序列化
261         /// </summary>
262         /// <param name="type"></param>
263         /// <param name="datas"></param>
264         /// <param name="offset"></param>
265         /// <returns></returns>
266         public static object Deserialize(Type type, byte[] datas, ref int offset)
267         {
268             dynamic obj = null;
269 
270             var len = 0;
271 
272             byte[] data = null;
273 
274             len = BitConverter.ToInt32(datas, offset);
275             offset += 4;
276             if (len > 0)
277             {
278                 data = new byte[len];
279                 Buffer.BlockCopy(datas, offset, data, 0, len);
280                 offset += len;
281 
282                 if (type == typeof(string))
283                 {
284                     obj = Encoding.UTF8.GetString(data);
285                 }
286                 else if (type == typeof(byte))
287                 {
288                     obj = (data);
289                 }
290                 else if (type == typeof(bool))
291                 {
292                     obj = (BitConverter.ToBoolean(data, 0));
293                 }
294                 else if (type == typeof(short))
295                 {
296                     obj = (BitConverter.ToInt16(data, 0));
297                 }
298                 else if (type == typeof(int))
299                 {
300                     obj = (BitConverter.ToInt32(data, 0));
301                 }
302                 else if (type == typeof(long))
303                 {
304                     obj = (BitConverter.ToInt64(data, 0));
305                 }
306                 else if (type == typeof(float))
307                 {
308                     obj = (BitConverter.ToSingle(data, 0));
309                 }
310                 else if (type == typeof(double))
311                 {
312                     obj = (BitConverter.ToDouble(data, 0));
313                 }
314                 else if (type == typeof(decimal))
315                 {
316                     obj = (BitConverter.ToDouble(data, 0));
317                 }
318                 else if (type == typeof(DateTime))
319                 {
320                     var dstr = Encoding.UTF8.GetString(data);
321                     var ticks = long.Parse(dstr.Substring(2));
322                     obj = (new DateTime(ticks));
323                 }
324                 else if (type == typeof(byte[]))
325                 {
326                     obj = (byte[])data;
327                 }
328                 else if (type.IsGenericType)
329                 {
330                     obj = DeserializeList(type, data);
331                 }
332                 else if (type.IsArray)
333                 {
334                     obj = DeserializeArray(type, data);
335                 }
336                 else if (type.IsGenericTypeDefinition)
337                 {
338                     obj = DeserializeDic(type, data);
339                 }
340                 else if (type.IsClass)
341                 {
342                     var instance = Activator.CreateInstance(type);
343 
344                     var ts = new List<Type>();
345 
346                     var ps = type.GetProperties();
347 
348                     if (ps != null)
349                     {
350                         foreach (var p in ps)
351                         {
352                             ts.Add(p.PropertyType);
353                         }
354                         var vas = Deserialize(ts.ToArray(), data);
355 
356                         for (int j = 0; j < ps.Length; j++)
357                         {
358                             try
359                             {
360                                 if (!ps[j].PropertyType.IsGenericType)
361                                 {
362                                     ps[j].SetValue(instance, Convert.ChangeType(vas[j], ps[j].PropertyType), null);
363                                 }
364                                 else
365                                 {
366                                     Type genericTypeDefinition = ps[j].PropertyType.GetGenericTypeDefinition();
367                                     if (genericTypeDefinition == typeof(Nullable<>))
368                                     {
369                                         ps[j].SetValue(instance, Convert.ChangeType(vas[j], Nullable.GetUnderlyingType(ps[j].PropertyType)), null);
370                                     }
371                                     else
372                                     {
373                                         //List<T>问题
374                                         ps[j].SetValue(instance, Convert.ChangeType(vas[j], ps[j].PropertyType), null);
375                                     }
376                                 }
377                             }
378                             catch (Exception ex)
379                             {
380                                 Console.WriteLine("反序列化不支持的类型:" + ex.Message);
381                             }
382                         }
383                     }
384                     obj = (instance);
385                 }
386                 else
387                 {
388                     throw new RPCPamarsException("ParamsSerializeUtil.Deserialize 未定义的类型:" + type.ToString());
389                 }
390 
391             }
392             return obj;
393         }
394 
395 
396         private static object DeserializeList(Type type, byte[] datas)
397         {
398             List<object> result = new List<object>();
399             var stype = type.GenericTypeArguments[0];
400 
401             var len = 0;
402             var offset = 0;
403             //容器大小
404             len = BitConverter.ToInt32(datas, offset);
405             offset += 4;
406             byte[] cdata = new byte[len];
407             Buffer.BlockCopy(datas, offset, cdata, 0, len);
408             offset += len;
409 
410             //子项内容
411             var slen = 0;
412             var soffset = 0;
413             while (soffset < len)
414             {
415                 slen = BitConverter.ToInt32(cdata, soffset);
416                 var sdata = new byte[slen + 4];
417                 Buffer.BlockCopy(cdata, soffset, sdata, 0, slen + 4);
418                 soffset += slen + 4;
419 
420                 if (slen > 0)
421                 {
422                     int lloffset = 0;
423                     var sobj = Deserialize(stype, sdata, ref lloffset);
424                     if (sobj != null)
425                         result.Add(sobj);
426                 }
427                 else
428                 {
429                     result.Add(null);
430                 }
431             }
432             return result;
433         }
434 
435         private static object DeserializeArray(Type type, byte[] datas)
436         {
437             var obj = DeserializeList(type, datas);
438 
439             if (obj == null) return null;
440 
441             var list = (obj as List<object>);
442 
443             return list.ToArray();
444         }
445 
446         private static object DeserializeDic(Type type, byte[] datas)
447         {
448             dynamic obj = null;
449 
450 
451 
452             return obj;
453         }
454     }
455 }

  完结的长河中,平时结构、类都还相比顺遂,可是数组、List、Dictionary照旧境遇了某些麻烦,近些日子先放着,找到方法加以。真假设传这个,近些日子先用其余连串化成byte[]来做……

长途方法反转

  远程方法反转就是将收取到的数量一定到地点的靶子方法上,若是代码生成、参数使用应用泛型反系列化,理论上是能够进步部分性质的;但是另一方面写服务业务,一边编写定义结构文件、还一边生成服务代码,本地方法都是纳秒级、相对io的快慢来说,假使为了那一点质量进步,在使用的时候推断又是一阵@##¥%*#¥@#&##@……,所以依旧利用反射、拆箱吧。

  1 /****************************************************************************
  2 *Copyright (c) 2018 Microsoft All Rights Reserved.
  3 *CLR版本: 4.0.30319.42000
  4 *机器名称:WENLI-PC
  5 *公司名称:Microsoft
  6 *命名空间:SAEA.RPC.Common
  7 *文件名: RPCInovker
  8 *版本号: V1.0.0.0
  9 *唯一标识:289c03b9-3910-4e15-8072-93243507689c
 10 *当前的用户域:WENLI-PC
 11 *创建人: yswenli
 12 *电子邮箱:wenguoli_520@qq.com
 13 *创建时间:2018/5/17 14:11:30
 14 *描述:
 15 *
 16 *=====================================================================
 17 *修改标记
 18 *修改时间:2018/5/17 14:11:30
 19 *修改人: yswenli
 20 *版本号: V1.0.0.0
 21 *描述:
 22 *
 23 *****************************************************************************/
 24 using SAEA.RPC.Model;
 25 using SAEA.RPC.Net;
 26 using SAEA.RPC.Serialize;
 27 using SAEA.Sockets.Interface;
 28 using System;
 29 using System.Linq;
 30 using System.Reflection;
 31 
 32 namespace SAEA.RPC.Common
 33 {
 34     /// <summary>
 35     /// RPC将远程调用反转到本地服务
 36     /// </summary>
 37     public class RPCReversal
 38     {
 39         static object _locker = new object();
 40         
 41 
 42         /// <summary>
 43         /// 执行方法
 44         /// </summary>
 45         /// <param name="action"></param>
 46         /// <param name="obj"></param>
 47         /// <param name="args"></param>
 48         /// <returns></returns>
 49         private static object ReversalMethod(MethodInfo action, object obj, object[] args)
 50         {
 51             object result = null;
 52             try
 53             {
 54                 var @params = action.GetParameters();
 55 
 56                 if (@params != null && @params.Length > 0)
 57                 {
 58                     result = action.Invoke(obj, args);
 59                 }
 60                 else
 61                 {
 62                     result = action.Invoke(obj, null);
 63                 }
 64             }
 65             catch (Exception ex)
 66             {
 67                 throw new RPCPamarsException($"{obj}/{action.Name},出现异常:{ex.Message}", ex);
 68             }
 69             return result;
 70         }
 71 
 72 
 73         public static object Reversal(IUserToken userToken, string serviceName, string methodName, object[] inputs)
 74         {
 75             lock (_locker)
 76             {
 77                 try
 78                 {
 79                     var serviceInfo = RPCMapping.Get(serviceName, methodName);
 80 
 81                     if (serviceInfo == null)
 82                     {
 83                         throw new RPCNotFundException($"当前请求找不到:{serviceName}/{methodName}", null);
 84                     }
 85 
 86                     var nargs = new object[] { userToken, serviceName, methodName, inputs };
 87 
 88                     if (serviceInfo.FilterAtrrs != null && serviceInfo.FilterAtrrs.Count > 0)
 89                     {
 90                         foreach (var arr in serviceInfo.FilterAtrrs)
 91                         {
 92                             var goOn = (bool)arr.GetType().GetMethod("OnActionExecuting").Invoke(arr, nargs.ToArray());
 93 
 94                             if (!goOn)
 95                             {
 96                                 return new RPCNotFundException("当前逻辑已被拦截!", null);
 97                             }
 98                         }
 99                     }
100 
101                     if (serviceInfo.ActionFilterAtrrs != null && serviceInfo.ActionFilterAtrrs.Count > 0)
102                     {
103                         foreach (var arr in serviceInfo.ActionFilterAtrrs)
104                         {
105                             var goOn = (bool)arr.GetType().GetMethod("OnActionExecuting").Invoke(arr, nargs.ToArray());
106 
107                             if (!goOn)
108                             {
109                                 return new RPCNotFundException("当前逻辑已被拦截!", null);
110                             }
111                         }
112                     }
113 
114                     var result = ReversalMethod(serviceInfo.Mothd, serviceInfo.Instance, inputs);
115 
116                     nargs = new object[] { userToken, serviceName, methodName, inputs, result };
117 
118                     if (serviceInfo.FilterAtrrs != null && serviceInfo.FilterAtrrs.Count > 0)
119                     {
120                         foreach (var arr in serviceInfo.FilterAtrrs)
121                         {
122                             arr.GetType().GetMethod("OnActionExecuted").Invoke(arr, nargs);
123                         }
124                     }
125 
126                     if (serviceInfo.ActionFilterAtrrs != null && serviceInfo.ActionFilterAtrrs.Count > 0)
127                     {
128                         foreach (var arr in serviceInfo.FilterAtrrs)
129                         {
130                             arr.GetType().GetMethod("OnActionExecuted").Invoke(arr, nargs);
131                         }
132                     }
133                     return result;
134                 }
135                 catch (Exception ex)
136                 {
137                     if (ex.Message.Contains("找不到此rpc方法"))
138                     {
139                         return new RPCNotFundException("找不到此rpc方法", ex);
140                     }
141                     else
142                     {
143                         return new RPCNotFundException("找不到此rpc方法", ex);
144                     }
145                 }
146             }
147         }
148 
149         /// <summary>
150         /// 反转到具体的方法上
151         /// </summary>
152         /// <param name="userToken"></param>
153         /// <param name="msg"></param>
154         /// <returns></returns>
155         public static byte[] Reversal(IUserToken userToken, RSocketMsg msg)
156         {
157             byte[] result = null;
158             try
159             {
160                 object[] inputs = null;
161 
162                 if (msg.Data != null)
163                 {
164                     var ptypes = RPCMapping.Get(msg.ServiceName, msg.MethodName).Pamars.Values.ToArray();
165 
166                     inputs = ParamsSerializeUtil.Deserialize(ptypes, msg.Data);
167                 }
168 
169                 var r = Reversal(userToken, msg.ServiceName, msg.MethodName, inputs);
170 
171                 if (r != null)
172                 {
173                     return ParamsSerializeUtil.Serialize(r);
174                 }
175             }
176             catch (Exception ex)
177             {
178                 throw new RPCPamarsException("RPCInovker.Invoke error:" + ex.Message, ex);
179             }
180             return result;
181 
182         }
183     }
184 }

发表评论

电子邮件地址不会被公开。 必填项已用*标注