GGTalk 对需要频繁查询数据库的数据做了服务端全局缓存处理,这样做一来大大降低了数据库的读取压力,二来在客户端的请求到来时,服务端能更快地响应,极大地提升了用户体验。这篇文章将会详细剖析关于 GGTalk 服务端全局缓存的设计与实现。还没有GGTalk源码的朋友,可以到 GGTalk源码下载中心 下载。
一. GGTalk 服务端三大核心
首先,我们需要了解 GGTalk服务端 的三大核心,其分别是:
- 消息处理:处理来自客户端的消息;
- 全局缓存:将用户和群组的数据缓存在内存中;
- 数据库交互:对数据库中的信息进行增删改查。
1. 消息处理
此部分的代码位于
GGTalk/TalkBase/Server/Core/ServerHandle.cs
当一个客户端的请求进来时,首先会进入消息处理环节,根据用户传递的消息号,进入不同的逻辑分支。以修改用户信息为例:
<span style="color:#333333"><span style="background-color:#ffffff"><code class="language-csharp"><span style="color:#008000">//(客户端逻辑代码)</span>
<span style="color:#008000"><span style="color:#808080">///</span> <span style="color:#808080"><summary></span></span>
<span style="color:#008000"><span style="color:#808080">///</span> 修改个人资料。</span>
<span style="color:#008000"><span style="color:#808080">///</span> <span style="color:#808080"></summary></span> </span>
<span style="color:#0000ff">public</span> <span style="color:#0000ff">void</span> <span style="color:#a31515">ChangeMyBaseInfo</span>(<span style="color:#0000ff">string</span> name, <span style="color:#0000ff">string</span> signature, <span style="color:#0000ff">string</span> department) {
<span style="color:#008000">//...</span>
<span style="color:#0000ff">this</span>.rapidPassiveEngine.SendMessage(<span style="color:#a31515">null</span>, <span style="color:#0000ff">this</span>.talkBaseInfoTypes.ChangeMyBaseInfo, data, <span style="color:#a31515">""</span>, <span style="color:#a31515">true</span>);
<span style="color:#008000">//...</span>
}
</code></span></span>
当一个用户信息被修改时,会调用如上方法,然后通过调用 rapid客户端引擎 上的 SendMessage 方法发送一条消息(其中 data
为用户信息的 byte[]数组
)。
<span style="color:#333333"><span style="background-color:#ffffff"><code class="language-csharp"><span style="color:#008000">//(服务端逻辑代码)</span>
<span style="color:#0000ff">public</span> <span style="color:#0000ff">void</span> <span style="color:#a31515">Initialize</span>() {
<span style="color:#008000">//...</span>
<span style="color:#0000ff">this</span>.rapidServerEngine.MessageReceived += <span style="color:#0000ff">new</span> ESBasic.CbGeneric<<span style="color:#0000ff">string</span>,ClientType, <span style="color:#0000ff">int</span>, <span style="color:#0000ff">byte</span>[], <span style="color:#0000ff">string</span>>(rapidServerEngine_MessageReceived);
<span style="color:#008000">//...</span>
}
</code></span></span>
客户端发送消息会触发 rapid服务端引擎 上的 MessageReceived 事件,最终程序流程会来到如下图的地方。
根据客户端传递在消息号来匹配对应的 if分支,然后进行对应的处理。
2. 全局缓存
此部分的代码位于
GGTalk/TalkBase/Server/Core/ServerGlobalCache.cs
接着前面修改用户信息的例子:
<span style="color:#333333"><span style="background-color:#ffffff"><code class="language-csharp"><span style="color:#0000ff">if</span> (informationType == <span style="color:#0000ff">this</span>.talkBaseInfoTypes.ChangeMyBaseInfo) {
<span style="color:#008000">//...</span>
<span style="color:#0000ff">this</span>.serverGlobalCache.UpdateUserInfo(sourceUserID, contract.Name, contract.Signature, contract.OrgID);
TUser user = <span style="color:#0000ff">this</span>.serverGlobalCache.GetUser(sourceUserID);
<span style="color:#008000">//...</span>
}
</code></span></span>
消息处理后会来到如上 if分支,其中分别调用了 serverGlobalCache 上的 UpdateUserInfo
和 GetUser
方法,下面是这两个方法的具体实现。
<span style="color:#333333"><span style="background-color:#ffffff"><code class="language-csharp"><span style="color:#008000"><span style="color:#808080">///</span> <span style="color:#808080"><summary></span></span>
<span style="color:#008000"><span style="color:#808080">///</span> 获取目标用户,如果缓存