线上bug的解决方案--带来的全新架构设计
缘由
本人从事游戏开发很多年一直都是游戏服务器端开发。
因为个人原因吧,一直在小型公司,或者叫创业型团队工作吧。这样的环境下不得不逼迫我需要什么都会,什么做。
但是自我感觉好像什么都不精通。。。。。
好了好像偏题了!
回归正题
现在公司是做手游开发,java服务器 + U3D做客户端的mmo手游,仿魔兽世界!
做软件的都知道一个蛋疼的事情,那就是线上Bug。但是做服务的人更清楚另一个蛋疼的事情,就是在线更新,不停服更新。
知道的人,想想都蛋疼,当然不知道的,那就只能自己想象了。

线上经常出问题大家都是能理解的。bug肯定是有的。做服务的同僚应该都知道,不到维护的时间是不能停止服务区更新的除非是非常重大的bug。
这里面游戏服务器更为严格,因为你无故维护,维护一次可能就会流失一批玩家。所以这一直是一个梗。
本人经过三个星期的研究和测试,最终发现一个可以解决这种一出现bug,却能在线更新,且不影响性能的触发方式。

通过这样一个方式,主程序,加数据库,通过脚本实现逻辑模块;
这样就有一个脚本的实现形式,脚本如果实现的不好,那么性能消耗就很大了。
我的做法是把逻辑部分的方法抽象出来。放到脚本去实现。通过脚本把实现脚本逻辑代码在注册会逻辑模块。
这样的做法能保证我们有逻辑模块有bug的时候及时的修改逻辑,再次注册脚本已到达热更新效果。保证服务器运行的稳定性。
我们开始吧。
首先我要说一下我这里使用的是C#语言作为讲解。java也是一样的道理。不在赘述,如果需要代码实现的可以留言!这里可能牵涉到我之前的一些文章包含的类容,比如脚本加载器,日志模块,http监听模块。
我们先创建一个控制台项目叫TestApp
在新建一个类库项目 TestApp.Scripts

基本工作已经完成了。
接下来,我们在TestApp下面新建一个类IMainManager
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
/**
*
* @author 失足程序员
* @Blog http://www.cnblogs.com/ty408/
* @mail 492794628@qq.com
* @phone 13882122019
*
*/
namespace TestApp
{
/// <summary>
///
/// </summary>
public interface IMainManagerScript
{
void Test();
}
}
我们在TestApp下面新建一个类MainManager
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
/**
*
* @author 失足程序员
* @Blog http://www.cnblogs.com/ty408/
* @mail 492794628@qq.com
* @phone 13882122019
*
*/
namespace TestApp
{
/// <summary>
///
/// </summary>
public class MainManager : IMainManagerScript
{
public static MainManager instance = new MainManager();
public static MainManager GetInstance()
{
return instance;
}
public IMainManagerScript IScript;
public void Test()
{
IScript.Test();
}
}
}
接下来我们在TestApp.Scripts 新建一个文件
using Net.Sz.Framework.Log;
using Net.Sz.Framework.Script;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
/**
*
* @author 失足程序员
* @Blog http://www.cnblogs.com/ty408/
* @mail 492794628@qq.com
* @phone 13882122019
*
*/
namespace TestApp.Scripts
{
/// <summary>
///
/// </summary>
public class MainManagerScript : BaseScript, IMainManagerScript
{
public void Test()
{
Logger.Info("我是test");
}
public override void InitScript()
{
MainManager.GetInstance().IScript = this;
Logger.Info("MainManagerScripttest InitScript");
}
}
}
using Net.Sz.Framework.Log;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestApp
{
class Program
{
static void Main(string[] args)
{
//Logger.LOGCONSOLE = true;//不在控制台打印信息
//Logger.LOGLEVEL = Logger.ENUM_LOGLEVEL.INFO;//不显示debug消息
Logger.Info("==================Start============================");
Net.Sz.Framework.Script.ScriptManager.GetInstance().LoadCSharpFile(new string[] { "../../../TestApp.Scripts/" });
MainManager.GetInstance().Test();
Logger.Info("==================End============================");
Console.ReadLine();
}
}
}
我们先尝试运行一次

