Thrift搭建分布式微服务(四)

      第一篇 《连接配置》

    第二篇 《连接池》

    第三篇 《标准通信》

    

第四篇 快速暴露接口

    之前的文章,我们介绍了如何使用连接池管理Thrift节点,以及使用Thrift搭建微服务用到的标准输入输出。这一篇,我将介绍如何快速暴露服务接口,并对服务端进行错误处理。

    从代码图上看,开发者在使用Thrift.Utility搭建微服务时,两个类围绕着标准输入输出,是最常用的两个类,ThriftClient上一篇已经讲过,用于客户端,与服务端建立连接,并访问服务端接口,返回值。ThriftService用于服务端,用来暴露服务接口,我们看一下ThriftService.cs:    

 1     public abstract class ThriftService
 2     {
 3         protected virtual string Excute<Q>(StandRequest<Q> request, Func<StandRequest<Q>, string> func)
 4         {
 5             if (request.IsValid())
 6             {
 7                 try
 8                 {
 9                     string result = string.Empty;
10                     if (func != null)
11                     {
12                         result = func(request);
13                     }
14                     StandResponse<string> response = new StandResponse<string>
15                     {
16                         Code = "0",
17                         Desc = "SUCCESS",
18                         Data = result
19                     };
20                     return SerializeHelper.JsonSerialize2(response);
21                 }
22                 catch (Exception ex)
23                 {
24                     CatchException(ex);
25                     StandResponse<string> response = new StandResponse<string>
26                     {
27                         Code = "-2",
28                         Desc = "服务端异常",
29                         Data = string.Empty
30                     };
31                     return SerializeHelper.JsonSerialize2(response);
32                 }
33             }
34             StandResponse<string> res = new StandResponse<string>
35             {
36                 Code = "-1",
37                 Desc = "请求数据异常",
38                 Data = string.Empty
39             };
40             return SerializeHelper.JsonSerialize2(res);
41         }
42 
43         /// <summary>
44         /// 异常处理
45         /// </summary>
46         /// <param name="ex"></param>
47         protected abstract void CatchException(Exception ex);
48     }

这个类做了两件事,第一件事就是提供了供服务端暴露接口时使用的方法Excute(StandRequest<Q> request, Func<StandRequest<Q>, string> func),只需将得到的请求参数反序列化成StandRequest<Q>,传入Excute,Excute将返回序列化好的响应。第二件事就是,在Excute里提供了错误处理机制,避免开发者进行重复的劳动,开发者只需要重写CatchException方法。

    先看一下传统的调用一个本地的方法是怎么做的:

1 List<BrandInfo> brans = ProductService.GetBrandByVendorSysNo(32);

再看看用Thrift.Utility如何调用远端的服务:

1 using (var tc = new ThriftClient<ProductService.Client>("ProductService"))
2 {
3     List<BrandInfo> brands = tc.Invoke<int, List<BrandInfo>>("GetBrandByVendorSysNo", 32);
4 }

很简洁吧,如何做到的呢?

 1     public class ProductServiceImpl :ThriftService, ProductService.Iface
 2     {
 3         public string GetBrandByVendorSysNo(string request)
 4         {
 5             var req = SerializationUtility.JsonDeserialize2<StandRequest<int>>(request);
 6             return Excute(req, (arg) =>
 7             {
 8                 //调用Service,这是没有使用Thrift之前的方法,通过string GetBrandByVendorSysNo(string request)将其暴露给客户端调用,就这4、5行代码就可以暴露一个服务接口。                   
 9                 List<BrandInfo> brans = ProductService.GetBrandByVendorSysNo(req.Data);
10                 return SerializationUtility.JsonSerialize2(brans);
11             });
12         }
14 15 protected override void CatchException(Exception ex) //开发者自己实现服务端错误处理 16 { 17 if (ex is BusinessException) 18 { 19 20 } 21 else 22 { 23 24 } 25 } 26 }

使用本框架,暴露服务端接口就是这么简单。再看看客户端的配置:

1 <?xml version="1.0" encoding="utf-8" ?>
2 <ThriftConfig>
3   <MonitorType>Demo.RPCClient.ConnectionPoolMonitor,Demo.RPCClient</MonitorType>
4   <ServiceArray>
5     <Service Name="ProductService" IP="127.0.0.1" Port="7911" MaxActive="100" MaxIdle="20" MinIdle="10" WaitingTimeout="1000"/>
6     <Service Name="SOService" IP="127.0.0.1" Port="7912" MaxActive="100" MaxIdle="20" MinIdle="10" WaitingTimeout="1000"/>
7   </ServiceArray>
8 </ThriftConfig>

客户端自定义模拟器示例:

 1     public class ConnectionPoolMonitor:IThriftFactoryMonitor
 2     {
 3         public void Monitor(List<Tuple<string, int, int>> tuples)
 4         {
 5             foreach (var t in tuples)
 6             {
 7                 Console.WriteLine(string.Format("自定义{0}连接池,空闲连接数量:{1},激活连接数量:{2}", t.Item1, t.Item2, t.Item3));
 8             }
 9         }
10 
11         public void TimeoutNotify(string serviceName, int timeOut)
12         {
13             Console.WriteLine(string.Format("自定义{0}连接池等待连接超时{1}", serviceName, timeOut));
14         }
15     }

    Demo的代码没有提供给大家,感兴趣的可以照着示例自己写一个。

    到此整个系列就完结了,之所以写这个系列的文章,是希望和园友们进行交流讨论,如果代码中有什么缺点或没考虑到的地方,还希望园友们能提出来,加以改善,让这个框架更完美。

Thrift微服务代码下载Thrift.Utility

posted @ 2016-04-25 19:29  Scott Lewis  阅读(2157)  评论(1编辑  收藏  举报