❔ REST API but it is HttpListener only available
Hello there, I got a challenge to write good scalable C# REST API app by using only .NET 7 (instead of ASP .NET) with HttpListener.
So I have some questions:
1) As I understood, it will only one
HttpListener
instance that catch all requests on different endpoints - not dedicated HttpListener
to dedicated endpoint?
2) After I catch connection, I should do httpListenerInstance.GetContextAsync()
and then transfer it to ThreadPool.QueueUserWorkItem
?
3) How to execute some logic on needed endpoint? I found an answer by notifying all endpoints like hey my dudes, it is new connection to /endpoint
can all of you handle it and execute if needed by checking itself context by using Observer pattern. But I see it may slower my system, is it any way to notify only 1 needed endpoint class?
4) ThreadPool.QueueUserWorkItem
or it is better to create custom class which will store ConcurrentQueue<HttpListenerContext>
with all my connections and then run another Task which will peak and notify endpoint func (see p.2 and p.3)?
Please leave good advices - I can not use sweety ASP .NET.16 Replies
1) Yes, that seems correct, assuming there's lots of overlap between the endpoints you're listening to. If not, it may be better to split them up, to reduce the amount of work you have to do to decide what to do with each request.
2) If you're going to use the Async() APIs (which you should, this will be crucial for getting the most out of the ThreadPool) then don't mix-and-match with non-Async ones. Fire off your processing to the ThreadPool with
Task.Run()
and keep a reference to that Task
to make sure it eventually gets await
ed, which will help you make sure that exceptions bubble out and get logged or otherwise handled, and that you can do a proper cleanup during shutdown.
3) I have no idea what you're trying to ask here.
4) ThreadPool.QueueUserWorkItem()
is probably better, so long as it gives you a way to synchronise when the work item finishes. Don't try and second-guess the efficiency and optimization of the Framework. If you think you can do something better, you'll usually be wrong, unless you have hard data to back up how your specific scenario can be optimized better. But as stated above, use Task
/Async()
APIs instead.let me rephrase p. 3: relationship 1-to-many. Where 1 is my class that should ask to execute and many are my endpoints classes. I guess, that by notify all endpoints (even if it's doesn't match user Uri) I can solve this problem, but the fault is we are wasting server resources. So is it any solution to use MediatR to execute exactly needed endpoint func (if user is on
/endpoint1
only notify class of this endpoint).
p. s. the dummy idea that my friend said is store dictionary with key: endpoint Uri and value: needed executor class (but I guess it is super bad idea caz not scalable enough)Back in ye olde PHP days before proper frameworks were a thing, it wasn't uncommon to roll your own front router
That is, you redirect all traffic to
index.php
and, depending on the requested URL, you call different other files
You're basically looking at doing something like that
Whether it'll be a dictionary, or something based on reflections and attributes, is up to youxd, so it is challenge that my teacher gave us: no Spring for Java and no ASP for C#
And depends on the complexity of the URLs
Where 1 is my class that should ask to executeWhat? What does this mean? What class is asking to execute what? We've talked about building an HTTP server, with an HttpListener, it doesn't ask to execute endpoints, it listens and is told to execute endpoints I like this, BTW, this is a cool challenge not practical, but an excellent learning experience
Basically, something akin to
I thought that the idea is store all contexts in 1 executor function and then it will ask directly 1 endpoint func
assuming your queries will not have any parameters, and assuming that dictionary remains static after its initial construction on startup, yes, that is a reasonable approach
if you DO need some amount of parameter matching, I would recommend a set of
Regex
s
or just one regex, if you can manage itI was thinking of that too, but imagine we have more than 10 endpoints. Not the best idea for scalable?..
I don't see why
again, that sounds perfectly reasonable
M8, you want scalable you use ASP is a school project
the more endpoints you have, the better a Dictionary gets
except for memory footprint
but that's not gonna be significant compared to the lookup gains
huh, yeap 🙂
my perfectionism 💀
I guess I will store regexp as @V.EINA Jaken mentioned
unless the
HttpListener
parses out the query for you
I would do that for parsing the path out from the params
or if you have parameters within the pathWas this issue resolved? If so, run
/close
- otherwise I will mark this as stale and this post will be archived until there is new activity.