SNS Webgame 社区类页面网游开发, 自己所用的架构,以及遇到的一些问题和困惑
大家好,我第一次做服务器的程序,之前我一直做手机客户端,什么WEB框架啥的都没用过 ,遇到很多困难跟疑惑,请大家多多指教。
目前在做的一个社区页面网游,HTML页面,非FLASH的,所有的交互都是基于HTTP的。
这个游戏的逻辑比较常见,类似于SLG,玩家消耗时间采集资源(比如点一个按钮,等5分钟就可以采集了10个粮食),随后制造了5个士兵,接着玩家之间可以进行PK,双方损失N个士兵等等.
同时具有社区的常见功能,玩家之间也可以互相加好友,留言等等。 但是除了管理员,普通用户没有广播的功能。也没有专门的聊天频道。
这个系统的特点是:
1. 用户数可能会很多, 可能会有上百万在线(至少所用的架构要能扩展到支持那么多),并且不分区,大家都在同一个区。
也就是, 所有的玩家,都可以通过用户名查询到另外一个玩家的信息,然后可以加好友或者PK。
2. PV量很大,并且数据库操作频繁,玩家的每个点击,都可能生成新的对象.比如生成几个士兵,跟别人进行一场PK,会产生一条PK记录。
我现在的设计是
浏览器 ----> LOAD BALANCE -----> 动态页面服务器 TOMCAT集群 -----> Logic server -----> DB server
前端, 静态的图片,CSS什么的,都可以交给 NGIX
动态页面服务器,用JSP,可以用 N台 TOMCAT 集群
后端, 逻辑服务器 Logic server
数据库 DB server , 一台MYSQL
困惑之一: 页面服务器与逻辑服务器的通信问题
我现在的做法是,N台 TOMCAT 通过SOCKET 连接到 逻辑服务器, 然后发送自定义的消息格式;逻辑服务器用一个线程维护消息队列,然后逻辑服务器开启一个线程,不停地处理消息,并把结果返回对应的页面服务器。
然后页面服务器把逻辑服务器返回的结果,翻译成HTML返回给玩家
页面服务器
//
static Integer msgId = 0;
List<MyMsg> msgQueue = Collections.synchronizedList(new LinkedList());
HashMap<Integer, MyMsg> resultMap = new HashMap<Integer, MyMsg>();
public String requestHandler(HttpServletRequest hsr) {
// 一些检查
// 根据 request 生成 msg
MyMsg msg = new MyMsg();
synchronized (msgId) {
msg.setId(msgId++);
}
msg.startTime = System.currentTimeMillis();
msgQueue.add(msg);
while (resultMap.get(msg.getMsgId()) == null) {
Thread.yield();
if (System.currentTimeMillis() > msg.startTime + 10000) {
break; // 超过 10 秒没响应, 算超时
}
}
MyMsg result = resultMap.get(msg.getMsgId());
resultMap.remove(result);
if (result != null) {
return "翻译result";
} else {
return "返回超时错误";
}
}
// 接收消息 , 逻辑服务器收到 MyMsg, 处理后, 会返回一个同样 msgId 的MyMsg 给页面服务器, 页面服务器直接保存
public void onReceiveMsg(MyMsg msg){
if (System.currentTimeMillis() > msg.startTime + 10000) {
return; // 超过 10 秒才回来, 直接丢弃
}
resultMap.put(msg.getMsgId(), msg);
}
请问这样的设计,有没有问题? 很多线程在等待自己的结果的时候,会不会造成服务器出问题;
自己写这些,总感觉有些不可靠, 有没有现成的 服务器间通信框架,以及 消息队列什么的可以直接用的?
逻辑服务器中:
把所有收到的消息都加入到队列里面,然后进行 串行处理。 这样就省得同步什么的了。
但这种做法,会不会造成效率损失?
一般大家做 逻辑服务器与页面服务器的通信是怎么做的?
困惑之二
逻辑服务器上的数据库缓存问题, 因为数据库操作非常频繁,所以肯定需要缓存。
我现在的做法是
逻辑服务器起三个线程, 一个负责逻辑处理以及数据管理, 一个负责数据库读取, 一个负责数据库更新。 我没有用 hibernate , 直接用的JDBC。
比如玩家登陆
页面服务器创建玩家登陆消息 -> 逻辑服务器 -> DB读取线程读取数据 -> 读取到的数据,放入 数据管理进程 -> 返回玩家的信息给 页面服务器
然后数据管理线程,定时遍历 所有的账户数据(一个列表),判断该账户是不是有更新,如果有更新, 则放到DB更新线程去更新数据库。
我用的判断数据是不是有更新的方法是,
在该 object 上次被更新到数据库以后,就生成一个 saved = object.clone(), 把所有的成员对象都 clone一遍,
然后比较 当前object 与 saved 的所有成员, 看是否完全一致, 不一致,则说明有更新, 需要放到 数据库更新线程去更新。
现在这种做法,
1.我感觉很麻烦, 所有的entity,都要写 clone 方法 以及 saved与当前对象判断更新的方法,
2.非常担心的就是一旦服务器突然出故障退出, 则可能会有很多账户的数据是过期的。只能靠日志慢慢恢复。
3.所有的数据以及逻辑都放在一台电脑上, 如果用户数达到几十上百万以后, 会不会性能上有问题。
我后来看了一些数据库缓存的资料,比如memcache, redis ,都是类似于 hashMap 的功能, 好像是为了处理分布式系统,我的逻辑这块,完全就在一台机器上,所以我也不太懂怎么把这些缓存的工具应用到现在的系统中。
请大家多多指教。