Doms开发日记

Doms系统开发过程中的点滴

  博客园 :: 首页 :: 联系 :: 订阅 订阅 :: 管理
  22 Posts :: 0 Stories :: 213 Comments :: 4 Trackbacks
ThumbCached是自己项目中的一个小组件,本着共享交流相互学习的想法,现将它开源出来,希望各位大虾多多指教。这里先贴贴一篇文档,以后再贴组件的应用实例和原理。




ThumbCached
分布式细小二进制文件数据高速缓存及储存系统  (中文名:拇指缓存)
Version: 1.0.1

简介
ThumbCached 是一个简单高效的用于小文件数据的分布式缓存及储存系统,系统适用于缓存及储存数量庞大、个体容量小、读取频繁、需要持久化、非关键性的二进制文件数据,例如网站大量图片的缩略图、用户的自定义头像等。

功能特点
  • 使用两个大文件来储存大量细小文件的数据,可以节约过多的细小文件所浪费的磁盘空间,同时方便数据的转移和备份。
  • 服务程序和应用程序可以分布于不同的服务器,并且多个应用程序可以同时访问同一个服务。
  • 内置数据缓存机制,能提高热点数据的访问速度。
  • 数据的传输使用标准HTTP协议,方便多种程序语言(如ASP.Net,PHP等)使用现有的组件访问服务端。
  • 使用一个key来访问一个文件的信息和数据,不需记住文件的路径和文件名,能简化应用程序的编写。
  • 能在一个服务中同时开启多个储存单元,以便于将不同类型的数据(如用户自定义头像和图片缩略图)分开储存。
  • 服务端使用高效的异步Socket技术。

 
通信协议

ThumbCached使用标准的HTTP协议与应用程序通信,主要的操作有:添加或更新、获取和删除。操作的对象是block(一个block包含有key、最后修改时间、二进制数据内容)。Block的key是一个由字母和数字组成的字符串,例如“item001”,“23A8F001C”。

1、添加或更新block

使用HTTP POST方法,URL格式为:“/key”。

POST方法需要附上block的二进制内容。如果两次POST的Key一样,则会更新这个Key原先的内容。如果需要指定block的时间,可以在URL后附加指定时间,如“/key?20080815123000”,时间格式为“yyyyMMddHHmmss”。方法成功之后,服务端返回HTTP 200 OK状态码和空白内容。

2、获取block

使用HTTP GET方法,URL格式为:“/key”。

如果方法成功,服务端返回指定block的内容,并且在HTTP response header的“Last-Modified”字段中返回该block的最后修改时间。如果指定的block不存在,服务端会返回HTTP 404 NotFound状态码和空白内容。

在获取block时还可以同时指定一个时间值,如“/key?20080815123000”,当block的最后修改时间比指定的时间要新的时候,服务端返回block的内容,否则返回HTTP 304 NotModified状态码和空白内容,并且在HTTP response header的“Last-Modified”字段中返回该block实际上的最后修改时间。使用这个方法可以减少不必要的数据传输量。

3、删除block

使用HTTP GET方法,URL格式为:“/key/remove”.

方法返回HTTP 200 OK状态码和空白内容。
服务端的安装和使用

ThumbCached可以以控制台或者Windows服务的形式运行。先下载ThumbCached的源代码(需要用vs2008编译)或已编译版本,运行“ThumbCached.exe”即可以控制台的形式启动程序。若希望以Windows服务形式运行,则运行“InstallService.bat”批处理进行安装,要卸载此项服务,请运行“UninstallService.bat”。

       服务端通过“ThumbCached.exe.config(控制台)”或“ThumbCachedService.exe.config(Windows服务)”进行配置,当配置内容更改后,需要重启服务才能让新配置生效。

示例的配置文件内容如下:


<thumbCached>
  
<cache>
    
<node id="tcd001">
      
<storeFile infoFilename="d:\tcd_avatar.db" dataFilename="d:\tcd_avatar.dat" />
      
<blockPool bufferPoolSize="128" activeTime="300" />
    
