框架设计的局部与整体
second60 20180417
1. 例子引出
在框架设计中,很多总和分的问题需要处理,即局部与整体的问题。所以要有很好的扩展性。是框架设计中的重点之一。
举个例子
1.1 初始需求
棋牌初始产品需求,玩家能获取自已的某个游戏GAME 1中的房间。游戏在单进程中。
最简单的设计
A程序设计了一个接口:get_user_game_room()
这对单个进程是完全没有问题的,但并没有任何扩展性
1.2 改进需求
产品要求添加多一个新游戏GAME2
A程序又在原有接品中添加了个参数:
get_user_game_room_by_gameid(int gameid)
设计分析:这样设计是可以支持多子游戏,但前提是客户端必须传参数gameid过来,
1.3 升级需求
产品要求不用知道是什么游戏,获得游戏中所有的房间
A程序又开始写代码了,让客户端遍历两个子游戏,分别请求并获得两个游戏的玩家房间,再拼起来。
问题来了,上面的设计是不合理的,原因如下:
a) 客户端不知道有多少个游戏,假如到时添加很多个游戏怎么支持
b) 客户端不可能通过遍历的方式去循环请求接口
c) 客户端是轻逻辑实现,只想一个接口做到所有的事情
分析:
上面的设计完全是开发人员根据当前的需求做的实现,只能支持当时的需求。并无扩展性可言。
2. 设计思路
2.1 通用性
因为是棋牌项目,所以多子游戏是肯定的,后面还可能会多地区。所以设计功能时,每个接口要考虑下多子游戏和多地区的情况。
接口具有通用性:无论怎么怎么变更需求,接口定好后通用,不能随便改变
a) 初始需求中,获取自已房间列表,要支持多子游戏获取房间列表,
b) 获取玩家所有子游戏房间列表的情况,虽然需求没有给出,但应该支持。
初步框架图:
2.2 扩展性
接口具有扩展性的,给出客户端后,是不能随便修改的。
a) 此接口当一个公共接口,统一入,统一出。
参考:get_user_game_room(int optye, map<string,string> params);
optype为类型,0为所有,1为单游戏ID,2为多游戏ID
params为参数
2.3 整体与局部
接口设计好了,但后端怎么样来支持多子游戏和多地区呢?
a) 对于多子游戏是一个“分”的过程,即局部的过程,所以要有一个“总”的地方。而在原来的设计中并没有总的一个地方,都是分散在各个进程中。
b) 总是一个存储数据的地方,可以把数据放到redis缓存中,查房间的信息,只需要去redis中查找即可
c) 同时接口不用定义到所有的”分进程中”,在一个通用服务中去redis中读取即可。
d) 在通用进程中定义通用接口,供客户端调用,通用进程去redis中查找即可
2.4 可复制性
以后要添加类似的通用性接口,也只需在通用过时程中添加即可。
3优点
1. 接口具有较好的通用性,以后无论是添加多游戏,还是多地区,都无须在分进程中写接口,”分”进程只需同步数据到”总”的redis中即可
2. 接口扩展性,无论是获取所有玩家房间,单个游戏房间,多个游戏房间,或其他房间的过滤需求,都是可以的
3. 可复制性,后面要添加一个类似的通用接口,只需用同样的设计方法实现即可
4 缺点
4.1 保证数据一致性
分和总之间的同步,局部与整体间的同步要规划好
a) 可以把数据都放在“总”里,“分”里是无状态的,“分”中要取数据,从“总”中读取即可。
b) 对于上面程序A的设计,是完全没有数据一致性的,数据都是放在不同进程中,所以取数据不方便,同时也不能保证数据的一致性
4.2 单点问题
a) 通用进程,如果是只有一个,那么通用进程如果出现问题,那么此功能将会不可使用,所以可以让通用进程采用集群的方式,布署多个
b) 上面的“总”redis也同样,单个如果出问题将会不可功能不可用,开启redis的集群即可
4.3 通用进程
通用进程会加大代码的工作量,但会减少多进程排查问题和后面可扩展的问题,所以前期工作量会大些,但后期开发时间将会大大减少
5 总结
这里主要用过例子,引出一个设计中整体与局部,扩展和通用性的问题,例子比较简单,但很多地方都可以用到,当然很多写的不细致的地方,欢迎大家吐槽。