6
Python Flask vs Node.js Tech Stack Rationale by Glenn Engstrand

Python Flask vs Node - Glenn Engstrand

  • Upload
    others

  • View
    34

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Python Flask vs Node - Glenn Engstrand

Python Flask vs Node.js

Tech Stack Rationale

by Glenn Engstrand

For those considering the development of micro-services, two verypopular programming languages for that are Python and javascriptand two popular frameworks for those languages are Flask andNode. js. You may be wondering which one to choose from. In this blog,I wi l l explore what it is l ike to develop a rudimentary news feed micro-service written in version 3 of Python on Flask by comparing thatexperience with developing the same micro-service in Node. js

Why choose Flask over Django?Isn't Django more popular thanFlask? According to Googletrends, it is three times morepopular. According to StackOverflow Trends, it is five timesmore popular. Django can be usedto implement micro-services butit was original ly intended to solvea different problem, namely howto develop a monol ithic web siteappl ication. Why compare Pythonon Flask against Node. js? Manytechnology startups aredisi l lusioned with Java and areseeking alternatives.

Python and javascript are the usualconsiderations. At first glance, theyseem somewhat simi lar but thereare some very profound differencestoo.

Both are Dynamic ScriptingLanguages which makes for a fastercode, run, debug cycle. Neitherprogramming language uses statictype checking but both offer work-a-rounds for that. Both areenthusiastical ly embraced by thestartup community, especial ly in theBay Area of Cal ifornia. Both providean integration with Swagger wherethe API specification itself is definedin a model contained in a YAML fi le.

Page 2: Python Flask vs Node - Glenn Engstrand

Copyright © 2017 Glenn Engstrand

Architecture Differences

node. js

A bui ld time generator usestemplates to generate code and aruntime l ibrary is also used in sucha way that the programmerdoesn't have to write any code toimplement the API itself. ForPython, that integration is a projectcal led connexion. For Node. js usethe swagger-tools project.

Python 3 includes support for typehints baked into the languageitself whi le javascript rel ies onjsdoc annotations and the closurecompi ler which is rarely used inserver side development. Thoughsti l l uncommon, you can writeyour Node. js apps in TypeScriptwhich can perform static typechecking. Node. js is more popularthan Python Flask. According toGoogle Trends, Node. js interest isthree times more than PythonFlask interest. According to StackOverflow Trends, Node. js interestis thirteen times more than PythonFlask interest. According toIndeed.com, there are seven timesas many Node. js jobs as there arePython Flask jobs with only a twopercent reduction in averagesalary.

The most profound architecturaldifference between these twoprogramming languages l ies intheir respective threading models.Theoretical ly, Python is multi -threaded but threads are under thecontrol of the Global InterpreterLock which means that at mostonly one thread can access anyPython objects at any single timewhich means no true paral lel ismcan occur in a single process.Javascript is also single-threadedper process and uses an eventloop for its concurrency model .Another important architecturalaspect in the two programminglanguages is how symbol ic codegets converted into machinelanguage. For Python, the sourcecode is loaded and recompi led intothe byte code if the modifiedtimestamp of the former is laterthan the modified timestamp ofthe latter.

What both Flask and Node. js havein common is that they areminimal ist web frameworks thatare wel l suited for micro-servicedevelopment. Flask does notconcern itself with compi lation butNode. js embeds the Chrome V8compi ler within it. This means thatjavascript code is compi led intomachine language code in memorythe first time it is referenced.

Page 3: Python Flask vs Node - Glenn Engstrand

Design Differences

Copyright © 2017 Glenn Engstrand

Python / Flask

This is known as J IT or Just InTime compi lation. After that, themachine language code isexecuted directly. Chrome V8compi led machine languagecode executes faster thanPython compi led byte code.

What both connexion and swagger-tools has in common is that theyboth read the same swagger YAML specification at the time that theappl ication is launched and route requests based on that specification.How connexion differs from swagger-tools is that the HTTP servercomponent is pluggable whereas swagger-tools just depends onNode. js which has embedded within it the HTTP server functional ity.For connexion, the server backends avai lable are tornado, gevent, andflask server. Though advise on the Internet recommends using geventin production, my own tests revealed that the flask server had the bestperformance under load. Flask server can be configured to run in thefol lowing modes; single threaded single process, single threaded multi -process, or multi -threaded. Running load tests on al l of these modesrevealed multi -threaded to have the best performance.

Though javascript does supportprototype based objectorientation, development ofNode. js services typical ly rel iesmore on modules than objects.The opposite is true for Flaskwhich depends heavi ly on objectorientation. The service developedand tested here used the verypopular Flask SQLAlchemyextension which provides accessto MySql via an Object RelationalMapping layer.

Here is how the threading modeldifferences manifest differences inhow services are designed. Forjavascript, functions that depend(either directly or indirectly) onblocking I/O must use a cal lbackmechanism where a functionexpression is passed in as anargument to the higher orderfunction. Instead of returning thevalue from the blocking I/O, thatfunction expression is cal led withthe desired value. The lambda isalso cal led when the I/O requestfai led.

Page 4: Python Flask vs Node - Glenn Engstrand

Coding Differences

Copyright © 2017 Glenn Engstrand

I t is not correct to make anyassumptions about the order in whichthese function expressions are executedin relation to code around it. Recentimprovements include a promise basedapproach which is simi lar to cal lbacksbut is easier to chain multiple blockingI/O cal ls together and separates thesuccess processing code from thefai lure processing code. Pythonfunctions can safely return values fromblocking I/O due to its threading model .Waiting for I/O to complete for onerequest does not prevent processing tooccur for other requests.

