干货---实现思路:RPC Thrift 服务端 注册服务端信息到zookeeper上。客户端从zookeeper获取服务端信息,并实现负载。
经验---注意事项。
如图:
Thrift 坑:
1)Thrift 二次封装的socket 使用 using (TBufferedTransport transport = new TBufferedTransport(GetTSocket())),会被活生生坑死。IDisposable中为实现close()..
所以必须使用如下代码, transport.Close();是重点
using (TBufferedTransport transport = new TBufferedTransport(GetTSocket()))
{
try
{
transport.Open();
TProtocol protocol = new TBinaryProtocol(transport);
CityService.Client client = new CityService.Client(protocol);
return func(client);
//return "";
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
return "fales:" + e.Message;
}
finally
{
transport.Close();
}
}
经验:
1)当zookeeper服务器节点信息如有异常服务时,会自动轮询可用RPC Thrift服务。(指无法连接RPC Thrift服务端,代码层面报错不在此范围内。)
2)客户端实现注意去除异常服务器连接,如下代码实现。
/// <summary>
/// 记录error数
/// </summary>
private int errorCount = 0;
/// <summary>
/// 查询(包含保险公司是否可以投保)
/// </summary>
/// <param name="query"></param>
/// <param name="shortEName"></param>
/// <returns></returns>
public string GetQueryCitiesInfo(string query, string shortEName = null)
{
using (TBufferedTransport transport = new TBufferedTransport(GetTSocket()))
{
try
{
transport.Open();
TProtocol protocol = new TBinaryProtocol(transport);
CityService.Client client = new CityService.Client(protocol);
return client.getQueryCitiesInfo(query, shortEName);
}
catch (Exception e)
{
errorCount++;
Console.WriteLine(e.StackTrace);
if (errorCount >= thriftClient._nodeChildren.Count())
{
Logs.WriteLogInfo("无可用服务!" + e.StackTrace);
errorCount = 0;
return null;
}
return GetQueryCitiesInfo(query, shortEName);
}
finally
{
transport.Close();
}
}
}
}public class ClientShort { /// <summary> /// 负载模式--枚举 /// </summary> internal enum ConnectModel { /// <summary> /// 随机 /// </summary> Random, /// <summary> /// 轮询 /// </summary> Loadbalance, } /// <summary> /// 获取一个唯一类目的thriftClient(YiXin.BaoXian.Toolkits.Common.Thrift.Clien) /// </summary> private static YiXin.BaoXian.Toolkits.Common.Thrift.Client thriftClient = Toolkits.Common.Thrift.Client.GetSingleInstance("YinXin.BaoXian.RegionCityRPC"); /// <summary> /// thrift TBufferedTransport() /// </summary> private static TBufferedTransport _TBufferedTransport; /// <summary> /// 记录error数 /// </summary> private int errorCount = 0; /// <summary> /// thrift tsocket /// </summary> private static TSocket _tsocket = null; /// <summary> /// 短连接-构造函数 /// </summary> public ClientShort() { thriftClient.Init(); } #region 测试可删除代码 /// <summary> /// 委托实验--可删除 /// </summary> /// <param name="func"></param> /// <returns></returns> private string UsingTBufferedTransport(Func<CityService.Client, string> func) { using (TBufferedTransport transport = new TBufferedTransport(GetTSocket())) { try { transport.Open(); TProtocol protocol = new TBinaryProtocol(transport); CityService.Client client = new CityService.Client(protocol); return func(client); //return ""; } catch (Exception e) { Console.WriteLine(e.StackTrace); return "fales:" + e.Message; } finally { transport.Close(); } } } /// <summary> /// 委托实验可删除 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="func"></param> /// <returns></returns> private string UsingTransport<T>(Func<T, string> func) where T : class { using (TBufferedTransport transport = new TBufferedTransport(GetTSocket())) { try { transport.Open(); TProtocol protocol = new TBinaryProtocol(transport); CityService.Client client = new CityService.Client(protocol); T t = client as T; return func(t); //return ""; } catch (Exception e) { Console.WriteLine(e.StackTrace); return "fales:" + e.Message; } finally { transport.Close(); } } } /// <summary> /// 委托实验调用时更简洁,性能会有影响。 /// </summary> /// <param name="shortEName"></param> /// <returns></returns> public string GetCityInfoList1__Test(string shortEName = null) { return UsingTransport<CityService.Client>((client) => { return client.getCityInfoList(shortEName); }); } /// <summary> /// 选择负载模式 /// </summary> /// <param name="model"></param> /// <returns></returns> private TBufferedTransport GetTBufferedTransport(ConnectModel model) { string servers = null; switch (model) { case ConnectModel.Random: servers = thriftClient.Random(); break; case ConnectModel.Loadbalance: servers = thriftClient.Loadbalance(); break; default: break; } Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + servers); TBufferedTransport transport = thriftClient.GetTSocket(servers); try { if (!transport.IsOpen) transport.Open(); } catch (Exception e) { Console.Write("寻找可用客户端"); errorCount++; if (errorCount >= thriftClient._nodeChildren.Count()) { Logs.WriteLogInfo("寻找可用客户端" + e.StackTrace); return null; } return GetTBufferedTransport(ConnectModel.Loadbalance);//轮询 } _TBufferedTransport = transport; errorCount = 0; return _TBufferedTransport; } #endregion /// <summary> /// 查询 /// </summary> /// <param name="query"></param> /// <param name="shortEName"></param> /// <returns></returns> public string GetQueryCitiesInfo(string query, string shortEName = null) { using (TBufferedTransport transport = new TBufferedTransport(GetTSocket())) { try { transport.Open(); TProtocol protocol = new TBinaryProtocol(transport); CityService.Client client = new CityService.Client(protocol); return client.getQueryCitiesInfo(query, shortEName); } catch (Exception e) { errorCount++; Console.WriteLine(e.StackTrace); if (errorCount >= thriftClient._nodeChildren.Count()) { Logs.WriteLogInfo("无可用服务!" + e.StackTrace); errorCount = 0; return null; } return GetQueryCitiesInfo(query, shortEName); } finally { transport.Close(); } } }