-
Notifications
You must be signed in to change notification settings - Fork 25
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
My thoughts on the Python FDK #66
Comments
Hi and thanks for the feedback. First of all, as for now Fn ships 1 request at the time to a function. However, nobody said that it’s not going to change in months. So, between two options: “sync server” VS “concurrent server that can do sync request as well” I would personally pick the one that is capable to do more. The next concern here is an HTTP framework choice:
Unfortunately, non of the existing HTTP async concurrent frameworks on a market can deal with cold start thing. They all are huge filled with unneeded code, tons of code. It’s a shame that Python standard lib doesn’t have good choice of async HTTP framework, so, we have to find our own way. Homegrown. Why? Well, say hi to cold start time, we have pretty strong requirement: FDK must start within 3 seconds. So, I tried to use this framework as 3rd-party dependency, however, the cold start time was beyond 4 second, which is not acceptable for sure. But, moving this framework to an FDK repo made the whole startup time lower, less than 2.5 seconds. This is a win, but what’s the cost? A cost of a trade-off.
This is a battle for year. Eventlet been around python 2 for a while, but tulip(asyncio) appeared not so long ago. However, eventlet lost its battle to become de-facto native core technology. So, there’s only one problem - due to certain disagreement Python standard lib doesn’t have native async http server. That’s the problem we need to bring to python cores rather than arguing here, don’t you think so? Note: The biggest advantage over eventlet is that asyncio is built-in into a language and a lot of tools being developed with it, the amount of libs with asyncio is way more bigger than tools with eventlet. Just check how many tools live at aio-libs space as an example of the technology adoption. |
That’s true and I foresee that for any interpreted language we have officially supported we would concider changing the way it woks by adopting the concept of delayed imports, of course, if that feature is supported. |
Thanks for the reply. First, let's put to rest the notion that you need a homegrown solution to achieve the needed startup performance. My FDK proves that you don't. Secondly, if you insist on an async server using Python 3 asyncio specifically (I still don't see the need, but...), I'm sure there's a better solution based on tools with community support instead of code developed by one individual. You say asyncio has won the battle and is built in, but then I see all this code you had to write, and that concerns me. Maybe check out this article as perhaps a better solution? not sure: https://medium.com/@pgjones/an-asyncio-socket-tutorial-5e6f3308b8b0 Finally, My FDK proves that the change in the FDK programming model to support lazy importing is COMPLETELY UNNECESSARY for the Python FDK. |
As soon as we'd found asyncio-based HTTP framework that can start within less than 3 seconds, we'd remove our own code immediately, but changing asyncio to eventlet is not a solution.
Well, if you'd check our HTTP framework you'd see that we use the same interface (
to be clear, your code proves that every import inside of an HTTP request handler would not cause any problems because they are all inside of a function with limited availability scope (when our FDK doesn't limit the scope). In any case, placing all imports inside of a function is not pythonic way to solve imports cold start issue. |
thanks @paulfelix for your feedback. we did try https://medium.com/@pgjones/an-asyncio-socket-tutorial-5e6f3308b8b0 but it wasn't quite sufficient for our needs, as Denis pointed out, we pretty much ended up copying a lot of stuff from sanic and chose instead to just basically vendor sanic and strip some of the stuff we did not need to reduce the cold start time. very good feedback on the imports issue, if the python3.7 bit becomes a blocker for users that seems like a pretty sane route to go (just tell users to import in handler). I'm skeptical as well of requiring python3.7, as it hasn't been out for long and certain enterprise users may need more flexibility on supported python versions that have been around for a while longer. honestly, would prefer this approach for flexibility alone, as 3.5+ will support the async stuff fine which was one of our main requirements. I agree that for the FDK in their current state of just running 1 function at a time, asyncio doesn't seem necessary at all to me, either, and would allow us to not need the hassle of the async stuff at all. python itself seems very fragmented, and it's not clear the best path forward with the fdk python for a lot of reasons (python 2 support people want, some people want async, some don't need it - don't mean to spark this discussion, just reiterating why this kind of feedback is useful) again, thanks a lot for digging in and pasting your honest feedback, one of my greatest fears with the python fdk (or any fdk, really) is users just going and implementing their own - if that happens, then we need to reconsider why that's the case and work to fix that, the goal is for these to be useful and any of our ideologies shouldn't get in the way of that! |
I want to share some thoughts on the fdk-python design and some experiences (so far) developing my own Python FDK. This is not a proposal to make any changes to the fdk-python, just thoughts.
Two substantial changes to the latest fdk-python include:
The main driver for these changes, from my understanding, is to a) improve cold startup time up to the point when the function is listening on the unix socket, and b) support Python 3 asyncio programming in the function itself.
I feel the implemented solutions to these problems are unnecessary and result in too much extra code that has to be developed/maintained/fixed. Specifically, the homegrown async http code is unnecessary, and the lazy importing approach (using a Python 3.7 feature) is also unnecessary. It also sets the Python FDK programming model apart from the FDKs for other languages.
Here's my experience so far developing my own Python FDK. I think it also solves the same problems while using much less code and avoiding a change to the function programming model. The code shown here is working code, but still just proof-of-concept, as it lacks extra error handling, return types, etc.
I chose to use the
eventlet
wsgi package to listen to http over the unix socket. Here's my main code fo far:Here's the basic wsgi application code. It constructs a
Request
object from the environment variables (code not shown) that is passed to the function's handler.Here is the function's
func.py
code:Notice that the function's modules are not imported until the handler is called. Unless I'm missing something, that's all we need for lazy loading. The next time the handler is called, the
myfunction
module will have been loaded already, so the import will be a no-op.Using my FDK, I have been working on a function that handles GraphQL queries and makes concurrent calls to other services using Python asyncio. The time from cold-start container loading to the first handler call is < 1sec.
I have been able to run my function on OSX and CentOS platforms with the same performance on both.
The text was updated successfully, but these errors were encountered: