Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multi proxying #11

Open
PedroMPagani opened this issue Aug 9, 2022 · 36 comments
Open

Multi proxying #11

PedroMPagani opened this issue Aug 9, 2022 · 36 comments

Comments

@PedroMPagani
Copy link

Is there a redis platform support already in AjQueue, if not, would you mind if I implemented it?

@ajgeiss0702
Copy link
Owner

ajgeiss0702 commented Aug 9, 2022

There is not, feel free.

If you plan on making a PR, make sure to target the dev branch, and also ensure that if redis is not enabled, then the functionality will not be effected.

Also, if you do implement redis, please make sure all the features that might be effected still work (stayqueued, and probably other things I can’t think of off the top of my head)

Feel free to contact me on discord if you need help with anything :)

@Folas1337
Copy link

Is there a redis platform support already in AjQueue, if not, would you mind if I implemented it?

Just want to show my interest in this feature too, seems to be a rather old issue but perhaps a little attention can't hurt.

@ajgeiss0702
Copy link
Owner

Is there a redis platform support already in AjQueue, if not, would you mind if I implemented it?

Just want to show my interest in this feature too, seems to be a rather old issue but perhaps a little attention can't hurt.

There is not. I assumed the author of the issue intended to make it and do a PR on it, but I have not heard anything.

My time to work on plugins is very limited so I am not able to do this myself currently

@Folas1337
Copy link

Is there a redis platform support already in AjQueue, if not, would you mind if I implemented it?

Just want to show my interest in this feature too, seems to be a rather old issue but perhaps a little attention can't hurt.

There is not. I assumed the author of the issue intended to make it and do a PR on it, but I have not heard anything.

My time to work on plugins is very limited so I am not able to do this myself currently

Oh yeah i had the very same understanding, don't worry. I'm also contacting some people who might perhaps be willing to implement it when I pay them a little bit :)

Hopefully it'll come true one day.

@PedroMPagani
Copy link
Author

I've been busy at work, I'll do it little by little whenever I have some free time

@PedroMPagani
Copy link
Author

Having this with a Redis system also kind of gives the sense of a need of a master controller, otherwise the queues would be trying to send the user to a server in a proxy he isn't connected to, which makes it also require a system where the master could be transfered ownership to another instance if a crash or pings are ignored.

That's why this system is so sensitive, and that's why I haven't really deeply considered writing this.

  1. Easy and efficient, concurrency-safe would be having 1 application dedicated to handle the queues.

  2. To write something like a master-etc node would require the proxies to be able to take ownership in case a failover happens over the current master.

This requires some type of level experience I have in DonutSMP, since it looks even more interesting to write it I'll give it a start today, will push progress here.

@ajgeiss0702 would you be willing to create a branch for it? so maybe some other users or devs would also be willing to contribute.

@Folas1337
Copy link

Having this with a Redis system also kind of gives the sense of a need of a master controller, otherwise the queues would be trying to send the user to a server in a proxy he isn't connected to, which makes it also require a system where the master could be transfered ownership to another instance if a crash or pings are ignored.

That's why this system is so sensitive, and that's why I haven't really deeply considered writing this.

  1. Easy and efficient, concurrency-safe would be having 1 application dedicated to handle the queues.

  2. To write something like a master-etc node would require the proxies to be able to take ownership in case a failover happens over the current master.

This requires some type of level experience I have in DonutSMP, since it looks even more interesting to write it I'll give it a start today, will push progress here.

@ajgeiss0702 would you be willing to create a branch for it? so maybe some other users or devs would also be willing to contribute.

Just for my own understanding, why the need for this master controller? I think the part where you said "trying to send the user to a server in a proxy he isn't connected to" is where you lost me 😅

@Folas1337
Copy link

Also maybe this source of information could be useful: https://blog.martinl.dev/posts/queue-plugin/

I've found it while I was desperately searching for a solution but couldn't find one.

@PedroMPagani
Copy link
Author

PedroMPagani commented Nov 11, 2022

Also maybe this source of information could be useful: https://blog.martinl.dev/posts/queue-plugin/

I've found it while I was desperately searching for a solution but couldn't find one.

I like this blog and it even gives me the idea to create my own to post my crazy stuff.

The main problem with his idea and design is that it uses the memory storage from redis mainly, it is more than a good idea, but it also causes many issues too.

About race conditions etc, the main reason of having AjQueue is to have a queue right, if you don't have a master the queue wouldn't be central thingy, instead each proxy would be ticking queues and the queue could reach 3x it's speed of what the user really wants.

The solution for that would be:

  1. Have it so 1 proxy is the master and ticks and runs the queue, the others are just there as slaves. (Concept Master-Slave)

Where slave would be a safe "cache", if the master goes down or stop responding to pings one of the slaves take over the queue, that's why a master system.

  1. Multi Proxying isn't only about the proxy control, you have to sync all of it, glist,
    All the users online, sending users to other instances, all of that.

  2. His design bases itself using redis store in memory, that's gonna use a lot more bandwidth even tho private, because he's gonna be pulling data from redis all the time, instead a best solution is to use pubsubs and store the data in memory on the proxies.

  3. My design is also not the best one, the best desing would be so all the proxies are just slaves, and there would be another application like Paper running on the backend ticking processing and sharing whatever it has to share.

The worry in relation to threads on deadlock isn't a worry on this, as well as it wouldn't on the proxies, since you would be using the pubsubs daemon threads and workers, never really directly interfering in the threads of the events directly.

Another reason to have a master is in case of servers full.

@PedroMPagani
Copy link
Author

Also maybe this source of information could be useful: https://blog.martinl.dev/posts/queue-plugin/

I've found it while I was desperately searching for a solution but couldn't find one.

I like this blog and it even gives me the idea to create my own to post my crazy stuff.

The main problem with his idea and design is that it uses the memory storage from redis mainly, it is more than a good idea, but it also causes many issues too.

About race conditions etc, the main reason of having AjQueue is to have a queue right, if you don't have a master the queue wouldn't be central thingy, instead each proxy would be ticking queues and the queue could reach 3x it's speed of what the user really wants.

The solution for that would be:

  1. Have it so 1 proxy is the master and ticks and runs the queue, the others are just there as slaves. (Concept Master-Slave)

Where slave would be a safe "cache", if the master goes down or stop responding to pings one of the slaves take over the queue, that's why a master system.

  1. Multi Proxying isn't only about the proxy control, you have to sync all of it, glist,
    All the users online, sending users to other instances, all of that.

  2. His design bases itself using redis store in memory, that's gonna use a lot more bandwidth even tho private, because he's gonna be pulling data from redis all the time, instead a best solution is to use pubsubs and store the data in memory on the proxies.

  3. My design is also not the best one, the best desing would be so all the proxies are just slaves, and there would be another application like Paper running on the backend ticking processing and sharing whatever it has to share.

The worry in relation to threads on deadlock isn't a worry on this, as well as it wouldn't on the proxies, since you would be using the pubsubs daemon threads and workers, never really directly interfering in the threads of the events directly.

Another reason to have a master is in case of servers full.

When servers are full they might not exactly be full in the proxy itself, but server side they would, that's why having a master is good, you need to keep track for the glist as well, so you don't keep overloading the auth threads on the paper side, when knowing the user can't join.

Another relation to multi Proxying is that there should be a safe mechanism blocking players from joining multiple proxies at the same time, because dupes can be done that way, specially if you're multi instancing your game modes, even tho AjQueue isn't responsible for the security of the proxies, adding this should be a must, since most people that multi proxy are starters usually and have no experience on what could happen.

This experience I bring from DonutSMP backend, because we had many issues related to it.

@ajgeiss0702
Copy link
Owner

ajgeiss0702 commented Nov 11, 2022

My understanding is that a proxy can connect a player to any of the servers, so I was assuming that if the first player in the queue isn’t connected to the proxy that’s running it, don’t send them. (Only the proxy that the player is connected to should send them, then remove them from the queue). This would eliminate the issue of needing a “master”

Obviously I don’t have much experience with multi-proxy setups, or even redis, so any input would be appreciated.

And I will definitely make a branch if there’s going to be multiple people contributing to this.

@Folas1337
Copy link

The only thing I can hopefully contribute as I've tried it before is that to my knowledge when using RedisBungee it prevents a player from joining two different proxies at once.

Should at least eliminate that issue I hope.

@PedroMPagani
Copy link
Author

PedroMPagani commented Nov 11, 2022

My understanding is that a proxy can connect a player to any of the servers, so I was assuming that if the first player in the queue isn’t connected to the proxy that’s running it, don’t send them. (Only the proxy that the player is connected to should send them, then remove them from the queue). This would eliminate the issue of needing a “master”

Obviously I don’t have much experience with multi-proxy setups, or even redis, so any input would be appreciated.

And I will definitely make a branch if there’s going to be multiple people contributing to this.

Yeah you have a good point, the thing is is let's say the user wants to make the queue run 1 player a second, if you don't control all the proxies you'd have like 3. That's why the need of a master, so the master would tick everyone in the queue, and whoever is joining servers would get sent properly.

User tick -> move queue -> user chosen -> dispatch send to proxies -> find user -> send to server.

@ajgeiss0702
Copy link
Owner

My understanding is that a proxy can connect a player to any of the servers, so I was assuming that if the first player in the queue isn’t connected to the proxy that’s running it, don’t send them. (Only the proxy that the player is connected to should send them, then remove them from the queue). This would eliminate the issue of needing a “master”
Obviously I don’t have much experience with multi-proxy setups, or even redis, so any input would be appreciated.
And I will definitely make a branch if there’s going to be multiple people contributing to this.

Yeah you have a good point, the thing is is let's say the user wants to make the queue run 1 player a second, if you don't control all the proxies you'd have like 3. That's why the need of a master, so the master would tick everyone in the queue, and whoever is joining servers would get sent properly.

User tick -> move queue -> user chosen -> dispatch send to proxies -> find user -> send to server.

Yes, but the proxy would skip sending players if the player at the front of the queue isn’t connected. So only the proxy that the player at the front is connected to will send them. Then it removed them from the queue, and the next time, it the player isn’t connected to that proxy, then it does nothing and allows the proxy that has that player to send them.

There would also be the issue of a player in the queue that is completely offline. This could probably be accounted for by having some metadata saying which proxy the player is connected to. If the player is at the front of the queue and they aren’t in the proxy they’re supposed to be, use the current logic for that (remove them from the queue and move on to the next player)

@Folas1337
Copy link

Folas1337 commented Nov 12, 2022

I'm sorry of I'm the only person on earth not understanding the whole discussion but what exactly is the problem of the solution from the blog I posted?

I'm not a programmer, so excuse me for any misunderstandings. I'm just trying to make my small brain understand on a high level.
You have a list on redis, when someone joins you add them to the list with the same logic ajQueue already uses. When people are supposed to be sent once every second, you read the list prior and send people with the same logic ajQueue already uses to send and that's it. If someone disconnects they'll be removed from the queue.

One person should never be able to be connected to two proxies thanks to redisbungee and if the proxy tries sending someone who wasn't connected anymore, they remove them from the list and wait for the next time to send someone.

Also if player A is the next one and they're no longer connected to proxy A, any other proxy would have nothing to do but wait.

If for whatever reason player A was on a proxy that went down unexpectedly and they were then connected to another proxy, I'd say it's fair if they keep their position in the queue as long as they aren't up next (and thus be deleted from the list if they aren't connected anymore).

Any flaws in this system that I overlooked? Cause I do agree that I possibly oversimplify things.

@PedroMPagani
Copy link
Author

The problem is that ajqueue is 1 queue, in multi proxy the queue would be 3 tasks, instead of 1, making it 3x faster than what the user may like

@Folas1337
Copy link

The problem is that ajqueue is 1 queue, in multi proxy the queue would be 3 tasks, instead of 1, making it 3x faster than what the user may like

Oh I see where you're coming from now but I wouldn't personally mind that too much. All 3 proxies would try and send in parallel every second and thus the waiting time shouldn't be increased too drastically. Also the extra resources are probably negligible in my opinion.

Sure, you can try to solve a problem that I as an end user wouldn't mind but you could also go the quick way first and then think of redoing it and solving this minor problem.

I'll make this up to you in the end, just giving my feedback on the matter :)

@ajgeiss0702
Copy link
Owner

The problem is that ajqueue is 1 queue, in multi proxy the queue would be 3 tasks, instead of 1, making it 3x faster than what the user may like

No, it wouldn’t. Not if we just make the change I suggested. If only the proxy that has the player sends the player, then only that server would send them. The others would wait and only send the player in that queue if they have the player

Of course there is the possibility of the queue send intervals not being synced, but that will most likely not be a huge deal. We could probably have them sync to be fairly close using redis, but I’m not sure that would be worth the number of requests that would take.

@PedroMPagani
Copy link
Author

Having the queue only ticking the users from each proxy doesn't really sounds like that bad of a thing, i think we'll stick to that instead of having the master ticking, we might sync the intervals later somehow.w

@PedroMPagani
Copy link
Author

@ajgeiss0702 can I contact you in discord? I have something to send you and I think it would also be a good opportunity on optimizations for ajQueue, i really need your help on this.

I'll drop my personal discord here Pedro Pagani#9082

@Folas1337
Copy link

Is anything happening regarding this at all? No expecting AJ to be doing anything but I was under the impression that Pedro was totally willing to do this and then suddenly I heard nothing about it anymore?

Otherwise I might go ahead and try and fine more people that would perhaps be willing to take this on...

@ajgeiss0702
Copy link
Owner

Is anything happening regarding this at all? No expecting AJ to be doing anything but I was under the impression that Pedro was totally willing to do this and then suddenly I heard nothing about it anymore?

Otherwise I might go ahead and try and fine more people that would perhaps be willing to take this on...

As far as I know there's not anything going on with this. Its something I want to do eventually, but I don't have a ton of time for this currently, so it would be nice if someone else was able to implement this.

@PedroMPagani
Copy link
Author

don't have time to invest on this anymore, maybe in the future.

@ajgeiss0702
Copy link
Owner

If anyone reading this wants to start implementing this and would like some pointers on what they would need to do, or ask questions about implementing it, feel free to contact me on discord

@ajgeiss0702
Copy link
Owner

ajgeiss0702 commented Oct 14, 2023

I’ve made a step that will allow you to implement it yourself. You can now implement a QueueHolder that stores players in the queue. It’s not really documented atm, but you can check out the default implementation: https://github.com/ajgeiss0702/ajQueue/blob/dev/common/src/main/java/us/ajg0702/queue/common/DefaultQueueHolder.java

And registering it: https://github.com/ajgeiss0702/ajQueue/blob/dev/common/src/main/java/us/ajg0702/queue/common/QueueMain.java#L203

If you have any questions about implementing it, you can always ask me on discord

@SladeHazard

This comment was marked as off-topic.

@PedroMPagani

This comment was marked as off-topic.

@ajgeiss0702

This comment was marked as off-topic.

@SladeHazard

This comment was marked as off-topic.

@ajgeiss0702

This comment was marked as off-topic.

@SladeHazard

This comment was marked as off-topic.

@ajgeiss0702

This comment was marked as off-topic.

@mor-uto

This comment was marked as off-topic.

@ajgeiss0702

This comment was marked as off-topic.

@mor-uto

This comment was marked as off-topic.

@ajgeiss0702

This comment was marked as off-topic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants