利用thrift实现js与C#通讯的例子
2013-04-15 22:57
489 查看
关键字:thrift js javascript C# Csharp webservice
1.为什么要用thrift js C#?
1.1 首先,js 通过 thrift 访问C#,实际上是一种c/s模式。thrift是通信工具,js是客户端,C#是服务端。
1.2 使用js直接与thrift server通信。让web开发变得更简单。如果使用Web Service,你需要自己去实现C/S两端的序列化与反序列化操作,还需要自行处理异常,降低了开发效率。而thrift则会自动生成两端的操作类,你只需要处理方法内部的逻辑即可。
1.3 js直接与thrift server通信,可以提高性能,并且用C#开发server,开发效率也非常高。(那些web service弱爆了)
1.4 当然,我们不能只看到优点。用这种方法也有比较明显的缺点:如果使用web service,则网页与web service可以封装在一个工程里,部署到IIS上后,可以存在于一个网站内。而使用了thrift后,你还需要手动管理thrift程序。包括:
1.4.1 你需要拥有服务端的绝对控制权,比如,你可以直接登录服务器的操作系统上进行操作。因此,如果你只有一个网页空间,则不适合这种方法。当然,你也可以用web service里绑定thrift,但这样你又需要自己手动进行序列化与反序列操作,而且两次转换让性能更低,有违初衷
1.4.2 给thrift server程序增加自动启动,与监视程序,来完成thrift的崩溃后自动重启。
2.环境
Win7 - VS2012 - .net 4.0 C# 控制台工程(用来承载thrift)
Win7 - VS2012 - .net 4.0 C# Web工程(用来调试js,超方便)
3.步骤(以下步骤,对于小白来说,有些困难。QQ讨论群:23152359 )
3.1 去thrift官方下载thrift库,目前是0.9.0。
3.2 去thrift官方下载编译好的win下的thrift编译器,是一个exe文件。
3.3 写一个数据结构定义文件。我在这里只是用了服务,没有定义自定义数据结构。
data.txt:
3.4 命令行下,用thrift编译器,对它进行编译:
run.bat:
3.5 建立一个名字为CSharpServer的C#控制台工程,.net 4.0的。
3.6 为这个工程,添加现有项目:thrift库目录\thrift-0.9.0\lib\csharp\src\Thrift.csproj,然后引用这个项目。
3.7 把thrift编译出来的UserStorage.cs(在gen-csharp目录里),拖动到解决方案管理器里的CSharpServer项目的根目录下,UserStorage.cs与Program.cs应该在同一级。
3.8 在CSharpServer项目里创建一个UserStorage的处理类UserStorageHandle.cs:(它应该与UserStorage.cs与Program.cs在同一级)
3.9 主程序Program.cs:
3.10 按F5,启动CSharpServer项目。
3.11 新开一个VS2012(内存不够的赶快去买),建立一个叫JsProject的C# .net 4.0 Web空工程。
3.12 去jquery官网下载jquery-1.9.1.js(mini版也行,随便)
3.13 把thrift编译的js文件data_types.js与UserStorage.js,thrift库的js库文件(thrift库目录\thrift-0.9.0\lib\js\thrift.js),以及刚下载的jq文件jquery-1.9.1.js,全部拖动到解决方案资源管理器的JsProject项目的根目录下:
data_types.js \ jquery-1.9.1.js \ thrift.js \ UserStorage.js 应该与Web.config在同一级。
3.14 在根目录下创建一个Test.html文件,Test.html 应该与Web.config在同一级:
Test.html:
3.15 给Test.html的 “ var debugPosation = 0; ” 这一行,下断点,然后F5,就可以看到效果了。
4.注意两个问题
4.1 由于web服务一般都是80端口,如果thrift端口与其不同,js在访问时会遇到跨域问题,js报错e.message = "拒绝访问"。但是,对于传说中的windows server,完全没有问题,因为,windows server支持.net的传说中的端口复用功能!因此,假设部署后,网站的iis的url为:http://www.baidu.com/XXX,则你最好给thrift server留一个二级域名,比如 http://www.baidu.com/ThriftService ,把这个留给thrift。最后,直接把thrift server的监听url,设置为这个 http://www.baidu.com/ThriftService 就OK了,不会有端口冲突问题,因为win Server + .net 支持tcp端口复用!!!! 如果你的网站的url还带有端口,比如 http://www.baidu.com:9999/XXX,或者IP形式:http://11.2.33.44:9999/XXX,则thriftservice也需要与它的端口相同,比如:http://www.baidu:9999/ThriftService 或 http://11.2.33.44:9999/ThriftService 。问,网站端口与thriftserver端口并不是80,而是9999,有没有问题?答:木有问题,端口复用功能依然会发挥作用。不过,端口复用技术,是通过让IIS和ThriftServer,把端口监听的工作,都交给System.exe去做,所有如果要做防火墙,要注意一下。防火墙参见这个帖子:/article/6303075.html
4.2 网址的最后一个斜杠问题。js访问thrift service,网址最后一个字符,是不带斜杠的。比如http://www.baidu.com/XXX/,这个就是错误的,因为最后一个是斜杠。应该去掉最后一个斜杠,更正为: http://www.baidu.com/XXX 。而ThriftServer的监听网址,则最后一个斜杠是不能省去的。坑爹吧?当然了,这个问题可能会因为日后的补丁被修正,所以大家自己留意一下。
5.为什么不能使用js + thrift server方案?
看到这里傻眼了吧?上面白忙活大半天,但最后居然发现这个方案有问题?是的。
5.1 Thrift的定义,仅仅是一个通信工具,它不是能7*24运行的类似于iis这种服务提供程序。相对于wcf来说,thrift简单,所以高效。但正是因为它简单,所以它缺少很多在复杂网络环境下充当服务端的功能。在实际使用中,如果把它当成webService Server,则经常出问题。而且很多问题是try catch也抓不住,直接导致宿主程序崩溃的。所以,如果希望构建一个稳定的webService server,还是使用wcf之类的稳定方案为妙。
不过,这并不是说thrift就不行。thrift可以在系统内部来进行数据传输,但绝对不能放在外部。
5.2 js + thrift不支持异步调用!原因是,js只有以ajax方式进行远程服务调用才具有异步功能,但thrift封装的远程服务调用,不是ajax方式的。
其他更多问题详见 http://www.cnblogs.com/xxxteam/archive/2013/04/24/3040839.html
1.为什么要用thrift js C#?
1.1 首先,js 通过 thrift 访问C#,实际上是一种c/s模式。thrift是通信工具,js是客户端,C#是服务端。
1.2 使用js直接与thrift server通信。让web开发变得更简单。如果使用Web Service,你需要自己去实现C/S两端的序列化与反序列化操作,还需要自行处理异常,降低了开发效率。而thrift则会自动生成两端的操作类,你只需要处理方法内部的逻辑即可。
1.3 js直接与thrift server通信,可以提高性能,并且用C#开发server,开发效率也非常高。(那些web service弱爆了)
1.4 当然,我们不能只看到优点。用这种方法也有比较明显的缺点:如果使用web service,则网页与web service可以封装在一个工程里,部署到IIS上后,可以存在于一个网站内。而使用了thrift后,你还需要手动管理thrift程序。包括:
1.4.1 你需要拥有服务端的绝对控制权,比如,你可以直接登录服务器的操作系统上进行操作。因此,如果你只有一个网页空间,则不适合这种方法。当然,你也可以用web service里绑定thrift,但这样你又需要自己手动进行序列化与反序列操作,而且两次转换让性能更低,有违初衷
1.4.2 给thrift server程序增加自动启动,与监视程序,来完成thrift的崩溃后自动重启。
2.环境
Win7 - VS2012 - .net 4.0 C# 控制台工程(用来承载thrift)
Win7 - VS2012 - .net 4.0 C# Web工程(用来调试js,超方便)
3.步骤(以下步骤,对于小白来说,有些困难。QQ讨论群:23152359 )
3.1 去thrift官方下载thrift库,目前是0.9.0。
3.2 去thrift官方下载编译好的win下的thrift编译器,是一个exe文件。
3.3 写一个数据结构定义文件。我在这里只是用了服务,没有定义自定义数据结构。
data.txt:
service UserStorage { i32 Sum( 1: i32 arg_number1, 2: i32 arg_number2), string GetString() }
3.4 命令行下,用thrift编译器,对它进行编译:
run.bat:
thrift-0.9.0.exe --gen csharp data.txt thrift-0.9.0.exe --gen js data.txt pause
3.5 建立一个名字为CSharpServer的C#控制台工程,.net 4.0的。
3.6 为这个工程,添加现有项目:thrift库目录\thrift-0.9.0\lib\csharp\src\Thrift.csproj,然后引用这个项目。
3.7 把thrift编译出来的UserStorage.cs(在gen-csharp目录里),拖动到解决方案管理器里的CSharpServer项目的根目录下,UserStorage.cs与Program.cs应该在同一级。
3.8 在CSharpServer项目里创建一个UserStorage的处理类UserStorageHandle.cs:(它应该与UserStorage.cs与Program.cs在同一级)
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace CSharpServer { public class UserStorageHandle : UserStorage.Iface { public UserStorageHandle() { ; } public int Sum(int arg_number1, int arg_number2) { int result = arg_number1 + arg_number2; Console.WriteLine(DateTime.Now.ToString() + " 收到请求:Sum,参数:arg_number1 = " + arg_number1.ToString() + ",arg_number2 = " + arg_number2.ToString() + ",返回:result = " + result.ToString()); return result; } private static int Counter = 0; public string GetString() { int currentCounter = System.Threading.Interlocked.Increment(ref UserStorageHandle.Counter); Console.WriteLine(DateTime.Now.ToString() + " 收到请求:GetString,参数:没有,返回:result = \"thrift is OK : " + currentCounter.ToString() + "\""); return "thrift is OK : " + currentCounter.ToString(); } } }
3.9 主程序Program.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Thrift.Transport; using Thrift.Protocol; using Thrift.Server; using System.Net; namespace CSharpServer { class Program { private static HttpListener httpListener = null; private static THttpHandler httpServer = null; static void Main(string[] args) { string serviceUrl = "http://localhost:99/"; try { UserStorageHandle handle = new UserStorageHandle(); UserStorage.Processor processor = new UserStorage.Processor(handle); TProtocolFactory protocolFactory = new TJSONProtocol.Factory(); Program.httpServer = new THttpHandler(processor, protocolFactory); Program.httpListener = new HttpListener(); Program.httpListener.Prefixes.Add(serviceUrl); Program.httpListener.Start(); IAsyncResult result = Program.httpListener.BeginGetContext(new AsyncCallback(WebRequestCallback), null); Console.WriteLine("Thrift 服务成功启动,网址是 " + serviceUrl); } catch (System.Exception ex) { Console.WriteLine("发生错误:" + ex.Message); Console.WriteLine("按回车键退出"); Console.ReadLine(); return; } Console.WriteLine("若需结束程序,请直接关闭窗口,或按回车。"); Console.ReadLine(); } public static void WebRequestCallback(IAsyncResult result) { if (Program.httpListener == null) { Console.WriteLine("发生错误:HttpListener已经被关闭"); Console.WriteLine("按回车键退出"); Console.ReadLine(); return; } HttpListenerContext httpListenerContext = Program.httpListener.EndGetContext(result); Program.httpListener.BeginGetContext(new AsyncCallback(WebRequestCallback), null); Program.httpServer.ProcessRequest(httpListenerContext); } } }
3.10 按F5,启动CSharpServer项目。
3.11 新开一个VS2012(内存不够的赶快去买),建立一个叫JsProject的C# .net 4.0 Web空工程。
3.12 去jquery官网下载jquery-1.9.1.js(mini版也行,随便)
3.13 把thrift编译的js文件data_types.js与UserStorage.js,thrift库的js库文件(thrift库目录\thrift-0.9.0\lib\js\thrift.js),以及刚下载的jq文件jquery-1.9.1.js,全部拖动到解决方案资源管理器的JsProject项目的根目录下:
data_types.js \ jquery-1.9.1.js \ thrift.js \ UserStorage.js 应该与Web.config在同一级。
3.14 在根目录下创建一个Test.html文件,Test.html 应该与Web.config在同一级:
Test.html:
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title></title> <script type="text/javascript" src="jquery-1.9.1.js"></script> <script type="text/javascript" src="data_types.js"></script> <script type="text/javascript" src="thrift.js"></script> <script type="text/javascript" src="UserStorage.js"></script> <script> $(document).ready(function () { var debugPosation = 0; try { var transport = new Thrift.Transport("http://localhost:99"); var protocol = new Thrift.Protocol(transport); var client = new UserStorageClient(protocol); var result_GetString = client.GetString(); var result_Sum = client.Sum(255, 322); } catch (e) { alert("出错鸟:" + e.message); } }); </script> </head> <body> </body> </html>
3.15 给Test.html的 “ var debugPosation = 0; ” 这一行,下断点,然后F5,就可以看到效果了。
4.注意两个问题
4.1 由于web服务一般都是80端口,如果thrift端口与其不同,js在访问时会遇到跨域问题,js报错e.message = "拒绝访问"。但是,对于传说中的windows server,完全没有问题,因为,windows server支持.net的传说中的端口复用功能!因此,假设部署后,网站的iis的url为:http://www.baidu.com/XXX,则你最好给thrift server留一个二级域名,比如 http://www.baidu.com/ThriftService ,把这个留给thrift。最后,直接把thrift server的监听url,设置为这个 http://www.baidu.com/ThriftService 就OK了,不会有端口冲突问题,因为win Server + .net 支持tcp端口复用!!!! 如果你的网站的url还带有端口,比如 http://www.baidu.com:9999/XXX,或者IP形式:http://11.2.33.44:9999/XXX,则thriftservice也需要与它的端口相同,比如:http://www.baidu:9999/ThriftService 或 http://11.2.33.44:9999/ThriftService 。问,网站端口与thriftserver端口并不是80,而是9999,有没有问题?答:木有问题,端口复用功能依然会发挥作用。不过,端口复用技术,是通过让IIS和ThriftServer,把端口监听的工作,都交给System.exe去做,所有如果要做防火墙,要注意一下。防火墙参见这个帖子:/article/6303075.html
4.2 网址的最后一个斜杠问题。js访问thrift service,网址最后一个字符,是不带斜杠的。比如http://www.baidu.com/XXX/,这个就是错误的,因为最后一个是斜杠。应该去掉最后一个斜杠,更正为: http://www.baidu.com/XXX 。而ThriftServer的监听网址,则最后一个斜杠是不能省去的。坑爹吧?当然了,这个问题可能会因为日后的补丁被修正,所以大家自己留意一下。
5.为什么不能使用js + thrift server方案?
看到这里傻眼了吧?上面白忙活大半天,但最后居然发现这个方案有问题?是的。
5.1 Thrift的定义,仅仅是一个通信工具,它不是能7*24运行的类似于iis这种服务提供程序。相对于wcf来说,thrift简单,所以高效。但正是因为它简单,所以它缺少很多在复杂网络环境下充当服务端的功能。在实际使用中,如果把它当成webService Server,则经常出问题。而且很多问题是try catch也抓不住,直接导致宿主程序崩溃的。所以,如果希望构建一个稳定的webService server,还是使用wcf之类的稳定方案为妙。
不过,这并不是说thrift就不行。thrift可以在系统内部来进行数据传输,但绝对不能放在外部。
5.2 js + thrift不支持异步调用!原因是,js只有以ajax方式进行远程服务调用才具有异步功能,但thrift封装的远程服务调用,不是ajax方式的。
其他更多问题详见 http://www.cnblogs.com/xxxteam/archive/2013/04/24/3040839.html
相关文章推荐
- 利用thrift实现js与C#通讯的实例代码
- thrift实现js与C#通讯
- Thrift初探:简单实现C#通讯服务程序
- Thrift 简单实现C#通讯服务程序 (跨语言 MicroServices)
- Thrift实现C#通讯服务程序
- 利用OTP.NET框架来实现C#与Erlang Node之间的通讯
- 利用apache Thrift 进行 node.js和 C++进程间通讯
- C#.NET利用ContextBoundObject和Attribute实现AOP技术--AOP事务实现例子
- C#动态执行类库中的函数:利用反射实现(js)Eval,asp(Execute)功能
- Thrift初探:简单实现C#通讯服务程序
- 利用sender的Parent获取GridView中的当前行 不用AJAX实现前台JS调用后台C#方法(小技巧) AjaxControlToolkit的CalendarExtender的本地化
- Thrift初探:简单实现C#通讯服务程序
- C#利用js脚本实现配置的文本表达式计算
- Thrift初探:简单实现C#通讯服务程序
- 利用自定义事件实现不同窗体间的通讯 -- C#篇
- C#利用反射实现(js)Eval,asp(Execute)功能 动态执行类库中的函数
- 利用Socket来实现Erlang与C#之间的通讯
- 利用autocomplete.js实现仿百度搜索效果(ajax动态获取后端[C#]数据)
- VS C# .NET WebBrowser控件 利用插入JS代码,实现控制弹出IE窗口