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 进行服务编排的分布式微 ...
随机推荐
- 读书笔记——OpenGL超级宝典
对于某些函数的理解 glClear和glClearColor glClearColor指定glClear清除特定缓冲区时使用的值. glFlush 让所有已发送的命令尽快的由实际的绘制引擎执行. gl ...
- 《HeadFirst设计模式》读后感——对学习设计模式的一些想法
最近看完了<HeadFirst设计模式>,GOF的<设计模式——可复用面向对象软件的基础>的创建型模式也读完了,经历了从一无所知到茅塞顿开再到充满迷惑的过程. 不得不说< ...
- LESSON THREE
安装redis,并使用ruby进行简单测试. 使用redis客户端ruby测试 安装gem yum install rubygems 安装ruby所需的redis-rb程序库 ...
- 探索 OpenStack 之(11):cinder-api Service 启动过程分析 以及 WSGI / Paste deploy / Router 等介绍
OpenStack 中的每一个提供 REST API Service 的组件,比如 cinder-api,nova-api 等,其实是一个 WSGI App,其主要功能是接受客户端发来的 HTTP R ...
- Solr字段配置错误
在站内搜索Solr Schema设计时,有个FTS_URL字段(之前设计url也会参与检索和打分),因此其配置信息如下: <field name="FTS_URL" type ...
- Codeforces Round #370 (Div. 2)C. Memory and De-Evolution 贪心
地址:http://codeforces.com/problemset/problem/712/C 题目: C. Memory and De-Evolution time limit per test ...
- hdu-5497 Inversion(滑动窗口+树状数组)
题目链接: Inversion Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)T ...
- 关于ZeroMQ的信息与文档
1. 官方文档(英文,很长) http://zguide.zeromq.org/page:all 2. 云风的关于 http://blog.codingnow.com/2011/02/zeromq_m ...
- [原创]CI持续集成系统环境--Gitlab+Gerrit+Jenkins完整对接
近年来,由于开源项目.社区的活跃热度大增,进而引来持续集成(CI)系统的诞生,也越发的听到更多的人在说协同开发.敏捷开发.迭代开发.持续集成和单元测试这些拉风的术语.然而,大都是仅仅听到在说而已,国内 ...
- window.lacation.replace
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8&quo ...