The Python Flask service has both twicethe number of fi les and twice the numberof l ines of code than the Node. js service.

You would think that, since there is twiceas much Python code as javascript code,that the Python code would be morecomplex. Actual ly, i t is the opposite thatis true. The Python code is heavi ly objectoriented whereas the javascript code isnot. The purpose of object orientation isto mitigate the complexity of the code. Ifyou look at just the method that creates anew outbound post, then you wi l lunderstand why the Node. js code is morecomplex than the Python Flask code. Inboth services, that method inserts a rowinto the outbound table.

The submitter’s friends arefetched and correspondingrows are inserted into theinbound table for eachfriend. Final ly, a document isinserted into the searchindex. In feed5 (PythonFlask), that method is tenl ines of code. In feed4(Node. js) , that method is 38l ines of code. The otherfactor that contributes tojavascript complexity ismanaging al l those cal lbacks in a way that properlyreleases al located resourcesboth when the I/O succeedsand when it fai ls.

A very importantrequirement of unit tests isthat they can be runseparately from anydependent service. The testsshould be able to pass evenwhen the dependentservices are unavai lable or ina bad state. That is usual lyaccompl ished by employinga technique cal led mocking.For node. js, I used theBusiness DrivenDevelopment focusedassertion l ibrary Chai andthe mockery l ibrary formocking modules that areresponsible for accessing thedependent services. There isan extension to Flask cal ledFlask-Testing which al lowsyou to include coverage ofthe control lers in your unittests but is not BDD focused.Because I was using SqlAlchemy for the relationaldatabase access,

Page 5: Python Flask vs Node - Glenn Engstrand

Community Differences

Both projects pride themselves on their bare bones nature. Instead ofproviding everything you need, these kind of projects focus on justbeing a micro-service container and let you pick and choose the othertechnologies that you wi l l need. In this way, they are considered to beun-opinionated. Their main attraction to early stage startups is thatthe learning curve is very shal low which lets new programmers feell ike they are being productive fairly quickly. Neither one of them has alot of features. As stated earl ier, the feed5 project here used Pythonversion 3. Even though Python 3 has been around for over eightyears, it is sti l l considered to be immature. I ts adoption has been slowdue to its incompatibi l i ty with version 2. I bel ieve Python 3 to be rocksol id but this perception of immaturity becomes a self fulfi l l ingprophecy. At the time of this writing, I had to run feed5 in dockerbecause the standard EC2 AMI was incompatible with Python 3.

Copyright © 2017 Glenn Engstrand

I was able to reconfigure it to connect with SQLite instead of MySql forthe unit tests. SQLite is a relational database for accessing a local fi leby a single user which is appropriate for unit tests. I used MagicMockfor mocking the DAOs and service classes for the rest of the dependentservices.

Both projects are hosted on GitHub so it is easy to compare them interms of community focused metrics. Node. js is only one year olderthan Flask. There is easi ly an order of magnitude more commits toNode. js than to Flask. Both projects have lots of committers. Anecdotalevidence suggests that there is a lot more onl ine content on Node. jsthan on Python Flask and that it is more accurate and helpful too.

The Python service can easi ly integrate with Kafka but I was never ableto find a Node. js driver that worked. Since message brokers are prettyimportant these days and since Kafka is the leading message broker,

I woulddeclarethat thisgap in theNode. jscommunitymakes itless stablethan thePythoncommunity.

Page 6: Python Flask vs Node - Glenn Engstrand

Copyright © 2017 Glenn Engstrand

Performance Differences Summary

AboutGlenn

Engstrand

Glenn's focus is on working with engineers in order todeliver scalable, server side, 12 factor compliantapplication architectures. He was a breakout speaker atAdobe's internal Advertising Cloud developer's conferencein 2017 and at the 2012 Lucene Revolution conference inBoston. He specializes in breaking monolithic applicationsup into micro-services and in deep integration with Real-Time Communications infrastructure.

The tool ing for both is fairly strong. When it comes to IDEs, pycharm isthe most popular choice for Python and WebStorm is the most popularchoice for Node. js development. I used emacs to code both projects.Package management for Node. js is npm and Python has pip. There arealmost three times as many packages avai lable in npm as in pip. I wasable to get only one MySql driver to work with Python 3 and FlaskSQLAlchemy and that driver cannot be instal led by pip.

Let's cover the most importantdifferences which is in how wel leach technology performedunder load on AWS.

In order to reduce thedifferences as much as possible,I commented out the cal ls toKafka in the Python service andran the Node. js service in aDocker container. Both serviceswere tested in identicalenvironments and with the sameload test appl ication.

The Python service was almosttwice as slow as the Node. jsservice.

The Python service exhibited14% less throughput than theNode. js service.

The Python service achieved athird less CPU uti l ization thanthe Node. js service. I t alsohandled one third the networkbandwidth.

The service written in Pythonunderperformed when comparedto the Node. js service. Not onlywas it slower, it a lso could notkeep up in throughput and couldnot uti l ize as much of thehardware. I bel ieve that the mostsignificant reason for thesedifferences l ies in the difference inthreading models. Python'sthreading model permits thePython coder to avoid the Node. jsevent loop inspired cal lback codecomplexity but, since only onethread runs at a time, no Pythonservice can ever keep more thanone CPU busy. Node. js is alsosingle threaded but, with clustermode enabled, the service can runsingle threaded, multi -processand uti l ize more of the server thatway.