也许上面的打印太乱,我们看看简洁版本的

上面我们看样看出来,功能是没有问题的。
如果你稍微注意了,或者看过我之前的文章的话,会发现我的这个脚本没有实现IBaseScript接口,而只继承了BaseScript抽象类。因为这样的脚本不需要放到脚本存储器里面,只需要执行init函数,把脚本自身反注册到主程序函数体里面!
现在就是牵涉更新的事情。
更新有一个问题,当服务一旦部署后需要更新那就是的再次执行加载脚本方法。如果你使用windows服务运行的,更新势必是一个问题。
这里我只介绍一种方式,http监听方式。
要开启http监听方式,需要一个Net.Sz.Framework.Netty.Http.IHttpHandler的实现类
using Net.Sz.Framework.Log;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
/**
*
* @author 失足程序员
* @Blog http://www.cnblogs.com/ty408/
* @mail 492794628@qq.com
* @phone 13882122019
*
*/
namespace TestApp
{
/// <summary>
///
/// </summary>
public class ReloadScriptHandler : Net.Sz.Framework.Netty.Http.IHttpHandler
{
public void Action(Net.Sz.Framework.Netty.Http.HttpSession session, string method, string bindpath, Dictionary<string, string> parms)
{
Logger.Info("收到请求");
Net.Sz.Framework.Script.ScriptManager.GetInstance().LoadCSharpFile(new string[] { "../../../TestApp.Scripts/" });
MainManager.GetInstance().Test();
session.writeSuccess();
session.AddBodyLine("OK");
session.WriteFlush();
}
}
}
接下来我们在主函数加入下面代码
Dictionary<string, Net.Sz.Framework.Netty.Http.IHttpHandler> handlers = new Dictionary<string, IHttpHandler>();
handlers.Add("ReloadScript", new ReloadScriptHandler());//开启对http监听,监听模块为 ReloadScript
Net.Sz.Framework.Netty.NettyPool.GetInstance().AddHttpBind(, handlers);
运行起来,看看,

可以看出,开启了http监听,reloadscript
然后我们修改一下MainManagerScript文件的Test方法
public void Test()
{
Logger.Info("我是test 修改过的版本");
}
在浏览器输入:http://127.0.0.1:9527/reloadscript

运行时成功的。这样的架构方式,很适合的是游戏开发,某些功能块很容易出bug,如果用脚本存储器访问比较耗费性能。
这样反向注册功能块脚本到功能块,既能实现bug的热更新,也不会影响性能消耗。
如果有疑问可以留言哦。如果你觉得这纯粹是扯淡,也欢迎留言。 不要问我,逻辑部分都是源码方服务器上安全吗?难道你打包就安全了?反编译,脱壳反混淆的工具一大堆。

