从事软件开发行业十多年,专注于网络通信技术和网络语音视频技术,擅长系统架构设计、系统性能优化等。zhuweisky.cnblogs.com
对大多数大型系统而言,数据库往往是最容易出现瓶颈的地方,而通过使用恰当的缓存技术可以非常有效地减轻数据库的负载。 将系统中用到的所有数据进行分类,分别对待不同种类的数据而不是一视同仁,有利于正确地做出缓存哪些数据、以及如何缓存的决策。
今天解决一个部署问题,问题是这样的: 我们的平台和GameServer部署在IDC的同一局网中,平台一块网卡配置了2个IP地址。 GameServer通过Remoting访问平台正常,平台通过Remoting回调GameServer也成功,但是GameServer通过Remoting访问平台的动态插件服务时,却抛出Socket异常。
如果你使用Spring.net作为你的IOC容器,那么一定要注意这个问题--Spring.net 目前不支持getter、setter的访问限定符。 我们通常使用setter属性来进行依赖注入,如: public class A { #regio...
动态代理的一个最主要的应用场合就是实现AOP - 截获方法调用,加入自己的预处理、后处理或Around处理。 我在ESBasic.Emit中实现了对这些截获的支持。 首先,介绍两个截获者: /// /// IMethodInterceptor 对方法进行截获并加入预处理和后处理。
void 也是.NET中的一种类型,只不过在C#中看不到“System.VOid”这种Type,而在IL这一层是可以看到的。 如果我们要通过反射判断一个方法是否有返回值,比较直观的解决办法好像是这样: MethodInfo originMethod = ;if (originMethod.
我们假设静态类DataHelper类有一个静态方法: public static object GetSafeDbValue(object val) { if (val != null) { ...
要告别作坊式开发,QA就变得非常重要。 本文是根据公司当前的现状而描述的,并不一定普遍适用--合适的,就是最好的。 QA 职责: 1. 制定和完善项目开发过程中的各项工作流程和规范。
当项目繁多的时候,需要规范,并且定义到细节,只有这样,才能支持大规模的开发。 PM非常重要,PM的能力将直接导致项目最后的质量。 本文是根据公司当前的现状而描述的,并不一定普遍适用--合适的,就是最好的。
总裁的三种境界:事必躬亲是下策,有人分劳是中策,各人尽责是上策。 一个公司能高效运作的一个基础是,有一群专业的人在流畅地分工协作、相互配合。 所以,总裁需要找专业的人来做专业的事,这样可以最有效地节约时间和成本。
在网络游戏中,有一个最基本的需求是,如果让一个玩家的动作(比如行走)即时地、流畅地在其它的游戏地理位置相邻的玩家的屏幕上显现,如果是在局域网内,这个不是什么大不了的问题,但是如果游戏玩家是分散在Internet上的用户,由于网络的延时的影响,使得其成为项颇有难度的任务。
有时候,我所谓的满足其实也很简单,就是一首好听的歌有人愿意和我分享。 有时候,我真希望是拉萨城下一个裹着红布的小和尚,日日颂经,沐着光芒。 当我第一次听到这首歌,刹那间天地变色。
当前我公司在工作任务分配、进度跟踪方面存在的一个严重问题是:上级下达任务给下面的员工后,下面的员工消极被动的接受任务然后展开工作,在工作过程中,上级会经常询问下级的进展情况,并在任务延期的时候频繁催促,这样的结果是,上级疲于跟进任务细节进展,下级也容易产生抵触情绪而丧失积极主动性,从而,下级不会主动向上级汇报工作进展状况,更严重的是,工作中出现问题或意外情况时,也没有主动上报的意识,导致上级不能及时地了解必要的信息而因此可能做出错误的判断。
今日将Remoting服务端搬到一台双网卡的服务器上启动,结果客户端无法Remoting连接到服务器,经过探索,发现Remoting服务绑定到了内网网卡的地址,解决办法很简单,只需要在Channel配置项中将useIpAddress属性设置为false,如: ...
通常,我们的Tcp服务器会放在IDC机房的某一个或几个防火墙后面,客户端与服务器之间的TCP连接会经过防火墙中转,如下图所示: 在这种情况下,有一点特别需要注意:当Firewall与Server之间的Tcp连接在一段时间(如10分钟)内没有任何应用层的消息经过时,Firewall可能会主动断开与Server之间的Tcp连接,但是Client与Firewall之间的连接一直是有效的。
DataRabbit3.0为ORM访问器提供了批量插入的功能,其方法定义如下: /// /// BatchInsert 批量插入一组记录。忽略所有Blob字段。 /// void BatchInsert(IList entityList); 当我们需要一次性向同一Table中插入大量(如千条以上)的记录时,使用BatchInsert方法可以显著的提供性能。
这几天研究了一下Linq,C# 3.0中的“扩展方法”特性为IEnumerable增加了诸如Where、Select等查询方法,这使得“语言集成查询”成为顺其自然的事情。而C#3.0中Linq的实现也是建立在C#2.0的匿名委托的特性之上。
今天装好了VS2008 Beta2,就迫不及待地试用一下Linq中的ORM功能,在初步尝试后,发现Linq中的ORM还是非常不错的,通过反射查看System.Data.Linq.dll发现,Linq中的ORM是使用反射完成了OR的映射工作,基于此,我开始有点怀疑Linq中的ORM的性能问题。
DataRabbit 3.0重写了DataRabbit 2.0的ORM实现的内核,性能提升了90倍左右,结果是DataRabbit 3.0的ORM性能与直接使用ADO.NET的性能已经非常接近。这是如何做到的? 主要是基于两点:(1)DataRabbit 2.0 基于泛型和反射实现,而DataRabbit 3.0 基于泛型和Emit动态程序集实现。
当客户端与服务端通过Tcp Socket进行通信时,如果客户端应用正常退出或异常退出,服务端都会在对应的连接上获取感知(如返回0、或抛出异常)。但是,如果客户端的网线被拔掉,那么,默认情况下,服务端需要在2个小时后才会感知客户端掉线。
Spring.Services程序集中提供了对Remoting的支持,使用Spring.net可以方便的发布和使用Remoting服务。1.Remoting发布(服务端) (1)首先在config文件中注册通道: ...
我在前文当泛型的参数类型是动态的... 中以一个简单的例子引出了动态代理,我们使用动态代理,主要是因为动态代理拥有这样的能力--使得某个类型A在运行的时候能转化为一个指定的接口I,即使这个类型A在定义的时候并没有从这个指定的接口I继承。
在使用泛型技术时,我们经常使用静态泛型参数,即泛型的参数类型在编译时就已经确定,比如: IList list = new List(); 集合IList的泛型参数是int类型,这在编译期就可以知道,于是,我们可以这样调用IList的Add方法: list.Add(6) ; 如果泛型的参数类型是动态的了,也就是说,只有当程序运行起来后,才知道泛型参数的具体类型,其可能是int,也可能是string或其它。
一个概念只有将其放到一个具体的上下文中,其含义和作用才会清晰、明确。脱离了上下文,概念就失去了其价值和生命力。所以,学习使用任何技术或概念的时候,有一件事情是非常重要的,那就是透彻地理解该技术概念所位于的上下文,这将有助于我们更好地使用和驾驭这个技术。
框架和类库等概念的出现都是源于人们对复用的渴望。“不要重复发明轮子”,成了软件界的一句经典名言。从最初的单个函数源代码的复用,到面向对象中类的复用(通常以类库的形式体现),再到基于组件编程中二进制组件(.NET中是以IL程序集形式存在的)的复用,人们复用软件的抽象层次越来越高。
在 我的架构经验小结(二)-- 关于三层架构 一文中,已经比较深入的介绍过三层架构方面的一些经验了,现在,我们来使用一个更小的比例尺来近距离观察我所理解的三层架构。一.三层架构图 二.系统各层次职责1.UI(User Interface)层的职责是数据的展现和采集,数据采集的结果通常以Entity object提交给BL层处理。
(完全限定类名:DataRabbit.Core.IPagerManager) DataRabbit框架提供了对单表查询的结果进行分页的功能,这就是IPagerManager所完成的目标。我们可以从DataRabbit的入口点IDataAccesser中获取IPagerManager引用: PagerParameters param = .
(完全限定类名:DataRabbit.Schema.IDataSchemaAccesser) 在前面介绍的很多访问器的实现中,都不需要使用者提供任何关于数据库表结构的信息(比如,主键、主外键关系等),这是因为它们都借助于IDataSchemaAccesser来获取目标数据表的大纲信息,本文就来介绍如何使用DataRabbit框架中的IDataSchemaAccesser来访问和操作数据表的大纲。
(完全限定类名:DataRabbit.Application.TransactionScopeFactory ,DataRabbit.Application.TransactionScope) 关于TransactionScopeFactory首先要提醒以下几点: (1)TransactionScopeFactory是DataRabbit框架的入口点,所有的访问器、分页管理器、大纲操作者都可以从TransactionScopeFactory生成的TransactionScope(事务范围)处获取。
(完全限定类名:DataRabbit.Relation.ISPAccesser) 虽然IRelationAccesser可以调用一些不含out参数的存储过程,但是在DataRabbit中调用存储过程最好是通过ISPAccesser接口来进行。
(完全限定类名:DataRabbit.Relation.IRelationAccesser) 前面介绍的IOrmAccesser是对单表进行ORM访问,而ITableAccesser是对单表进行基于关系的访问,如果我们要进行联合查询这样的跨表搜索,则使用它们就无法达成目标。
(完全限定类名:DataRabbit.Relation.ITableAccesser) ORM并不能完成所有的事情,有些数据库访问还是需要基于关系来进行,对于那些不提供基于关系进行数据访问操作的纯ORM框架,我认为是不明智的。
(完全限定类名:DataRabbit.ORM.IEntityRelationLoader) 在DataRabbit框架提供的ORM功能之中,除了IOrmAccesser接口展现的核心ORM功能外,IEntityRelationLoader接口也提供了一些有意义的功能。
本文将接着 DataRabbit 轻量的数据访问框架 -- IOrmAccesser 继续介绍IOrmAccesser的一些高级功能。这些高级功能需要DataRabbit.ORM.ISmartEntity接口的支持。
(完全限定类名:DataRabbit.ORM.IOrmAccesser) 在DataRabbit框架中,通过IOrmAccesser来对数据库进行ORM访问,只要Entity(即ORM中的“O”)的定义与数据库表的结构完全一致,即可使用IOrmAccesser来对其进行ORM操作。
(完全限定类名:DataRabbit.ITransactionAccesser) 在DataRabbit 轻量的数据访问框架 --序 中,我们已经知道,所有的访问器接口都继承了ITransactionAccesser接口。
(最新版本为DataRabbit 4.0,请到本文末下载处下载。最后更新:2009.09.15) DataRabbit支持基于关系(Relation)的数据库操作和基于ORM的数据库操作,支持SqlServer,并且可以通过插件的方式对其它数据库类型提供支持。
在目前的工作中需要解决复制整个SqlServer数据库的问题,复制的内容包括数据库大纲、数据库中的存储过程、函数、表结构、主外键关系以及表中的所有数据等,也就是说copy版本与原数据库一模一样。经过一段时间的摸索,找到的一个比较简单的解决方案是:(1)在复制数据库之前,先备份该数据库到文件。
System.Threading.Timer 是一个非常常用的定时器类,关于这个类的使用,我们需要注意以下几点: 1.System.Threading.Timer 的任何一个实例,实际上是通过使用win32底层(非.NET Thread Pool中的线程)来进行调度的。
1.领导和管理 人们乐于被领导;他们不喜欢被管理,不喜欢像牛一样被驱赶或指挥。 管理者强迫人们服从他们的命令,而领导者则会带领他们一起工作。 管理是客观的,没有个人感情因素,它假定被管理者没有思想和感受,必须被告知要做什么和该如何做。
.NET提供了Soap序列化的方式可以实现 object xml ,但是它有三个缺点:(1)它要求object 必须打上[Serializable]标签,这是强侵入性的。(2).NET的Soap序列化与程序集的版本紧密关联,如果object的class定义没有发生变化,而定义该class的程序集版本发生了变化,那么反序列化(xml->object)可能就会失败。
在ESFramework的设计实现中,很多地方都用到了Null Object设计模式。Null Object模式的含义在于,提供一个对象给指定的类型,用以代替这个对象为空的情况。 Null Object提供了“什么也不做”的行为,隐藏来自它的合作者的细节。
在 我的架构经验小结(一)-- 常用的架构模型 一文中简单介绍了我常采用的几种架构模型,本文将稍微深入地介绍其中的一种 -- 三层架构模型。一.三层架构图 二.系统各层次职责1.UI(User Interface)层的职责是数据的展现和采集,数据采集的结果通常以Entity object提交给BL层处理。
本文来自我提供用例培训的PPT。本文内容包括1.用例基本概念2.用例的作用3.从何处发现用例线索4.如何发现用例5.编写用例的准则6.如何判断系统用例是否有效1.用例基本概念(1)需求分析(用例技术)、系统分析(OOA)、系统设计(OOD)、系统实现(OOP)(2)用例的主要作用是:用来捕获系统的高层次(High Level)用户功能性需求 (3)用例从用户的视角描述了在逻辑上相对完整的一个功能流程。
经过这几年的积累,在系统架构方面逐渐积累了一些自己的经验,到今天有必要对这些经验作个小结。在我的架构思维中,主要可以归类为三种架构模型:3/N层架构、“框架+插件”架构、地域分布式架构。 一.三种架构模型 1.3/N层架构 这是经典的多层架构模型,对于稍微复杂一点或特别复杂的系统,不使用分层架构是很难想象的。
今天在使用.NET操作消息队列时,碰到一个小问题,如果采用XmlMessageFormatter序列化消息体,则消息体中不能包含Hashtable等字段,否则将无法完成序列化和反序列化(即使消息体对象加上了Serializable特性也不行)。
在将数据从数据源导出到数据目标的过程中,我们通常需要对数据进行一些检查、验证、加工、转换等操作,而这个加工转换的流程可能是非常复杂的,DTS通过可视化的拖拽的方式对数据加工转换流程进行自定义编辑。
ESFramework体系的目标之一就是帮助快速构建IM与业务相结合的系统,在我们的业务应用中,经常会遇到类似这样的需求:商家或服务商需要提供一些资料(文档、影片宣传资料等)给他的用户,他希望用户能方便地下载这些资料,另外,用户也可以直接上传自己的文件到服务器供商家检阅。
上一篇ESFramework扩展之EsfP2P -- 基于ESFramework的P2P实现 主要介绍了EsfP2P如何协助建立P2P Session,那只是整个故事的一半,EsfP2P主要职能的另一半是确保P2P消息的可靠传递。
好久没有写关于ESFramework的文章了,曾很早就承诺过要写一篇介绍基于ESFramework实现NAPT P2P的文章,今天终于能抽出时间做这件事。 网络地址转换NAT(或者NAPT)的基本理论知识,网上有很多相关资料,不是很清楚的朋友可以先了解下什么是NAT、以及为什么要使用NAT。
在DTS开发记录(1)--系统总体结构 一文中,我们已经看到,一次数据传递任务基于一个连接对和一个数据映射进行。但是之前,我们并没有提到“数据迁移任务”这个元素。随着设计的演化,我们发现一个数据任务已经不再仅仅是一个连接对加上一个数据映射了。