很早就写了关于kbmMW Server如何实现的垃圾回收,但最近一段时间还是为此遇到问题,实现的Server不能稳定运行,发生问题后不响应客户端的查询请求,在客户端得到服务端返回地址错误信息,只能重启Server解决。这是让人最头的问题,还好,今天终于搞定。

先复习一下早前写过的资料,回顾一下何为kbmMWServer的垃圾回收及实现机制,然后再看我遇到的具体问题。

kbmMWServer垃圾回收处理机制(一)

kbmMWServer垃圾回收处理机制(二)

kbmMWServer垃圾回收处理机制(三)

总结前文,kbmMWServer通过两个属性来控制是否做垃圾回收及定时回收垃圾的时间间隔:

GarbageCollection:是否做垃圾回收

GarbageInterval:回收垃圾的时间间隔,单位是秒

这里的垃圾,是指不应该保留的Service实例。

当客户端发来一个请求时,kbmMWServer会取得一个对应的Service实例来处理该请求,在服务端,kbmMWServer通过池(Pool)来管理Service实例,随着客户端的不断请求及服务端的响应,会在Service实例池中产生多个Service实例,当客户端的请求数量降下来,或者极端的说长时间没有了客户端的请求,那么在服务端的Service实例池中就会有多个不用的实例,因此需要定时的清理、删除,以节省服务器资源。

更具体的说,到底什么样的Service实例需要视为垃圾来清理呢?还是通过代码来说更为明确,找到TkbmMWServiceDefinition类的实现,下面几个属性决定Service实例是否被回收:

  TkbmMWServiceDefinition = class(TkbmMWCustomServiceDefinition)
public
...
property MinCount;//服务端保留的最小Service实例数,小等于这个数时,Service实例不被回收
property MaxIdleTime;//一个Service实例最大的空闲时间,当超过这个时间时,将被回收
property MaxIdleStatefulTime;//一个有状态Service实例最大的空闲时间,当超过这个时间时,将被回收
property Timeout;//一个Service实例执行时的超时时间,当正在执行时超过这个时间,将被回收
...
end;

当开发者不设置这几个属性,也就是默认情况下:

MinCount为-1,表示在服务端不保留Service实例,所有的Service实例都将做回收处理

MaxIdleTime为0,表示不管空闲多长时间,Service实例都不会被回收

MaxIdleStatefulTime为0:有状态Service实例,不管空闲多长时间,都不会被回收

Timeout为0,一个Service实例不管执行多长时间,都不会被回收

现在,我们可以找到最核心的垃圾回收处理的代码,具体看看,kbmMW如何例用上面所说的四个属性来实现的逻辑,因为版权的问题,不能贴出完整代码,只能用文字来描述这一过程。

前文中提到,kbmMWServer是利用TkbmMWServicePool来管理Service实例池的,这个TkbmMWServicePool类实现了一个方法GarbageCollect(All:boolean),执行垃圾回收。

其中的参数All,指回收所有的Service实例,什么情况下这个All为True呢?就是在停止kbmMWServer时,或者退出Server时。

TkbmMWServicePool.GarbageCollect进一步委托给ServiceDefiniation.Instances.GarbageCollect来执行回收动作,

if All or (sd.MaxIdleTime>) or (sd.MaxIdleStatefulTime>) or (sd.Timeout>) then
sd.Instances.GarbageCollect(All);

这里用到了上面所说的三个属性:MaxIdleTime,MaxIdleStatefulTime及Timeout做为执行垃圾回收的条件,由此可以理解,如果开发者设置了这三个属性其中之一不为0,才实际做垃圾回收动作,否则的话,只有在退出Server时才做。换句话说,仅设置kbmMWServer的GarbageCollection及GarbageInterval属性是不够的,还需要设置TkbmMWServiceDefinition的MaxIdleTime,MaxIdleStatefulTime及Timeout三个属性才会执行垃圾回收。

接下来,就到了TkbmMWServiceInstances.GarbageCollect方法,执行具体的垃圾回收动作,此方法是垃圾回收的核心代码,有源码的开发者可以直接去看。

作者首先建立一个lstExpired列表对象,目的是把需要清理的Service实例放入此列表对象中,接下来,就是循环FInstances,取出每个Service实例,先计算Service实例最后被请求时间与当前时间差:

cs:=FInstances.Items[i];//取出Service实例
d:=trunc((n.UTC-cs.FLastRequestTime.UTC)*SECSPERDAY);//计算所用时间,单位秒

下面这句,意思是说,如果一个Service实例没有被预先锁定并且处在闲置状态,即没有正在处理客户端请求,则按MaxIdleStatefulTime及MaxIdleTime回收,否则,按Timeout进行回收。FPendingLock在对一个Service加锁前为True,加锁后为False,当为True,表示正在锁定一个Service实例,我称之为预先锁定。FRequests,当锁定一个Service前,加1,解锁一个Service前减1,默认值为0。当一个Service.Requests为0,表示没有被锁定,可以解读为闲置。

if (not cs.FPendingLock) and (cs.FRequests<=) then
//按MaxIdleStatefulTime及MaxIdleTime回收
else
//按Timeout进行回收

在这一过程中,还会触发kbmMWServer.OnGarbageCollectQuery事件,利用该事件,可以进一步决定一个Service实例是否被回收。

当判定一个Servcie实例应该被回收时,把他加入到lstExpired对象列表,同时,从实例池中删除。

最后代码,就是按lstExpired,做Service实例的销毁。

整个过程大体就这样,那我犯的什么错误呢?就是设置了短的Timeout时间为60秒,同时Server也设置为60秒,在这种情况下,服务端每60秒检查一次Service实例,当一个正在执行的实例执行超过60秒时,被视为超时而被回收,从而造成服务端不稳定!