</node>
    
<node id="tcd002">
      
<storeFile infoFilename="d:\tcd_icon.db" dataFilename="d:\tcd_icon.dat" />
      
<blockPool bufferPoolSize="128" activeTime="300" />
    
</node>
    
<node id="tcd003">
      
<storeFile infoFilename="d:\tcd_thumbnail.db" dataFilename="d:\tcd_thumbnail.dat" />
      
<blockPool bufferPoolSize="128" activeTime="300" />
    
</node>
  
</cache>
</thumbCached>
<nbaseHttpd>
  
<binds>
    
<endpoint address="*" port="18500" nodeId="tcd001" />
    
<endpoint address="*" port="18501" nodeId="tcd002" />
    
<endpoint address="*" port="18502" nodeId="tcd003" />
  
</binds>
  
<connection keepAlive="true" timeout="180" connectionsLimit="5000"/>
</nbaseHttpd>


图1


这个示例共创建了3个储存单元。
<thumbCached>段定义储存单元,主要的属性及作用如下:
  • infoFilename和dataFilename:数据文件的路径和文件名,需要注意的是FAT32格式的磁盘分区对单个文件的最大容量只支持到4GB,所以最好把数据文件存放在NTFS的分区;
  • bufferPoolSize:block缓冲池的大小,默认是128MB,根据实际应用情况来设定此属性;
  • activeTime:block缓冲项的最大活动时间,默认是300秒,当一个block缓冲项超过这个时间都没有被访问过时,它就会从缓冲池中被清除;
  • id:每个储存单元需要定义一个不重复的id,用于跟下面的网络监听节点绑定。
 

<nbaseHttpd>段定义服务的网络监听节点,主要的属性及作用如下:
  • address和port:监听的IP地址和端口,如果想监听某个端口的所有IP地址(假如服务器有多张网卡或多个IP的话),可以使用星号(*)代表所有IP地址;
  • nodeId:跟上面的储存单元对应的id;
  • keepAlive:设置服务端与客户端之间的网络连接是否保持长连接,默认值是true;
  • timeout:保持长连接的最大时间长度,默认是180秒;
  • connectionsLimit:服务端最大允许的同时连接数量。

 
使用客户端组件—TCClient

TCClient是ThumbCached客户端的C#的一个实现,可以用于ASP.Net或其他基于.Net框架的应用程序。
 
1、主要的方法及作用

组件主要包含了 ThumbBlock 和 TCClient 两个类。
ThumbBlock :block对应的实体类,含有三个属性:
  • public string Key:block的key
  • public DateTime LastModifyTime:block的最后修改时间
  • public byte[] Data:block的二进制内容

TCClient:有如下几个方法:

  • public void Add(string key, byte[] data)
    添加或更新一个block
  • public void Add(string key, byte[] data, DateTime lastModifyTime)
    添加或更新一个block,并指定block的最后修改时间
  • public ThumbBlock Get(string key)
    获取指定的block
  • public ThumbBlock Get(string serverid, string key, DateTime ifModifySince)
    根据key和指定时间来获取一个block
  • public void Remove(string key)
    删除指定的block

 2、客户端配置文件

使用客户端组件之前,需要在应用程序的配置文件(web.config或app.config)中添加如下示例的段落:


<configSections>
  
<section name="tcclient" type="Doms.TCClient.Configuration.TCClientConfigSection, TCClient, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</configSections>
<tcclient>
  
<serverNodes defaultServer="icon01">
    
<server id="icon01" address="127.0.0.1" port="18500" />
    
<server id="icon02" address="127.0.0.1" port="18501" />
    
<server id="icon03" address="127.0.0.1" port="18502" />
  
</serverNodes>
</tcclient>
图 2

 这个示例演示了一个TCClient同时连接3个ThumbCached储存单元。需要注意的是 <configSections> 标签在原配置文件可能已经存在,不要重复添加。<tcclient>段主要的属性及作用如下:
  • address和port:储存单元的网络服务IP地址和端口。
  • id:为任意的一个字段串,用于代表一个储存单元的网络节点,在程序中将会使用这个id来决定程序访问的储存单元。
 