上面是C#版本的,如果想要源码,
或者是java源码的,可以留言哦~!
线上bug的解决方案--带来的全新架构设计的更多相关文章
- 线上bug分析
昨天下午大神把组内几十号人召集在一起开Online bug分析大会,主要是针对近期线上事故从事故原因和解决方案两个维度来分析. 对金融软件来说,每一次的线上事故都有可能给公司带来重大的损失,少扣了用户 ...
- 「日常开发」记一次因使用Date引起的线上BUG处理
生活中,我们需要掌控自己的时间,减少加班,提高效率:日常开发中,我们需要操作时间API,保证效率.安全.稳定.现在都2020年了,了解如何在JDK8及以后的版本中更好地操控时间就很有必要,尤其是一次线 ...
- 记一次线上bug排查-quartz线程调度相关
记一次线上bug排查,与各位共同探讨. 概述:使用quartz做的定时任务,正式生产环境有个任务延迟了1小时之久才触发.在这一小时里各种排查找不出问题,直到延迟时间结束了,该任务才珊珊触发.原因主要就 ...
- 线上bug或故障界定及填写规范
[线上故障与线上Bug界定] 一.线上故障: 1. 故障参照公司规范稍做调整: a) 1级故障:资讯首页或主App首页无法打开:多条业务线同时不可用:超过15分钟: b) ...
- 关于线上bug
之所以想写下线上bug,因为发觉有些公司对线上bug的处理是比较严格甚至是很苛刻,涉及到的相关人可能会因此而背黑锅. 之所以会存在这样情况,因为公司各部门都有关联,特别是用户.老板的投诉,也给公司会造 ...
- 程序员如何描述清楚线上bug
案例 一个管理后台的bug,把操作记录中的操作员姓名,写成了该操作员的id.原因是修改了一个返回操作人姓名的函数,返回了操作人的id.但是还有其他地方也用这个函数,导致其他地方把姓名字段填写成了操作员 ...
- 听说”双11”是这么解决线上bug的
听说"双11"是这么解决线上bug的 --Android线上热修复的使用与原理 预备知识和开发环境 Android NDK编程 AndFix浅析 Android线上热修复的原理大同 ...
- 记录一次线上bug
记录一次线上bug,总的来说就是弱网和重复点击.特殊值校验的问题. 测试场景一: 在3g网络或者使页面加载速度需要两秒左右的时候,输入学号,提交学生的缴费项目,提交完一个 学生的缴费后, ...
- 线上BUG:MySQL死锁分析实战
原文链接:线上BUG:MySQL死锁分析实战 1 线上告警 我们不需要关注截图中得其他信息,只要能看到打印得org.springframework.dao.DeadlockLoserDataAcces ...
随机推荐
- css中的浮动与三种清除浮动的方法
说到浮动之前,先说一下CSS中margin属性的两种特殊现象 1, 外边距的合并现象: 如果两个div上下排序,给上面一个div设置margin-bottom,给下面一个div设置margin-top ...
- JAVA 分页工具类及其使用
Pager.java package pers.kangxu.datautils.common; import java.io.Serializable; import java.util.List; ...
- 如何理解javaSript中函数的参数是按值传递
本文是我基于红宝书<Javascript高级程序设计>中的第四章,4.1.3传递参数小节P70,进一步理解javaSript中函数的参数,当传递的参数是对象时的传递方式. (结合资料的个人 ...
- Maven仓库搭建和配置
maven在本地搭建仓库的实际需求maven在项目构建过程需要下载一些必要的软件包,这些默认的下载链接都是访问maven的远程中央仓库Central Repo.如果项目中的成员,每次第一次构建的时候都 ...
- ORACLE从共享池删除指定SQL的执行计划
Oracle 11g在DBMS_SHARED_POOL包中引入了一个名为PURGE的新存储过程,用于从对象库缓存中刷新特定对象,例如游标,包,序列,触发器等.也就是说可以删除.清理特定SQL的执行计划 ...
- sqlserver批量修改首字母为大写
'hello world' ----> 'Hello world' update tableName set columnName=CHAR(ASCII(SUBSTRING(columnN ...
- Linux下编译安装Vim8.0
什么是Vim? Vim 是经典的 UNIX 编辑器 Vi 的深度改良版本.它增加了许多功能,包括:多级撤销.格式高亮.命令行历史.在线帮助.拼写检查.文件名补完.块操作.脚本支持,等等.除了字符界面版 ...
- Centos 7.0 安装Mono 3.4 和 Jexus 5.6
2013-07-26 写过一篇<CentOS 6.3下 安装 Mono 3.2 和Jexus 5.4>,CentOS 7在CentOS 6的基础上有很大的调整,本文是这篇文章的更新,主要介 ...
- 让ASP.NET5在Jexus上飞呀飞
就在最近一段时间,“Visual Studio 2015 CTP 5”(以下简称CTP5)发布了,CTP5的发布不仅标志着新一代的VisualStudio正式发布又向前迈出了一步,还标志着距离ASP. ...
- 【完全开源】知乎日报UWP版(上篇):界面设计、官方API分析
目录 说明 使用Fiddler分析android版API 部分效果图 关于源码 说明 在做博客园UWP版的时候其实就有做知乎日报的打算了,前段时间一直出差,在酒店里用Fiddler简单的分析了一下An ...