my network server engine has this architecture and has 3 main threads: SocketServerThread, ScheduledThread, GameServerThread. Game data is stored into DB, so there are other threads for DB connections (using a connectionPool)
-SocketServerThread manages all I/O data and new connections. When this thread receives data, it build a "input" message like (lenght:short, code:int, data:bytes) and send it to a shared structure: inputPriorityQueue. SocketServerThread produces "input" message and the only one that consume "outputMessage"
ScheduledThread manages specific scheduled events (game logic events and general server events) These events aren't generated by players inputs/actions, but usually by interal Cron jobs or scheduler. Example of these events are Monster AI, or player logout per x seconds inactivity. This thread can generate "input" message too, and put them in the "inputPriorityQueue" (processed by GameServerThread) or output messages, processed by SocketServerThread.
Then Another thread, GameServerThread, read "messages" from inputPriorityQueue, process them, update game server status and produces messages in the outputPriorityQueue.
SocketServerThread every 35ms reads all message it could read from "outputPriorityQueue" in a fixed maximum interval (for example 20ms), then for the other 15ms it is free to manage socket new connections and socket new incoming data.
SocketServerThread Appends all socket avaible data into the Client buffer data, and checks this client buffer data for composing all "input" message it cans.
SocketServerThread is the only one who can consume outputPriorityQueue message.
The queues(input and output) are Priorityqueue, so i can manage message processing order.. for example, a server message like: "Server will be restarted in 30 seconds" could have a higher priority and processed immediatly.