3、使用示例
首先需要将TCClient.Dll添加至应用程序的引用,如果你获取的是TCClient的源代码,必须先用vs2008将源代码编译成TCClient.Dll。
下面的代码演示了使用TCClient向ThumbCached添加、获取和删除一个block。

private static void Test()
{
    TCClient client 
= new TCClient("icon02");
    
//add block
    byte[] data = new byte[] 12345 };
    DateTime time 
= DateTime.Now;
    client.Add(
"item001", data, time);
    
try
    
{
        
//get block
        ThumbBlock block = client.Get("item001", time.AddDays(1));
        Console.WriteLine(
"block content length:{0}", block.Data.Length);
}

    
catch (BlockNotFoundException)
    
{
        Console.WriteLine(
"block not found");
    }

    
catch (BlockNotModifyException ex)
    
{
        Console.WriteLine(
"block actually last modified time is: {0}", ex.LastModifyTime);
        Console.WriteLine(
"block content does not modify since: {0}", time.AddDays(1));
    }

    
//remove block
    client.Remove("item001");
}


速度测试
       下面使用单一线程的客户端测试ThumbCached每秒钟能完成的请求次数。
       需要说明的是:这里的测试数据是不严谨且不完全的,实际的性能会因为不同的运行环境而有所不同,所以这里的数据仅供参考。

测试的硬件配置如下:
CPU:Athlon64 X2 4200+
RAM:2G DDR2
网络:100M base

测试使用大小为 10KB 的数据作为每次请求的block,共做了如下6种请求:

1、  添加block
2、  更新block
3、  删除block
4、  读取block
5、  在关闭服务端缓存的情况下添加block,模拟缓存用完的情况
6、  在关闭服务端缓存的情况下读取block,模拟缓存用完的情况

 首先在运行ThumbCached程序的本机上测试(即不通过实际网络传输数据),测试结果如下:



tcd_localtest101.png
图 4

说明:纵坐标的数值是每秒完成的请求次数。

然后测试程序通过网络连接ThumbCached服务程序,测试结果如下:


tcd_remotetest101.png
图 5

 
网上资源及意见反馈

ThumbCached及TCClient可以在 http://sourceforge.net/projects/thumbcached  上找到最新的源代码和文档。如果有问题想要讨论,或者有任何意见、建议或者发现bugs,可以访问位于google的讨论组: http://groups.google.com/group/thumbcached



后记:最近在国内访问不了sourceforge.net,所以可以到这里:http://www.domstorage.com/DownloadPage.ashx 下载服务端和客户端的源代码和已编译版本以及文档。

posted on 2008-07-14 16:01 kwanhong young 阅读(1793) 评论(21)  编辑 收藏

Feedback

#1楼  2008-07-14 16:28 Allie      
如果好东西 居然没人支持~~
  回复  引用  查看    

#2楼  2008-07-14 16:39 wingoo      
支持
  回复  引用  查看    

#3楼  2008-07-14 16:39 飄lá┽蕩去      
不错
支持向左走-copyleft
  回复  引用  查看    

#4楼  2008-07-14 16:53 Zigzag      
删除居然这么耗时啊,:-)
  回复  引用  查看    

外国.net开发者很不错,支持!。不像园子里个别高手拿了个MVP整天还折腾小儿科...什么控件使用、讨论一下webform和mvp哪个好...
  回复  引用    

#6楼  2008-07-14 17:11 坏人      
有意义么?太多可替代方案,大概看了下介绍,效能应该也远不如那些替代方案,特别是LZ描述的场景下。
  回复  引用  查看    

#7楼  2008-07-14 20:26 Jeffrey Zhao      
可能值得研究一下

  回复  引用  查看    

#8楼  2008-07-14 20:27 Jeffrey Zhao      
@很不错!!顶!
话说你难道没有看到国内的开源项目?
话说你难道没有看到国外的MVP讨论控件使用webform/mvp?
// 话说现在这个项目是国人的还是国外的似乎还没有搞清楚。
  回复  引用  查看    

#9楼  2008-07-14 22:30 工业酒精      
楼主

1、是否考虑到如果某台服务器宕机了,如何快速使得文件访问不受影响?几台存储服务器之间是否有同步功能?

2、建议参考下MogileFS,和memcached同出一家。
  回复  引用  查看    

#10楼  2008-07-14 23:52 Jeffrey Zhao      
@工业酒精
lz的项目和MogileFS还是差别比较大的,当然我也不知道lz的解决方案如何,没有细看……
  回复  引用  查看    

#11楼 [楼主] 2008-07-15 00:35 kwanhong young      
@1-3楼:谢谢各位的意见。

@4:还没有对这种类型的操作优化,呵呵

@5:园子里的大侠还是很有水平的

@6:这个不是很清楚了,因为这个组件本身没有意思想替代或想跟哪个软件拼一把,它是我自己的一个项目里面的一个小组件,运行了近一年,近5G的数据和日上万的pv,感觉还有点用途,于是就开源咯~~~至于有什么意义,我也不清楚

@7:谢谢!

@工业酒精
你所说的应该是分布式文件系统了,不过Tcd的目标不是做成FS哦 :-),它是一个辅助性的东东,主要用来存一些需要频繁读取的小数据,例如用户头像和缩略图,并且这些数据是可以“再生”的,即原始数据有另外一个比较“可靠”的地方(比如你提到的mogilefs或者NAS)保存着,缓存文件损坏了可以重新生成。
  回复  引用  查看    

#12楼  2008-07-15 00:39 Jeffrey Zhao      
话说“日上万”pv……lz这个数据有没有问题呢?如果没有问题的话,lz的解决方案兴师动众了……
  回复  引用  查看    

#13楼 [楼主] 2008-07-15 00:39 kwanhong young      
@#10:Jeffrey Zhao
是的,tcd不能作为fs来用。

我团队里有另一套叫DomsFS的东东做FS,不过它是商业性质的,暂时不能开源它 :)
  回复  引用  查看    

#14楼 [楼主] 2008-07-15 00:54 kwanhong young      
@12
数据没问题,头像和缩略图都是这个组件负责,截个图:

http://www.cnblogs.com/images/cnblogs_com/uubox/ganalytics.PNG

中间的缺口是网络故障


  回复  引用  查看    

#15楼  2008-07-15 09:38 Jeffrey Zhao      
@kwanhong young
我市指,这个pv值随便来一台服务器放文件就做得到啊,呵呵。:P
  回复  引用  查看    

#16楼  2008-07-15 09:46 天天无用      
试了一下,64位win2003服务器版无法运行,报错
Could not load file or assembly 'System.Data.SQLite, Version=1.0.48.0, Culture=n
eutral, PublicKeyToken=db937bc2d44ff139' or one of its dependencies. An attempt
was made to load a program with an incorrect format.
bz看看怎么回事
  回复  引用  查看    

#17楼  2008-07-15 09:59 蛙蛙池塘      
呵呵,不错,是时候推出自己的分布式文件系统了。
  回复  引用  查看    

#18楼  2008-07-15 12:21 leleroyn [未注册用户]
楼主用的的SQLite数据库做存储?
  回复  引用    

#19楼 [楼主] 2008-07-15 20:53 kwanhong young      
@15
计划往往跟实际相差很远,要提升pv还有很多非技术的因素:)

@16
因为我这里没有64位的环境,不知道用源码能否编译通过
sqlite的源码:http://www.sqlite.org/download.html

@18
用sqlite做数据块的索引,而实际数据储存在另一个二进制文件里头。
  回复  引用  查看    

#20楼  2008-07-15 21:16 airwolf2026      
好东西...想看后续的文章
  回复  引用  查看    

#21楼  2008-07-30 11:59 Birdshover      
好东西
  回复  引用  查看    


标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2008-07-14 16:25 编辑过