找到问题原因,自然就解决,不设置Timeout,让其保持默认值0。

再谈kbmMW垃圾回收的更多相关文章

  1. 浅谈JVM垃圾回收

    JVM内存区域 要想搞懂啊垃圾回收机制,首先就要知道垃圾回收主要回收的是哪些数据,这些数据主要在哪一块区域. Java8和Java8之前的相同点有很多. 都有虚拟机栈,本地方法栈,程序计数器,这三个是 ...

  2. 浅谈java垃圾回收机制

    今天看thinking in java,里面很详细的谈到java垃圾回收器机制,看完后让我对这神秘的区域有一定的了解,特写一些小总结记录下来. 分两点来说. 第一点:Object.finalize() ...

  3. 浅谈 JavaScript 垃圾回收机制

    github 获取更多资源 https://github.com/ChenMingK/WebKnowledges-Notes 在线阅读:https://www.kancloud.cn/chenmk/w ...

  4. JS 从内存空间谈到垃圾回收机制

     壹 ❀ 引 从事计算机相关技术工作的同学,对于内存空间相关概念多少有所耳闻,毕竟像我这种非计算机科班出身的人,对于栈堆,垃圾回收都能简单说道几句:当我明白JS 基本类型与引用类型数据存储方式不同,才 ...

  5. 浅谈python垃圾回收机制

    引入 ​ 解释器在执行到定义变量的语法时,会申请内存空间来存放变量的值,而内存的容量是有限的,这就涉及到变量值所占用内存空间的回收问题,当一个变量值没有用了(简称垃圾)就应该将其占用的内存给回收掉,那 ...

  6. 浅谈c#垃圾回收机制(GC)

    写了一个window服务,循环更新sqlite记录,内存一点点稳步增长.三天后,内存溢出.于是,我从自己的代码入手,查找到底哪儿占用内存释放不掉,最终明确是调用servicestack.ormlite ...

  7. 面试题之C# 内存管理与垃圾回收

    面试题之C# 内存管理与垃圾回收 你说说C# 的内存管理是怎么样的 这句话我记了一个多礼拜了, 自从上次东北师大面试之后, 具体请看<随便扯扯东北师大的面试>. 国庆闲着没事, 就大概了解 ...

  8. JVM虚拟机(四):JVM 垃圾回收机制概念及其算法

    垃圾回收概念和其算法 谈到垃圾回收(Garbage Collection)GC,需要先澄清什么是垃圾,类比日常生活中的垃圾,我们会把他们丢入垃圾箱,然后倒掉.GC中的垃圾,特指存于内存中.不会再被使用 ...

  9. [牛感悟系列]JAVA(1)理解JAVA垃圾回收

    理解JAVA垃圾回收的好处是什么?满足求知欲是一方面,编写更好的JAVA应用是另外一方面. 如果一个人对垃圾回收过程感兴趣,那表明他在应用程序开发领域有相当程度的经验.如果一个人在思考如何选择正确的垃 ...

随机推荐

  1. Hongcow Buys a Deck of Cards CodeForces - 744C (状压)

    大意: n个红黑卡, 每天可以选择领取一块红币一块黑币, 或者买一张卡, 第$i$张卡的花费红币数$max(r_i-A,0)$, 花费黑币数$max(b_i-B,0)$, A为当前红卡数, B为当前黑 ...

  2. leetcode-algorithms-2 Add Two Numbers

    leetcode-algorithms-2 Add Two Numbers You are given two non-empty linked lists representing two non- ...

  3. 使用CSDN-markdown编辑器

    欢迎使用Markdown编辑器写博客 本Markdown编辑器使用StackEdit修改而来,用它写博客,将会带来全新的体验哦: Markdown和扩展Markdown简洁的语法 代码块高亮 图片链接 ...

  4. Django之信号和序列化

    前言 Django的信号要从一张抽象图和一个需求说起: 赛道:Django 赛车:http请求 基础设施:Django设置的信号 一.Django内置信号类型 1.既然赛道上有各种基础设置,那么Dja ...

  5. 使用机器学习检测TLS 恶意加密流——业界调研***有开源的数据集,包括恶意证书的,以及恶意tls pcap报文***

    2018 年的文章, Using deep neural networks to hunt malicious TLS certificates from:https://techxplore.com ...

  6. 改变Cube的Shader下的Alpha值,实现Cube若隐若现的效果。

    private float rotaSpeed = 5f; private float timer = 1; private bool flag = true; private float delay ...

  7. linux:SSH最简单教程

    1.简介 ssh是一种用于计算机之间的加密登录协议.用户从本地计算机用ssh协议登录另一台计算机就可以认为登录安全,中途截获密码也不会泄露. 2.原理 (1)用户发登录请求给远程主机 (2)远程主机发 ...

  8. flask项目结构(四)使用sqlalchemy和alembic

    简介 其实我不是啥正经人,错了,不是啥正经程序员,所能想到的估计也就码农一级吧,高级程序员,搞什么算法,什么人工智能,大数据计算…………离我还太遥远. 但是这并不妨碍我继续学习,继续写垃圾小程序. 反 ...

  9. [Leetcode 104]求二叉树的深度Depth of BinaryTree

    [题目] Given a binary tree, find its maximum depth. The maximum depth is the number of nodes along the ...

  10. C数据结构 : 线性表 与 链表

    一.线性表 一般表现为数组,使用一组地址连续的存储单元依次存储数据元素,如图: 它具有如下特点: 长度固定,必须在分配内存之前确定数组的长度. 存储空间连续,即允许元素的随机访问. 存储密度大,内存中 ...