Multiple ports in one app? public plus private

hi there
we have been using sanic in production for a few years and its great.

one thing we need right now is the ability to run certain endpoints on certain ports.

The need is this:

we have some endpoints: metrics, apidocs, etc that need to be private, that means not on the port 80 that our load balancer exposes to the world.

Currently we use a “side-car” process for that which means we can only have one sanic worker as it needs to embed the subprocess that itself exposes the port 9999 to our internal networks containing mentioned routes.

it would be great if we could mark the endpoints to be served from a different port and then not have to worry about the maintenance of our subprocess PLUS we could much easier share state with regards to metrics

whats your thoughts?

btw we use prometheus

this repo mentions my problems:

Why not have these endpoints on a separate process completely? A service that only serves those endpoints?

How is it that you are passing data to your metrics endpoint?


My initial impression is that this seems like a fairly narrow use case to bake into Sanic itself. We would need to keep track of the number of ports registered to endpoints, and then spin up multiple servers (one for each port). Then, how would we handle multiple workers? I could see this growing very large in complexity.

Both app.run and app.create_server allow you to pass in a custom HTTPProtocol and a custom Router. I feel like this might be a good use case for that. Perhaps a first stab at this might be to work on a plugin that provides this ability through overriding the default Sanic classes with a custom implementation.

interesting with the custom router idea. Yeah this is pretty narrow i think, and i am not at all promoting the idea to polute sanic code with unneeded features.

The idea however about gathering metrics and exposing them through one endpoint is solid and there should be a way to do that regardless of the number of workers you run.

But maybe the issue should be shuffled a little and described like this:

you run one script

that script will create two processes
both can be sanic but one is for private stuff the other is a worker-scaled public router and the other is a metrics router for internal consumption.

the next issue is then that to gather metrics you would need a way for all the workers to write somewhere shared for the metrics app to consume from.

this secondary problem is definitely not the responsibility of Sanic and i think that just showed that yes, youre correct: running the two apps (public + private) in seperate process hierachies plus a IPC thingy for gathering logs is the right thing to do!

thx

One of the main things that I strive for in Sanic is for it to remain unopinionated. Personally, I think this is a fine solution if it meets your business needs. If I had to do it, I would prefer to run this in a separate service and only pass the information through some sort of messaging protocol.

The public/private is certainly an interesting idea. But, again, I think it is somewhat of a narrow enough use case that it first belongs in a private repo. If it really began to serve an important function, then sure, let’s bring it into core. Keeping the custom subclasses separate would keep the existing code base easier for maintenance.

btw thanks for the great framework and community and support. we even devloped and released some extras for it that we use every day(https://github.com/trustpilot/python-sanicargs)
so i am very grateful for the great work by your all!

:blush:

Nice idea. I am curious to see if it has any speed impact on the router.

Have you thought about submitting it here: https://github.com/mekicha/awesome-sanic

I see that you already did… :grimacing:

hahaha :slight_smile: have a great summer y’all!!!

1 Like