一、为什么要生成代理
使用RPC的原则就是像使用本地方法一样,让开发者感觉不到任何的不同。所以就必须把服务代理到本地,常见的方式有三种,动态代理接口,静态织入,静态编译。三种方式殊途同归,最终都是构建本地数据结构,然后和远程通信。三种方式各有优缺,具体如下:
优缺点 | 动态代理接口 | 静态织入 | 静态编译 |
---|---|---|---|
优点 | 动态构建类,灵活、适应性强。 | 静态代码生成,自定义类参数自动生成,修改较灵活,调用效率高 | 自定义类参数自动生成,密封性强,安全性高,调用效率高。 |
缺点 | 调用效率较低,自定义类参数须自行构建,实现须IL支持,对调用平台有要求,例如:IOS不允许动态类生成,则不可使用。 | 项目代码管理难统一,强迫症猝死 | 服务一旦有破坏性升级,则必须重新替换dll,灵活性几乎为0。 |
为什么RRQM不支持接口代理调用?
【原因一】
RRQM的rpc支持out和ref参数,在使用代理时,效率不高。
【原因二】
RRQM的rpc需要在参数支持调用上下文,所以无法直接用接口调用。
【原因三】
RRQM的rpc支持单次调用的调用配置(例如超时时间,取消调用,序列化方式等)
【原因四】
引用问题,当在服务接口中,使用了其他的项目的数据结构的话,在接口调用项目上也需要引用该项目。太麻烦。
RRQM源文件代理相比接口代理,有什么优缺点?
源文件代理相比接口代理,几乎没什么缺点。有人会觉得接口代理更整洁、方便?实际上源文件代理只会更整洁、方便。
假设一个场景,你需要开发服务器和客户端,这时,你需要做:
- 先单独定义一个接口项目
- 再定义一个实现项目
- 编译接口项目
- 引用到客户端
上述步骤中,还不包括,接口项目和实现项目需要引入其他引用的情况,也不包括,接口中包含了其他项目的自定义数据结构。如果包含了的话,客户端还需要引入其他项目。
而且,还需要考虑接口项目的编译目标平台和其他编译参数。最难受的是,如果这些工作,是你和同事合作的话,那可能就是出个bug,同事传你一个dll v1.0版本,再有问题,v1.1修复版,等等。
而最要命的,当属程序集数据泄露。设想一下,如果某个同事在写数据库操作的项目时,把连接信息直接放在了代码里(或某个逻辑),本身如果这个项目只在服务器应用,也没有关系,但是因为你懒,你在接口中使用了该项目的一个数据结构,这就使得你不得不把这个项目一同交给调用方的同事,但你对这些毫无察觉。嗷嚎,黑用户一反编译,直接帮你把数据整理了。
但是如果用RRQM的源代码,那上述的可怕问题根本不用考虑。其次,会更整洁,更方便。
假设相同场景,你需要开发服务器和客户端,这时,你需要做:
- 先定义一个服务项目(可以写接口,也能写逻辑,当然也可以分成两个项目)
- 编译项目,然后导出代理源代码。
- 引用到客户端
- 不需要考虑数据结构引用问题,因为代理会转写。
- 不需要考虑编译参数问题,因为客户端拿到的也是源码。
- 不需要再让同事一次次发你dll,只需要,他启动服务,你更新引用就ok。
- 不需要怕程序集数据泄露,因为一切都是转写的,而且只转写应用的、公共的部分。
二、从本地获取代理
在开发过程中,如果服务器和客户端,都是我们自己开发的话(在同一个电脑),就可以使用本地代理生成。
调用下列代码,会将已注册的所有服务,导出代理为字符串。
RpcStore是实例,或者是IRpcParser的属性。
string code=RpcStore.GetProxyCodes("MyNameSpace"));
【示例1】
将代理字符串,写成.cs文件,然后通过链接的形式,将代码添加到客户端项目。
服务器代码,在服务器执行后,会在运行路径下,生成一个WhisperServers.cs的文件。
File.WriteAllText("WhisperServers.cs", m_service.RpcStore.GetProxyCodes("WhisperServers"));
然后打开需要引入的客户端解决方案。选择需要添加代理的项目,依次执行:
右击项目=》添加=》现有项
然后选择服务器生成的.cs文件,选择“添加”的下拉框,选择“添加为连接”。
最后确认文件被正确添加为链接。
这样,每次当服务有更新的时候,只需要启动一下服务器,代理就会自动刷新。
实际上在RpcStore完成服务注册、解析器添加以后,调用GetProxyInfo
,输入代理类型、即可获得代理信息,然后再通过CodeGenerator.ConvertToCode方法,转换为可以直接编译的代码。
此时,你可以复制、或者直接把代理代码写成源代码
(cs文件)。
然后你可以把这个代码引入到客户端。
//或者直接本地导出代理文件。
ServerCellCode[] codes = rpcStore.GetProxyInfo(RpcStore.ProxyAttributeMap.Values.ToArray());
string codeString = CodeGenerator.ConvertToCode("RRQMProxy", codes);
亦或者,为防止篡改生成的代码,不想把代理代码直接投入使用,那可以考虑将代码单独编译成dll,然后将编译的程序集加载到客户端。
三、从远程获取代理
往往,在开发时,服务器和客户端可能是由多个人共同合作完成的,那么这个时候,如果还是以本地的方式获取代理的话,沟通往往会比较麻烦,所以如果能远程获取的话,就会事半功倍。
如果需要远程获取代理,就必须在服务器RpcStore初始化后,调用ShareProxy
分享代理文件,代理分享和实际调用没有任何关系,分享代理的主要作用就是减轻编码人员的负担,所以建议代理端口**不要**
一直打开,仅当客户端代理文件需要更新时打开即可,其他时候可以调用StopShareProxy
停止分享。示例中将以8848端口分享端口。
rpcStore.ShareProxy(new IPHost(8848));
然后需要依靠插件(或程序),直接获取服务,然后将代理源文件植入项目中。具体步骤如下:
a).下载、安装RRQMRPCVSIX插件
【下载】
访问以下任意连接下载插件,然后安装“RRQMRPCVSIX.vsix”即可。
b).下载、运行RRQMRPCTool工具
如果完成了a步骤,则可以忽略本步骤。如果VS版本太低,或不想安装VS插件,那下载 RRQMRPCTool运行工具即可。
解压后直接运行exe程序,界面和c步骤一致。
c).获取代理
【插件使用】
- 安装(下载)完成后,右击项目,即可见“重新引用RPC”菜单条目。
- 点击,填入参数,确定即可。
- 完成后,项目中会多出“RRQMRPC”文件夹,里面的文件既是代理文件。
【RRQMRPCTool.exe使用】
- 运行exe后,需要先选择“目标项目”,选择到客户端项目的
.csproj
文件。 - 然后,填入参数,确定即可。
- 完成后,项目中会多出“RRQMRPC”文件夹,里面的文件既是代理文件。
【目标Url】
http://127.0.0.1:8848/proxy?proxy=all&namespace=RRQMProxy
使用url,浏览器也能获取代理。
1.5 参数说明
参数 | 说明 |
---|---|
目标项目 | 1. 在VS插件中,该内容是自动识别的,不需要,也无法修改。 1. 在exe运行工具是,需要手动选择 .csproj 项目文件。然后会自动识别。 |
存放目录 | 1. 该选项默认为RpcProxy,意味着会在项目路径下,创建一个RpcProxy文件夹,然后存放所有代理文件。 1. 当手动选择其他路径时,最终仍然会以RpcProxy结尾。 |
目标地址 | 目标地址是个http的URL,这也是最重要的远程访问信息。其中支持以下参数: - proxy:代理类型,如果想获取TouchRpc的代理,传入TouchRpc即可,也可以是JsonRpc,多个参数用逗号隔开。输入all时,表示全部代理。 - namespace:命名空间,在VS插件或exe工具中,也是文件名。 |