从事软件开发行业十多年,专注于网络通信技术和网络语音视频技术,擅长系统架构设计、系统性能优化等。zhuweisky.cnblogs.com
1.缘起: 对象池应该是一个“历史悠久”的概念了,像我们经常说的线程池、还有ADO.NET中的数据库连接池等,都属于对象池的应用。 我们的应用有时也会碰到需要使用对象池的情况,我举个例子说明一下。
1.缘起: 假设我们的订单处理系统所要处理的订单是有优先级的,也就是说,不同的订单类型所要求被处理的紧迫程度不同,对那些优先级高的注单要先处理,对于优先级低的注单可稍后处理。对于处于同一优先级的订单了,就按照其到达的先后顺序进行处理。
1.缘起: 假设我们的订单系统需要管理所有未处理的订单,而客人经常需要查询属于自己的未处理的订单列表。另外,可能客服人员也需要根据订单ID迅速地找到对应的未处理订单。基于第一个需求,我们就可以将未处理的订单依据客人的帐号进行分组管理。
1.缘起: 我们经常需要对一些动态对象进行管理,最常见的例子就是在线用户管理。当一个用户成功登陆到服务器后,我们就需要将其管理起来;当他退出后,就不再需要再管理他了。这就是所谓动态对象的含义,这些对象并不是一直需要被管理,只有当其被激活后,才需要被管理。
1.缘起: 假设我们的用户管理系统要求用户的ID和Name都必须是唯一的,并且用户的ID和Name一经确定就不能被修改。而且管理系统经常需要根据ID来查找Name,也经常需要根据Name来查找ID。
1.缘起: 对于需要进行线程同步的地方,我们经常用的就是.NET内置的lock关键字和ReaderWriterLock类。lock的功能相对简单,因为它不区分读写,也就是说如果都在lock块中,读线程都会阻塞另一个读线程,在很多读远远多于写的应用中,这会极大地折损性能。
1.缘起: 假设我们的C/S系统中服务端与客户端之间采用UDP进行通信,那么服务端如何知道每个客户端当前是否仍然在线了?有可能某个客户端一直没有退出,但是在很长一段时间内都没有与服务端作任何通信,那么服务端就应该认为这个客户端已经离线了吗?为了能让服务端掌握每个客户端是否在线的状态,我们可以这样做,只要客户端一启动起来,就每隔一段时间间隔(如10秒)就向服务端发一个“我还在线”的消息,以表明自己的状态。
1.缘起: 假设我们的报表系统需要在每天的00:05:00统计前一天的报表数据,需要在每周一的00:30:00统计上周的报表数据,又需要在每月1日的00:30:00统计上月的报表数据。 这些报表统计任务是很常见的系统需求,对于类似这样的在指定时刻执行的定时任务,我使用ESBasic.Threading.Timers.TimingTaskManager(定时任务管理器)来处理它。
1.缘起: 举个例子也许就能够说清楚回调定时器的用途。假设我的订单系统接收各种不同类型的订单,当订单A进来时,系统根据订单的类型和其它特征进行综合判断后,决定A订单要在2秒之后被方法M1处理;接下来收到的B订单经过同样的判断后,决定要在10秒后被方法M2处理,……。
1.缘起: 假设我的订单处理系统有这样的需求:将一天24小时分为4个时段,凌晨2:15到8:30采用A类型的处理器处理接收到的订单,8:30到14:00采用B类型的处理器,14:00到20:00采用C类型的处理器,20:00到第二天凌晨2:15采用D类型的处理器。
1.缘起: 假设我们的系统在运行的过程中,源源不断的有新的任务需要处理(比如订单处理),而且这些任务的处理是相互独立的,没有前后顺序依赖性(顺序依赖性是指,必须在任务A处理结束后才可开始B任务),那么我们就可以使用多个线程来同时处理多个任务。
1.缘起: 有些系统需要每隔一段时间就执行一下某个动作,比如,一个监控系统每隔10秒钟就要检测一下被监控对象的状态是否正常,那这时我们就可以用到循环引擎了。 有人说可以使用.NET框架自带定时器如System.Threading.Timer,嗯,没错。
1.缘起: 假设我们要开发一个多人跳棋游戏。在跳棋游戏中,当一个人走一步棋之后,控制权就轮到下一家,如此轮询,一圈之后控制权又回到自己,然后再继续轮圈下去。我们可以使用数组或列表等数据结构来解决这种转圈圈的问题,但是始终都不够直观。
1.缘起: 同我们从DateTime中将时刻部分作为ShortTime抽离出来一样,我们将DateTime中的日期部分也抽离出来,以ESBasic.Date类来表示。 比如,我们的报表系统是以“天”为单位来进行统计的,为了提高效率,我们会在每天凌晨将前一天的报表数据统计完毕,并存储到数据库中,一天的报表数据就对应数据库数据库中的一条记录,该记录以一个表示日期的整数而不是DateTime作为主键。
(如果您能对照着源码来阅读本文,效果会更好。) 1.缘起: 假设我们的员工打卡系统,需要设定公司规定的上班时间、下班时间、以及还要对员工是否迟到早退等这些情况进行判断。
自从03年正式使用.NET开发以来,已经走过了6个年头,这期间我积累了几套类库和框架,ESBasic便是其中最基础的一个类库。ESBasic是Enterprise Service Basic的缩写,虽然也简写为ESB,但是它和Enterprise Service Bus(企业服务总线)没有任何关系。
所谓动态程序集,就是在运行期间由Emit创建的程序集。 假设,我们的Client和Server之间通过Remoting通信,在某个时刻,Client会创建一个动态程序集,并且Client和Server都会基于该程序集做一些动作,那么如何将动态程序集传递到Server端了?Client和Server如何正常使用这个程序集了? 我的经验是这样的:(1)Client端Emit动态程序集(Dynamic Assembly)完成后,将Dynamic Assembly保持到一个字典中,并再将其保存到一个本地的临时文件。
假设,Remoting服务端接受并保存了一个Remoting客户端注册的回调接口(比如ICallback),在一定的时刻,服务端会通过ICallback接口调用客户端的某些方法。当运行一段时间后,服务端再次回调ICallback时,就抛出了类似下面的异常: 对象“/9ca38d87_7f53_49b7_8c81_f2d499239f27/jqgpmhyy_rwcmicplf3j8s0j_1.rem”已经断开连接或不在服务器上。
DCFramwork框架主要由四个核心的dll构成:DCFramework.dll、DCFramework.Master.dll、DCFramework.Worker.dll、DCFramework.Client.dll。
分布式计算最基本的目的之一就是为了充分利用空闲的计算节点的计算能力。通常,我们首先会将要被分布式计算的程序在每个计算节点部署好,然后才可以调用分布式计算。这种“部署”是一种静态的。之所以称为静态的,是因为还有一种更动态更灵活的方式 -- 我们可以随时的、动态的将我们新完成的程序自动【提交】到已经部署好的分布式框架里动态运行起来。
在系统中,我们经常会遇到这样的需求:将大量(比如几十万、甚至上百万)的对象进行排序,然后只需要取出最Top的前N名作为排行榜的数据,这即是一个TopN算法。常见的解决方案有三种: (1)直接使用List的Sort方法进行处理。
在06、07年的时候,我写过一些关于三层架构方面的东西(参见这里),现在看来,觉得有很多实用性的内容需要补充到里面去。我们还是先从架构图看起,然后一一解释,你就会发现相比于两年前,这个架构做了哪些变化和调整。
在高并发的系统中,我们常采用多数据库分散放置、读写分离、细粒度的隔离级别设定等策略来提高系统的性能。DataRabbit3.3 以及以上版本对这三种策略都给予了内置的支持。 (1)数据库分散放置:对于较大型的系统,在设计数据库时,我们可以根据业务范围将其设计为多个数据库,而不是一个,然后将这些数据库部署在不同的物理服务器上,以分担负载。
在大型系统中,我们经常需要监视我们系统执行的性能状况,当出现性能问题时,我们要能够迅速地找到瓶颈在什么地方。在程序的层面上来说,就是看哪个方法执行所消耗的时间很长。 使用动态代理可以非常方便的记录方法执行的时间,比如,下面的截图,就是ESBasic.
宽容与忍耐 (转摘) 不让古人,是谓有志;不让今人,是谓无量。 忍耐若与敏感、魄力、思维、迅速行动结合,将所向无敌。 脾气服从理性的判断才会成功,否则只是动物式愤怒欲的满足.或从心理学的角度讲是怒需求。
我们要做的2D和3D游戏离不开动画,那么在XNA中如何实现动画了? 首先,我们来看最简单的动画 —— 移动。 要移动一个Sprite非常简单,我们只需要在Game1.Update()方法中改变Sprite的位置坐标,在下次Game1.Draw()方法被调用时,屏幕上显示的Sprite就被移动了。
在所有的图形引擎中,绘制都是最基础的部分,本文将介绍在XNA框架中与绘制相关的基础知识。 在XNA中,我们使用SpriteBatch来进行绘制。首先,我们需要使用SpriteBatch来绘制什么了?是精灵Sprite,对。
当安装好了VS 2008和XNA GameStudio 3.0后,我们就可以开始学习XNA了。 首先,在VS 2008中新建一个XNA GameStudio 3.0项目(选择Windows Game类型),会生成一个最简单的、可运行的游戏模板。
什么是成功了?成功有捷径吗? 我们做技术的,有的想向上或成为架构师、或转向管理,这有捷径吗?有,我相信,最原始最实在的路就是捷径。 无论是做人还是做技术,首先我们都需要 -- 诚实、正直、踏实。
本文讨论针对大型数据表(记录数2千万以上)进行数据查找与分页的可行的高效方案。 首先,恰当的索引是必须的。 没有索引的支持,在大数据表中进行查询是不可思议的。关键点在于如何创建索引? 1.建立正确的聚集索引(clustered index)。
谈到激励,就不得不提一个经典的故事 -- 《兔王遇到的难题》。 1.兔王遇到的难题 南山坡住着一群兔子。在蓝眼睛兔王的精心管理下,兔子们过得丰衣足食,其乐也融融。可是最近一段时间,外出寻找食物的兔子带回来的食物越来越少。
我们现在的一个.NET应用程序需要用到2G左右的内存,当我们将这个程序放到有4G内存的服务器上运行时,就会抛出OutOfMemory异常。 为了搞清楚抛出异常的原因,我写了个用于申请内存的测试程序,每次申请100M。
正如ORM名称所指示的,实现ORM的关键点在于解决“对象--关系”之间的映射,例如,如何将一个DataRow转换为一个Entity Object,又如何将一个对某Entity Object的操作映射到一个IDbCommand,等等。
我在项目中都使用Spring.net作为IOC容器,今天有遇到了以前曾经出现的一个奇怪的bug,描述如下。 我配置了GameRoomConfig对象: ...
什么是DataRabbit?如何使用DataRabbit?本手册会给你答案。 《DataRabbit 完全手册V1.0》是依据当前最新版本DataRabbit3.2(支持SqlServer 2000/2005/2008)进行阐述。
在通过Remoting调用重载的泛型方法时,遇到了一个奇怪的问题,现使用一个例子一步步来说明如下。 一.没有重载的情况 假设Remoting的接口是IComputer: public interface IComputer { int Ad...
在多线程程序中,我们经常需要对要访问的资源进行加锁。加锁的目的是为了同步对资源的访问,但是,加锁不可避免的会降低应用的并发量。那么如何在需要加锁的时候,尽可能地提高并发量了?下面是我的一些经验,仅供参考。
最新版本的DataRabbit(版本号:V3.2)新增一项重要功能--可以捕获访问数据库时产生的异常的详细信息,包括:异常对象、Sql语句、sql参数的名称和值。这是由IDBOperationLogger接口提供支持的。
这段时间在对我们的棋牌系统做压力测试,模拟3000用户同时在线的状况。在这种情况下,数据库服务器的cpu消耗仅为2%左右(cpu是2*至强4核),内存占用1.8G(物理内存共有4G),大概平均每秒钟向数据库中插入40多条记录(三个表,包括游戏主从记录、利润记录等),还有数十次的select和update。
对于SqlServer数据库,当有数据库连接建立时,会触发Audit login 事件;而当有某个数据库连接关闭时,将触发Audit logout 事件。 一.Audit logout 的Duration值 注意,在SQLSERVER的事件探查器中,我们通过观察可以发现,Audit login 和 匹配的Audit logout 事件使用的是同一个SPID,而且Audit logout 事件记录的StartTime正是Audit login事件产生的时间。
增加了对SqlServer2005/2008的新的数据类型的支持,如uniqueidentifier、time、sql_variant等。另外,EntityCreator也一起更新--不再强迫为Entity生成ToString()方法,使用者可以主动选择是否要生成。
在游戏开发中,AI的最基本问题之一就是寻路算法或称路径规划算法,在三年前,我曾实现过基于“图算法”的最短路径规划算法,然而在游戏中,我们通常将地图抽象为有单元格构成的矩形,如: (本图源于这里) 这个微型地图由3*3的单元格构成,当然,实际游戏中的地图通常比它大很多,这里只是给出一个示例。
在DataRabbit 轻量的数据访问框架(12)-- 将DataRabbit融入架构 一文中介绍了如何将DataRabbit与三层架构结合起来,但是,在实际的项目中,每一层是如何使用DataRabbit的了?本文将展示作者在项目中使用DataRabbit的标准做法。
在下面的例子中,我定义了一个事件发布类Computer,事件订阅者ComputerManager。Computer发布了一个OnAction事件,并且该事件在Increase方法被调用时触发。
在IL中,方法的定义语法: .method () { } 一.Flags部分可设置 1.可访问性 privatescope: 该方法不能被引用。 private: 该方法只能被自身及其嵌套类型调用。
本文通过一个简单的示例来说明在IL中进行异常处理时要注意的关键点。 我们来看一个包含try...catch...finally的示例: public void TestEF() { Transa...
首先看一个例子: public void Test(int a, StudentType studentType) { string ss2 = a.
一.OpCodes.Ldind_Ref OpCodes.Ldind_Ref ,MSDN的解释是:将对象引用作为 O(对象引用)类型间接加载到计算堆栈上。 比较拗口,我对OpCodes.Ldind_Ref 的理解是,当前计算堆栈顶部的值是一个(对象引用的)地址(即指针的指针),而OpCodes.Ldind_Ref 就是要把这个地址处的对象引用加载到计算堆栈上。
当我将基于DataRabbit的应用程序放到windows server 2008 SP1上运行时,抛出了System.AccessViolationException,提示信息为:“尝试读取或写入受保护的内存。
利用业余时间写了个基于XNA 3.0 的2D网络游戏引擎,引擎取名为Strive -- 奋斗。 基于Strive引擎,我做了个Demo - XTank,本文末会提供XTank的源码下载。