topfreegames / pitaya

Scalable game server framework with clustering support and client libraries for iOS, Android, Unity and others through the C SDK.
MIT License
2.34k stars 480 forks source link

Concerns about the Global Message Channel 'chLocalProcess' in Pitaya #321

Open f2ngwx opened 1 year ago

f2ngwx commented 1 year ago

In the Pitaya framework, all player messages are ultimately routed to a global channel called 'chLocalProcess.' I'm not quite clear on the reasoning behind this design choice. As it stands, I believe this design could potentially lead to performance issues and impact the overall gameplay experience for players. For instance, if one player experiences latency or freezes, it could affect other players' game processes. In extreme cases, if the default dispatch coroutine is occupied by a single player, causing significant delays, it would essentially render the game unplayable for others.

Would it be possible to shed some light on the rationale behind this design decision? Wouldn't it be more effective to have each player handle their own messages within their respective coroutines for a better gaming experience?

felipejfc commented 1 year ago

The channel is buffered with a configurable buffer size. For one player to block others, it would have to send a number of messages equal to the buffer. I believe the concern is valid but it's also a corner case that we didn't hit yet

f2ngwx commented 1 year ago

"We've encountered this issue before, where online players couldn't send messages in a timely manner due to some reasons. As a result, messages accumulated in the 'chSend' channel, causing one of the goroutines in 'Dispatch' to block, and eventually, all 'Dispatch' goroutines got blocked, leading to the server shutting down. In Pitaya, each agent has its independent channel. Is it possible to process players' messages in these individual channels? This approach has two benefits:

  1. It ensures that players' own messages are ordered.
  2. If there are issues as mentioned above, it won't affect other players' game progress.

I've mainly made the following changes:

  1. In the 'processMessage' function of 'HandlerService,' replace the line 'h.chLocalProcess <- message' with 'h.localProcess(lm.ctx, lm.agent, lm.route, lm.msg).'
    1. Replace the line 'h.chRemoteProcess <- message' with 'h.remoteService.remoteProcess(rm.ctx, nil, rm.agent, rm.route, rm.msg).' In summary, we've removed the 'chRemoteProcess' and 'chLocalProcess' channels."
felipejfc commented 1 year ago

I think what you did isn't going to solve the root cause of the issue. If the local/remote processing takes too long, what will happen is that your stack will blow up because of these calls. You could have achieved the same result by just increasing the size of these channels. I think the proper "fix" here would be to create shards using playerids and sending them to different channels

lyh1091106900 commented 1 year ago

I think it is very dangerous to process the same player's data in parallel, and there must be a mechanism to make the messages on the route execute sequentially, otherwise a lot of data will have to be locked

lyh1091106900 commented 1 year ago

The player's gourutinue should know the signal of the end of the previous message processing and then process the next message

bruce1125 commented 10 months ago

process players' messages in these individual channels?

I think the issue is exist, but I don't think the change you said could solve it completely. Thinking about the scene of two different session from a same UID, while the old one is blocked, the new one will run on a different goroutine that would cause the issue.

So, for me, now I use some mutex logic to prevent it, though I think it is not graceful enough, hopefully pitaya could provide a perfect solution to do it, maybe something like "actor"?