Thrift搭建分布式微服务(二)
第二篇 连接池
连接池配置,请前往Thrift搭建分布式微服务(一)
下面要介绍的其实不是单一的连接池,应该说是连接池集合。因为它要管理多个Tcp Socket连接节点,每个服务节点都有设置了自己的最大激活连接数、最大空闲连接数、最小空闲连接数、等待连接时间。
internal class ServiceTransportPool
{
public ServiceConfig ServiceConfig { get; set; } public ConcurrentStack<TTransport> TransportPool { get; set; } public AutoResetEvent ResetEvent { get; set; } public int ActivedTransportCount { get; set; }
internal object sync_obeject = new object();
}
一个ServiceTransportPool类对应一个服务配置,一个服务配置对应一个服务节点。连接池集合应具有下列成员:
internal class ThriftFactory
{
private static volatile List<ServiceTransportPool> transport_pools; private static object sync_obj = new object(); private static IThriftFactoryMonitor monitor = new ThriftFactoryMonitor();
}
transport_pools实现了对服务节点的管理,monitor 用来监控连接池的状态,如上一篇所讲,等待连接超时怎么通知连接池管理者,就用monitor来实现。这里monitor有个默认的实现,后面再讲。
初始化连接池集合:
static ThriftFactory()
{
if (transport_pools == null || transport_pools.Count == )
{
lock (sync_obj)
{
if (transport_pools == null || transport_pools.Count == )
{
var services = ConfigHelper.GetServiceConfigs();
transport_pools = new List<ServiceTransportPool>(services.Count);
foreach (var service in services)
{
ServiceTransportPool stp = new ServiceTransportPool()
{
ServiceConfig = service,
TransportPool = new ConcurrentStack<TTransport>(),
ResetEvent = new AutoResetEvent(false),
ActivedTransportCount =
};
transport_pools.Add(stp);
}
}
}
}
}
如何向连接池借出一个Socket连接:
public static TTransport BorrowInstance(string serviceName)
{
var transpool = (from tp in transport_pools where tp.ServiceConfig.Name.ToUpper() == serviceName.ToUpper() select tp).FirstOrDefault();
if (transpool == null)
{
throw new ThriftException(string.Format("There Is No Service Named \"{0}\"", serviceName));
} TTransport transport;
lock (transpool.sync_obeject)
{
if (transpool.TransportPool.Count() == )
{
if (transpool.ActivedTransportCount == transpool.ServiceConfig.MaxActive)
{
bool result = transpool.ResetEvent.WaitOne(transpool.ServiceConfig.WaitingTimeout);
if (!result)
{
monitor.TimeoutNotify(transpool.ServiceConfig.Name, transpool.ServiceConfig.WaitingTimeout);
}
}
else
{
transpool.TransportPool.Push(CreateTransport(transpool.ServiceConfig));
}
} if (!transpool.TransportPool.TryPop(out transport))
{
throw new ThriftException("Connection Pool Exception");
} transpool.ActivedTransportCount++; if (transpool.TransportPool.Count() < transpool.ServiceConfig.MinIdle && transpool.ActivedTransportCount < transpool.ServiceConfig.MaxActive)
{
transpool.TransportPool.Push(CreateTransport(transpool.ServiceConfig));
}
}
if (!transport.IsOpen)
{
transport.Open();
}
Monitor();
return transport;
}
当实际激活的连接数达到服务节点配置的最大激活连接数,获取Socket连接的请求就将处于等待状态,超过等待时间设置,使用监视器方法monitor.TimeoutNotify()去通知管理者。连接池空闲的连接小于最小空闲连接数设置,每次请求连接都会建立一个新的连接放到池子里。
归还连接:
public static void ReturnInstance(string serviceName,TTransport transport)
{
var transpool = (from tp in transport_pools where tp.ServiceConfig.Name.ToUpper() == serviceName.ToUpper() select tp).FirstOrDefault();
if (transpool == null)
{
throw new ThriftException("Connection Pool Exception");
}
if (transpool.TransportPool.Count() == transpool.ServiceConfig.MaxIdle)
{
transport.Flush();
if (transport.IsOpen)
{
transport.Close();
}
transport.Dispose();
}
else
{
lock (transpool.sync_obeject)
{
if (transport.IsOpen)
{
transport.Close();
}
transpool.TransportPool.Push(transport);
transpool.ActivedTransportCount--;
transpool.ResetEvent.Set();
}
}
Monitor();
}
当连接池最大空闲连接达到了服务节点设置的最大空闲连接数时,归还的连接将被销毁。借出连接和归还连接两段代码里都有一个Monitor()方法,此方法监控连接池连接的使用情况:
/// <summary>
/// 监控连接池状态
/// </summary>
private static void Monitor()
{
List<Tuple<string, int, int>> tuples = new List<Tuple<string, int, int>>(transport_pools.Count);
foreach(var transpool in transport_pools)
{
Tuple<string, int, int> tuple = new Tuple<string, int, int>(transpool.ServiceConfig.Name, transpool.TransportPool.Count(), transpool.ActivedTransportCount);
tuples.Add(tuple);
}
monitor.Monitor(tuples);
}
此方法将每个服务连接池的空闲连接数、和激活的连接数传给前面提到的监视器。在连接等待超时和拿到连接池的运行参数时,最终进行什么动作还是由开发者去实现的。继承下面的接口,开发者可以自定义监视器。
public interface IThriftFactoryMonitor
{
/// <summary>
/// 监控连接池运行状态
/// </summary>
/// <param name="tuple">元组集合,第一个元素表示服务名称、第二个元素表示空闲连接数量、第三个元素表示激活连接数量</param>
void Monitor(List<Tuple<string,int,int>> tuples); /// <summary>
/// 等待连接超时
/// </summary>
void TimeoutNotify(string serviceName,int timeOut);
}
默认的监视器只是将连接池的运行状态记录到控制台:
/// <summary>
/// 默认连接池状态监控类
/// </summary>
public class ThriftFactoryMonitor : IThriftFactoryMonitor
{
public virtual void Monitor(List<Tuple<string, int, int>> tuples)
{
foreach (var t in tuples)
{
Console.WriteLine(string.Format("{0}连接池,空闲连接数量:{1},激活连接数量:{2}", t.Item1, t.Item2, t.Item3));
}
} public virtual void TimeoutNotify(string serviceName, int timeOut)
{
Console.WriteLine(string.Format("{0}连接池等待连接超时{1}", serviceName, timeOut));
}
}
开发者自己实现的监视器,如何能被连接池使用,其实在一开始的连接池初始化里,还有一段使用反射来初始化开发者定义的监视器的代码。开发者只需在上一篇介绍的Thrift.config里配置MonitorType,其他的就交给框架处理:
static ThriftFactory()
{
......
if(!string.IsNullOrWhiteSpace(ConfigHelper.ThriftConfig.MonitorType))
{
monitor = Invoker.CreateInstance(Type.GetType(ConfigHelper.ThriftConfig.MonitorType)) as IThriftFactoryMonitor;
if (monitor == null)
{
throw new ThriftException(string.Format("There Is No Monitor Implement Which Type Is \"{0}\"", ConfigHelper.ThriftConfig.MonitorType));
}
}
}
通过连接池与服务节点建立了Socket连接,下一篇将介绍客户端如何使用建立的Socket连接与服务端通信。
Thrift微服务代码下载Thrift.Utility
Thrift搭建分布式微服务(二)的更多相关文章
- Thrift搭建分布式微服务1
Thrift搭建分布式微服务 一.Thrift是什么? 关于Thrift的基本介绍,参看张善友的文章Thrift简介. 二.为什么使用微服务? 在公司的高速发展过程中,随着业务的增长,子系统越来越多. ...
- Thrift搭建分布式微服务(一)
一.Thrift是什么? 关于Thrift的基本介绍,参看张善友的文章Thrift简介. 二.为什么使用微服务? 在公司的高速发展过程中,随着业务的增长,子系统越来越多.各系统间又不同程度的在某些逻辑 ...
- Thrift搭建分布式微服务(四)
第一篇 <连接配置> 第二篇 <连接池> 第三篇 <标准通信> 第四篇 快速暴露接口 之前的文章,我们介绍了如何使用连接池管理Thrift节点,以及使用Thri ...
- Thrift搭建分布式微服务(三)
第一篇 <连接配置> 第二篇 <连接池> 第三篇 标准通信 一.TCP的连接是无状态的,怎样知道我的请求被服务端接受并且正确执行了呢? 我的解决方案是使用自己定义的标准输入输出 ...
- Kite: 一个分布式微服务框架(翻译)
原文链接:https://blog.gopheracademy.com/birthday-bash-2014/kite-microservice-library/ 此为中文翻译 用GO语言来编写web ...
- Dapeng框架-开源高性能分布式微服务框架
我们公司性质是新零售,公司也有专门的框架组.这群大牛自己开发了一整套分布式微服务框架.我们也在使用这套框架,有很多心得体会. 该框架既Dapeng也!开源github地址:https://github ...
- Surging 分布式微服务框架使用入门
原文:Surging 分布式微服务框架使用入门 前言 本文非 Surging 官方教程,只是自己学习的总结.如有哪里不对,还望指正. 我对 surging 的看法 我目前所在的公司采用架构就是类似与S ...
- [转载]Surging 分布式微服务框架使用入门
前言 本文非 Surging 官方教程,只是自己学习的总结.如有哪里不对,还望指正. 我对 surging 的看法 我目前所在的公司采用架构就是类似与Surging的RPC框架,在.NET 4.0框架 ...
- 基于docker 如何部署surging分布式微服务引擎
1.前言 转眼间surging 开源已经有1年了,经过1年的打磨,surging已从最初在window 部署的分布式微服务框架,到现在的可以在docker部署利用rancher 进行服务编排的分布式微 ...
随机推荐
- 【体系结构】Oracle参数介绍
[体系结构]Oracle参数介绍 1 BLOG文档结构图 2 前言部分 2.1 导读和注意事项 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知识,~O(∩_∩ ...
- Greenplum 4.3 For Centos 6.5 安装指南
1.greenplum数据库安装前期准备工作 1.1 安装Linux l 内存:最小1GB,推荐2GB或以上. l 交换空间: 内存大小是1-2GB时,交换空间是内存的1.5倍,内存大小2-16G ...
- 关于Redis持久化
Redis有两种持久化的方式:快照(RDB文件)和追加式文件(AOF文件) RDB持久化方式是在一个特定的间隔保存某个时间点的一个数据快照. AOF(Append only file)持久化方式则会记 ...
- SQL 报错信息整理及解决方案(持续更新)
整理一下自己遇见过的 SQL 各种报错信息及相应解决方法,方便以后查阅,主要平台为 Oracle: ORA-01461: 仅能绑定要插入 LONG 列的 LONG 值: 原因:插入操作时,数据大于字段 ...
- Java异常处理和设计【转】
Java异常处理和设计 在程序设计中,进行异常处理是非常关键和重要的一部分.一个程序的异常处理框架的好坏直接影响到整个项目的代码质量以及后期维护成本和难度.试想一下,如果一个项目从头到尾没有考虑过异常 ...
- IP工具类-自己动手做个ip解析器
IP工具类-自己动手做个ip解析器 一.资料准备 导入依赖包:
- 《TCP/IP详解 卷一》读书笔记-----第三章 IP
1.Network byte order:数据在网络中的传输是按照大端模式来的,即如果需要传递一个四个字节的int变量,先传递最高的字节,然后依次类推.因此无论主机存储数据用的是大端模式还是小端模式, ...
- 【MVC 4】8.SportsSore:管理
作者:[美]Adam Freeman 来源:<精通ASP.NET MVC 4> 本文将继续构建 SportsStore 应用程序,为网站管理员提供一个管理产品分类的方法.本文将添 ...
- ZBrush中如何才能快速完成脸部雕刻(上)
骨骼,是一门基础艺术,几百年来一直为伟大的艺术大师所研究,它曾经,也将一直是创作现实且可信角色的关键,提高骨骼知识更将大大提高雕刻技能. 查看更多内容请直接前往:http://www.zbrushcn ...
- python中的getattr函数
getattr(object, name[, default]) -> value Get a named attribute from an object; getattr(x, 'y') i ...