构建 ActionScript游戏服务器,支持超过 15000并发连接
Building an ActionScript Game Server with over 15,000 Concurrent Connections
Renaun Erickson
1
Basic MMO Game Architecture
• Clients• Servers• Databases• Networking
2
MMO Network Considerations
• Protocols (TCP, UDP, HTTP)• Firewalls• Latency• Packet Size• Data Schema
3
Have to be able to create large number of connections that can
send packets at a reasonable rate and bandwidth
4
Socket Implementations
• Check each file descriptor each frame– Select, poll
• Slow for large number of connections• OS Optimized
– Epoll, kqueue, /dev/poll, pollset, I/O Completion Ports
• OS specific fast implementations• Event based libraries
– Libevent and libev• Fast for large number of connections• Portable code, hides OS specific implementations
5
Server Configuration
• Tell OS to allow large number of file descriptors
• Tell OS how much ram for each file descriptor
• Tell OS buffer sizes for network protocols• Tell OS what ports range to use, only 65k
ports per IP
6
Flash on the Client and Server
• Many MMOs in China use Flash as the Client
• Server naturally has MMO game logic• Put game logic on server for security• Many benefits of using the same
language on client and server
Is ActionScript on the server possible?
7
ActionScript on the Server
• Flash Player Dissected– Core – VM, Primitives, ActionScript syntax– APIs – C/C++ classes implementing rich Flash
Player API and features
• Tamarin– Open sourced core parts of the Flash Player– No rich API or features, you have to write
them yourself
8
Tamarin Projects
• Thane (part of Whirled SDK by ThreeRings)– http://wiki.whirled.com/Whirled_SDK
• Redtamarin (by zwetan and others)– http://code.google.com/p/redtamarin/
• PushButton Engines Network component by Ben Garney– https://github.com/PushButtonLabs/
PBNetworking
9
Case Study: SpellTraction
10Design By: Garth Braithwaite http://www.garthdb.com/ @garthdb
Live Demo and Source Code
• http://renaun.com/serveras/test• http://renaun.com/serveras/spelltraction/• https://github.com/renaun/
ActionScriptGameServerExamples
11
Server Setup
• Game Server– Amazon EC2 Medium Server– 64 bit Ubuntu OS– Running two game instances
• Main• Load Test
• Load Test Server– Amazon EC2 Medium Server– Custom test scripts
12
Server Code
• Redtamarin– Created ServerSocket.as – libev socket
implementation– Compile ActionScript files into ActionScript
Byte Code (abc files)– Command line redtamarin shell runs the abc
files
13
Server ActionScript Code
14
function loopHandler():void{
if (!ss.listening)ss.listen("10.111.33.190", 12122);
elseserverBrain.beat(); // Game Tick
}
var serverDispatcher:SocketServerNerveDispatcher = new SocketServerNerveDispatcher();
var serverBrain:ServerBrain = new ServerBrain();var serverNerve:ServerNerveSystem
= new ServerNerveSystem(serverBrain, serverDispatcher);serverBrain.addNerve(serverNerve);var ss:ServerSocket
= serverDispatcher.createServerSocket(serverNerve);ss.loop.add(loopHandler);ss.start(250);
Libev Socket Implementation
15
bool ServerSocketObject::_listen(Stringp host, const int port){ struct socket_io w_accept; StUTF8String hostUTF8(host); const char* hostAddr = hostUTF8.c_str(); if( (w_accept.fd = socket(PF_INET, SOCK_STREAM, 0)) < 0 ) return false; int flags = fcntl(w_accept.fd, F_GETFL, 0); fcntl(w_accept.fd, F_SETFL, (flags > 0 ? flags : 0) | O_NONBLOCK); sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr(hostAddr); addr.sin_port = htons(port); int status = bind(w_accept.fd, reinterpret_cast<struct sockaddr *>(&addr), sizeof(addr)); if (status != 0) return false; _socket = w_accept.fd; if (listen(w_accept.fd, 2) < 0) return false; w_accept.socketObject = this;
// Initialize and start a watcher to accepts client requests ev_io_init(&w_accept.io, accept_cb, w_accept.fd, EV_READ); ev_io_start(loop_ev, &w_accept.io); ev_loop(loop_ev, 0); return true;}
Linux Kernel Configurations
16
/etc/sysctl.confnet.core.rmem_max = 33554432net.core.wmem_max = 33554432net.core.rmem_default = 1048576net.core.wmem_default = 1048576net.core.optmem_max = 33554432net.ipv4.tcp_rmem = 4096 4096 33554432net.ipv4.tcp_wmem = 4096 4096 33554432net.ipv4.tcp_mem = 786432 1048576 26777216net.ipv4.tcp_max_tw_buckets = 360000net.core.netdev_max_backlog = 30000net.ipv4.ip_local_port_range = 2048 65535net.ipv4.tcp_window_scaling = 1net.ipv4.tcp_no_metrics_save = 1net.core.somaxconn = 131072fs.file-max = 131072
/usr/include/linux/limits.hNR_OPEN = 65536
/etc/security/limits.conf* soft nofile 65535* hard nofile 65535
17
Client Code
Client
Server
Shared Code
18
http://github.com/renaun
@renaun
http://renaun.com/blog
Q / A