从事软件开发行业十多年,专注于网络通信技术和网络语音视频技术,擅长系统架构设计、系统性能优化等。zhuweisky.cnblogs.com
对于数据源向同一数据目标导出(我们称之为“数据汇集”)和增量导出来说,对主键的处理也是一个大的挑战。 我先定义一下在本DTS系统中主键(PrimaryKey)的含义:PrimaryKey 表示主键或联合主键,PrimaryKey并不是针对某个数据库表的,而是针对某个特定的DataMapping而言的,它用于在数据迁移过程中来唯一确定数据源或数据目标中每条记录。
我们经常需要通过反射来调用目标对象的方法或获取/设置目标对象的属性,Type.InvokeMember 方法签名如下: public object InvokeMember(string name,BindingFlags invokeAttr,Binder binder, object target,object[] args,CultureInfo culture); BindingFlags 有个枚举值是BindingFlags.IgnoreCase ,表示忽略name的大小。
数据引擎是数据传递系统(DTS)的核心,正如游戏引擎是PC游戏的核心一样。 IAgileEngine从目前手上的DTS系统中不断的重构完善出来,虽然IAgileEngine已经不局限于在本DTS系统中使用,但是,我还是打算在这个系列文章中来介绍它。
在DTS开发记录(4)-- 映射列一文中,我们详细的讨论了参与映射的源列和目标列,在拥有了映射列的基本概念的基础上,我们可以讨论数据映射DataMapping了。 数据映射主要由一组映射项(MappingItem)组成,它包含了源数据大纲到目标数据大纲的详细的完整的映射关系。
增量导出恐怕是DTS系统中最艰难的部分了,我们曾考虑过很多方案,最后都因为需要表大纲做一定的假设而不具备通用性而放弃。有很多效率较高的方案,由于为了追求通用性而无法实现,因为现实的情况比我们理想的要复杂许多。
在DTS开发记录(1)--系统总体结构 一文中,我们介绍到映射列:“参与了数据映射的源列或目标列。注意,并不是所有的列都会参与映射,这是常见的情况。”1.映射列分为:源映射列和目标映射列。 public interface IMappingColumn { str...
在 DTS开发记录(2)-- 数据管道及插件 一文中,我们介绍了数据管道,IDataPipeFactory的CreateDataPipe方法需要一个IConnection参数,这个参数就表示一个连接。
通过前面两篇文章(已于2006-07-03修正)的介绍,我们已经大致明白了系统的目标的总体结构,从这篇文章开始,我们将逐渐深入到系统内部。 本文讲述数据管道,数据管道是用于在数据源/数据目标与DataTable之间进行数据传递的组件,它是与数据库类型和文件类型相关的,数据从数据源经过数据管道后,就变成与数据源类型无关的数据了,这样映射编辑和数据引擎便能对它们进行一致的处理。
(原文发表于2006-06-28 ,修正于2006-07-03) 在DTS开发记录(序)一文中,我们已经明白了当前这个Data Transfer System的主要目标和存在的难点与挑战。
(原文发表于2006-06-27 ,修正于2006-07-03) 目前手头上正在负责一个DTS(这里的DTS是Data Transfer System的缩写)系统的开发,我打算写一系列的文章来记录这个开发的全过程,这个记录可以说是实时的--每当遇到一个重要问题或解决一个重要问题,我将记录之。
(本文适用于ESFramework V0.3+) 在ESFramework介绍之(7)-- 服务器代理IServerAgent 一文中,我们详细的介绍了IServerAgent,我们已经知道,客户端与服务器之间的所有通信都可经过IServerAgent,包括要转发的P2P消息。
(本文适用于ESFramework V0.3+) 在ESFramework介绍之(7)-- 服务器代理IServerAgent(2006.06.06修正) 的介绍中,我们已经认识了IServerAgent的职责与作用,并且知道了 ITcpServerAgent和IUdpServerAgent是分别使用于Tcp和Udp的ServerAgent。
终于,使用Java完成了一个WebService的例子,其中的一个非常小的问题,折腾了我将近一天的时间。下面给出步骤,说明在Java平台上如何开发WebService。 采用的工具:Eclipse3.1.2 + Tomcat5.5 + XFire1.1 。
在.NET上用的VS.NET+Spring.net+Nhibernate,到了Java平台上,自然对应着Eclipse+Spring+Hibernate。上一篇文章介绍了如何在Eclipse上使用Hibernate的入门,本文就简单介绍一下如何在Eclipse使用Spring。
最近一个项目要用Java做,一点都不熟啊。没办法,只好硬着头皮啃了,花了大半天的时间,终于在Eclipse上完成了第一个Hibernate例子。下面记录关键的步骤,权作笔记,以备日后查看。 (1)下载Hibernate,并向项目中导入Hibernate。
ESFramework网络通信框架的最新版本为4.0 关于最新版本的详细介绍,请参见这里。 自从2004年7月开始,就一直从事N层C/S架构的服务端的开发,从最初的熟悉各种Windows Socket API、熟悉完成端口模型,探索高效稳定的服务端通信模型,时至今日,慢慢的积累了一些(N层)C/S系统的开发经验,ESFramework网络通信框架体系便是这些经验的总结。
ESFramework的4层结构的4层分别是:客户端(Client)、应用服务器(AS)、功能服务器(FS)、数据库服务器。它们之间的联系图示意如下: FS (FunctionServer),功能服务器,处理并且仅处理所有的功能性请求,不参与用户管理、状态保持等,提供最纯粹的功能服务。
(本文部分内容只适合ESFramework V0.3+) 在ESFramework介绍之(14)-- AS与FS通信方案 一文中,我们讲到了AS与FS之间基本的通信方案,并且采取了一些策略来保证AS与FS之间的稳定通信。
如果你的客户端基于ESFramework构建,并使用Tcp与服务端通信。通过这篇文章你将知道如何迅速、高效地创建客户端应用。 ESFramework对基于Tcp客户端的支持主要在ESFramework.Network.Tcp.Passive命名空间,下图给出了该命名空间中的核心组件,以及这些组件之间的关系: 下面解释一下这些组件的作用、职责。
根据插件的“自治”性,插件如果需要配置信息,则插件应该自己能读取和修改配置信息,而不是框架或宿主来完成这些事情。这种松耦合特性,我们曾在ESFramework介绍之(29)―― 插件公共设施 AddinUtil 一文中特别强调过。
以下是我在使用NHibernate过程中遇到的一些小问题,记录下来,权当笔记吧!1.自增序列与严格类型匹配 在使用Oracle数据库的自增主键时,hbm.xml配置文件中generator class可设为"increment",也可设为"sequence",最好使用"increment",使用"sequence"有时在插入obj时会抛出“ORA-02289: 序列(号)不存在”异常! 另外,在load object时,传入的ID的类型要与数据库的严格一致。
这是一篇迟到了很久的文章,要不是今天看到Mediar朋友写的“基于ESFramewok的 客户端和客户端通迅”的文章,我也许还不会想起写这篇应该很早就发表的Blog,它可以帮助ESFramework的研究者/使用者们更好的使用ESFramework。
(本文适用于ESFramework V0.2+) 现在我们回想一下,当网络组件(Tcp/Udp组件)接收到一个消息后,这个消息会流经哪些组件,然后再通过网络组件发送出去了。如果你研究过ESFramework V0.1,你会发现,消息“行走”的路线模型可以用下图表示出来: 请求消息(路径由黑线表示)经过网络组件后,会被Hook链中的各个Hook按照特定的顺序处理,然后到达消息处理器,消息处理器处理请求消息,并给出回复消息(路径由红线表示),回复消息同样再经过Hook链,然后通过网络组件发送出去。
(本文适用于 ESFramework V0.2+) 不知你是否还记得,前面我们讲过,ESFramework规定了插件有如下特点: (1)一个插件是一个独立的物理单元。它可以独立的提供一项完整的服务(功能),而不需要依赖于其它插件。
对于游戏编程而言,我也是个初学者,这个游戏编程入门系列的文章,就当作是我在学习游戏编程的笔记和阶段小结吧。我们先从最简单的“精灵”开始,暂时我们不需要考虑DirectX或是OpenGL,不需要考虑3维等等这些复杂情形,直接使用GDI+绘图功能就可以了。
ESFramework对Tcp和Udp协议都提供了完整的支持,在ESFramework介绍之(21)-- Tcp组件接口ITcp介绍 和 ESFramework介绍之(23)―― AgileTcp 两篇文章中介绍了Tcp组件,相对于Tcp来说,Udp要简单许多,所以我在这里打算用一篇文章来介绍它。
1.Nullable类型可以这么用! int? cursor; //其它逻辑 cursor = (++cursor) ?? default(int); 上述代码的含义是,如果cursor为空值,则取int型的默认值0,否则,将cursor值增加1。
(本文适用于ESFramework V0.2+) QQ上,你给好友发消息,如果对方不在线,则服务器会把这个消息持久化存起来,等好友下次上线时,再转发给他。像这样的消息在ESFramework中称为OverdueMessage。
最近好事连连啊!2006-04-30 11:30:00 本Blog访问量突破100000 ! 也祝嘟嘟于昨天顺利通过硕士答辩!
你一定经常看见类似下面的图标: 它们就表示“撤销”与“反撤销”。在程序中,这种功能通常是使用Command模式实现的,本文也不例外。首先抽象定义Command,使用ICommand接口: public interface ICommand { void Excute() ; } Excute表示执行该ICommand引用的目标的所包含的动作(或动作序列)。
ESFramework中很多重要的组件都配备了日志记录器IEsbLogger,用于记录框架运行时的错误和异常。这些重要组件都暴露了一个名为“EsbLogger”的属性,用于设值法注入日志记录器。
NHibernate功能的强大,勿庸置疑。但是很多地方使用起来也颇为繁琐,比如,无法完整的构建数据层、我们很多时候还是需要绕过NHibernate而直接使用ADO.net;比如,任何一次数据访问,哪怕只是简单的数据读取,我们都需要仔细的处理Session、Transaction。
(本文内容适合于 ESFramework V0.2+) 通常,最单纯的情况是一个插件对应某一特定类型的功能请求,但是,在有的应用中也会出现这样的情况,有多种类型的功能请求相互关联、并且可能交叉,如果是这样,对应每种类型的请求都开发一个插件可能会非常困难,因为这可能会牵涉到插件之间的相互引用/访问,这违背了插件的“自治”性。
我们来讨论一下这种情景,你采用基于ESFramework的4层架构进行应用开发,你分析用户的需求,并将其分类整理为几大块,考虑每一块使用一个功能插件来完成。在这几个插件中,有个插件需要访问某个数据库,并且只有这个插件需要访问这个数据库,根据插件的“自治”性质,你不想将本插件中的数据访问“上升蔓延”到应用程序(FS),而是让它“仅仅”在本插件中,这样,无论是对FS还是插件都是有好处的--FS自己不需要访问数据库(日志记录除外),插件“自治”、而且插件之间相互独立,整个系统的结构是非常清晰简单的。
从事了几年的C/S模式的开发,曾一直无暇研究B/S,前段时间摊上了一个B/S的活,这才开始认真的关注其B/S开发。而且,AJAX技术的风起云涌,也使得B/S应用的表现力日益增强,大有逐步吞食C/S领地之势。
框架,从另外一个角度说,就是一个半成品的应用程序,既然如此,框架在运行的过程中也会遇到诸多的异常、错误情况,我们需要将这些情况记录下来,以便在发生问题时为我们的诊断提供必要的帮助。 最最开始,那还是在ESFramework的前身即EnterpriseServerBase的时候,由于当时只是将EnterpriseServerBase作为一个类库,而并没有提升到一个框架的高度,所以是没有必要为之配备一个日志记录器(Logger),就像你从来不曾看到在使用.NET类库时还必须传个日志记录器给它,以使.NET类库中的API碰到额外情况时能够记录下错误信息。
前面已经介绍了ITcp接口,而AgileTcp就是ESFramework给出的ITcp的参考实现。在之前,我曾经讲解过模拟完成端口的Tcp组件实现和异步Tcp组件实现,在它们的基础之上,我更改了处理策略,而形成了AgileTcp,目的是更清晰的结构、更高的效率。
(本文名字取为“服务器系统自动升级”,实际上适用于所有应用程序自动升级的情况。) 前文介绍了在服务器或客户端应用程序运行的过程中,插件如何自动升级、更新。基于前文相同的理由,AS、FS、IRAS也需要有自动升级的功能。
写了这么多篇介绍ESFramework的文章才想起来还有一些很基础的内容没有介绍,前面介绍的一些组件、框架基本上是与协议无关的(比如无论是Tcp还是Udp甚至是Remoting、WebService都可以通用),然而到了应用的最底层,我们总需要选择一种通信协议,.
记不得在哪里看过这句话,“当你拥有一把用得顺手的锤子,就会认为全世界都是钉子”。所有的事情、所有的问题,你都尝试用这把锤子去解决。很多情况下,常常,这把锤子解决不了问题,或者说,有更好的工具来解决手头的问题。
当我们的服务平台搭建成功后,所需要做的主要事情就是开发服务端功能插件(IFunAddin)和客户端插件(IPassiveAddin),每个插件对(AddinPair)实现了一组相似或相近的需求/功能。
什么是动态组?举个例子就清楚了。QQ支持多人在一个组中聊天的模式是群,这是一种静态组;而MSN中的动态的将多个人拉到一个组中来群聊,就是动态组。关于动态组,还有一个很好的例子,就是多人联网游戏,比如联网的星际。
1.IMessageHeader的实现在哪里?(2006.03.31) MSN上有个叫MeDiar的朋友问我ESFramework中IMessageHeader的实现在哪里?答案是,IMessageHeader在你的具体应用中实现,而不是在ESFramework框架中。
当我们的应用中客户端与AS之间是通过Tcp进行通信的时候,通常,应用也要求管理所有在线的用户。这种管理至少包含以下几点:(1) 当用户上线时,记录上线时间(2) 当用户请求服务时,记录请求服务的时间、服务的类型、本次服务下载的数据量(3) 当用户下线时,记录下线时间。
(环境:.Net1.1 ,Spring.net 1.2 Preview)1.集合属性注入 我们的组件经常需要集合类型的属性注入,比如我的Hook(钩子)组件需要注入一个集合,该集合中的元素(int型)指明了要截获哪些类型的消息。
对于漫游用户的支持和跨区域功能请求的支持是ESFramework最基本的目的之一(回顾),在详细讲述解决方案之前,先了解一下关于这个问题的上下文。 在我们前面讲述的4层C/S架构中,每个AS负责一块区域。
对于“依赖注入”,我最常用的是“设值注入法”(即通过Setter属性注入),对于需要注入很多依赖的类来说,一个一个的手动写属性的繁琐已经让我难以忍受了。于是我写了一个VS2003的小插件,你只需要输入类型和属性名,它就能在编辑器指定的地方自动生成属性,并且一次可生成多个属性。
我们已经积累了这样的经验:如果有一个大块的数据需要通过Tcp发送,我们会采用异步的方式以避免当前工作线程阻塞。那么,如果我们有多个线程需要同时发送大块的数据了?每个线程都在NetworkStream或Socket上提交异步发送数据的请求会导致数据发送的混乱(多个线程同时在一个Socket上进行写操作),所以,我引入了前面介绍的线程安全的网络流。
每个城市都对应着自己的AS,每个AS都有一组FS为之服务,而所有的AS都由一个IRAS联系/管理起来(回顾)。前面我们已经提到,所有的FS都可以是动态添加/移除的,并且FS的地址也是自由可变的。
前面我们已经多次提到,每个AS都有一组FS为之服务(回顾),AS将接收到的功能请求通过Tcp连接池 或Remoting转发给某个FS处理。下面我们将深入讨论AS和FS之间的通信机制。 首先要解决第一个问题,AS如何知道每个为之服务的FS的地址? 最常见的一种解决方案是,AS处的配置文件中有一个FS地址列表,AS每次启动时,就读取这个列表,然后与列表中的每个FS建立Tcp连接池。