A presentation at JUG Nürnberg in in Nuremberg, Germany by Alexander Reelsen
Running a Serverless Lucene Reverse Geocoder Alexander Reelsen alex@elastic.co @spinscale
Agenda ‣ What is serverless? ‣ Searching for Locations ‣ Demo ‣ How to execute java code faster
Serverless?
Serverless? ‣ FaaS (Function as a Service) ‣ Execution Environment as a Service ‣ Payment model: Pay per code runtime ‣ Not running? No bill! ‣ Configure memory size (also changes CPU power) ‣ Maximum function execution time ‣ Provider takes care of scaling functions
Examples ‣ Good: Short lived HTTP requests ‣ Good: Short running jobs ‣ Good: Event streaming & processing ‣ Good: Share nothing web applications ‣ Good: Parallelizable workloads ‣ Bad: Slack bots?
Providers? ‣ AWS Lambda, GCP Cloud Functions, Azure Cloud Functions, Cloudflare, IBM OpenWhisk, Google Cloud Run ‣ Faastruby, Binaris, Spotinst ‣ K8s: KNative, Fission, Kubeless, Nuclio, OpenFaas ‣ Docker: Fn, OpenFaas
Java? ‣ Not too well suited for short lived tasks ‣ JVM startup time ‣ JIT compiler ‣ Dependency initialisation ‣ Application initialisation
Location Tracker: Owntracks + Lambda + Kibana
https://github.com/spinscale/serverless-owntracks-kotlin
Location search
Reverse Geocoder ‣ Input: Latitude, Longitude ‣ Output: readable representation (City)
Search across points ‣ Each city gets indexed with a lat/lon pair ‣ Search for the next point to the supplied one ‣ Problem: Neighbours!
Point based search: Near neighbours
Point based search: Near neighbours
Search across shapes ‣ Each city gets indexed with a lat/lon pair ‣ Certain cities get indexed as a geoshape ‣ Run two searches: ‣ Lat/Lon within any shape ‣ Lat/Lon nearby any point
Geo and Lucene: BFF! ‣ LatLonPoint: two points, 4 bytes each ‣ LatLonShape: triangular mesh tesselation
Geo and Lucene: BFF! https://home.apache.org/~mikemccand/geobench.html
Geo and Lucene: BFF! https://home.apache.org/~mikemccand/geobench.html
Serverless Lucene ‣ Local execution, index part of the package ‣ Offline index creation ‣ Packaging index into code ‣ Index needs to be unpacked, using Lucene via classpath resources is tricky
Demo
Summary ‣ Works! ‣ Problem: Data quality, getting accurate shape data ‣ Problem: First invocation (up to 2s) ‣ JVM startup ‣ Lucene index opening
Faster startup & runtime
Enter GraalVM! ‣ A new compiler, supporting HotSpot and AOT compilation ‣ Graal compiler part of Java9 (experimental!) ‣ Graal JIT compiler part of Java10 (Linux 64bit only) ‣ Project Metropolis: Java-on-Java Hotspot implementation ‣ Truffle: Framework to implement other languages on top of graal (jruby replacement)
Enter GraalVM! ‣ AOT static compilation + SubstrateVM = executable binaries of java apps ‣ Using SubstrateVM ‣ Reflection!
Deployment model
AWS Lambda ‣ Deployment model: Zip archive in S3 bucket ‣ Execution: Download zip archive & execute ‣ Requires regular java start (AWS reduced JVM startup time) ‣ GraalVM can only be used with custom runtime
runtime flow
CUSTOM RUNTIME
AWS_LAMBDA_RUNTIME_API=localhost:12345 _HANDLER=”my_handler” /bin/bootstrap CUSTOM RUNTIME
AWS_LAMBDA_RUNTIME_API=localhost:12345 _HANDLER=”my_handler” /bin/bootstrap AWS ENDPOINT CUSTOM RUNTIME
AWS_LAMBDA_RUNTIME_API=localhost:12345 _HANDLER=”my_handler” /bin/bootstrap GET /2018-06-01/runtime/invocation/next AWS ENDPOINT CUSTOM RUNTIME
AWS_LAMBDA_RUNTIME_API=localhost:12345 _HANDLER=”my_handler” /bin/bootstrap GET /2018-06-01/runtime/invocation/next AWS ENDPOINT Lambda-Runtime-Aws-Request-Id: 123 { “body”: “{ “foo”: “bar” }”, “requestContext”: “{ … }”, “headers” : { … } } CUSTOM RUNTIME
AWS_LAMBDA_RUNTIME_API=localhost:12345 _HANDLER=”my_handler” /bin/bootstrap POST /2018-06-01/runtime/invocation/123/response { AWS ENDPOINT “body”: “{ “foo”: “bar” }”, “headers” : { … } } CUSTOM RUNTIME
AWS_LAMBDA_RUNTIME_API=localhost:12345 _HANDLER=”my_handler” /bin/bootstrap POST /2018-06-01/runtime/invocation/123/response { AWS ENDPOINT “body”: “{ “foo”: “bar” }”, “headers” : { … } } HTTP OK 202 CUSTOM RUNTIME
AWS_LAMBDA_RUNTIME_API=localhost:12345 _HANDLER=”my_handler” /bin/bootstrap POST /2018-06-01/runtime/invocation/123/error { AWS ENDPOINT “statusCode”: 500, “body” : “…” } CUSTOM RUNTIME
AWS_LAMBDA_RUNTIME_API=localhost:12345 _HANDLER=”my_handler” /bin/bootstrap POST /2018-06-01/runtime/init/error { AWS ENDPOINT “errorMessage” : “…”, “errorType” : “…” } CUSTOM RUNTIME
Google Cloud Run
Google Cloud Run ‣ Serverless done ‘right’? ‣ Docker container as a web application listening in $PORT ‣ Deployment model: docker push && gcloud beta run ‣ Easier to test ‣ Configurable concurrency ‣ Improved billing model due to concurrency
Demo
Summary
Summary ‣ Economics ‣ Billing model ‣ Runtime cost vs. development cost ‣ Break even vs. non serverless model ‣ Development ‣ Vendor lock-in ‣ Deployment model is important ‣ Cloud Run: Run serverless or as container ‣ Scalability strategies, base load container, increased load serverless? ‣ Observability
Discussion … ask all the things!
Links ‣ https://serverless.com/framework/docs/ ‣ https://www.openfaas.com ‣ https://cloud.google.com/knative/ ‣ https://kubeless.io/ ‣ https://fission.io/ ‣ http://fnproject.io/ ‣ https://nuclio.io ‣ https://openwhisk.incubator.apache.org/ ‣ https://www.graalvm.org ‣ https://openjdk.java.net/projects/metropolis/ ‣ https://github.com/oracle/graal/tree/master/substratevm ‣ https://en.wikipedia.org/wiki/Reverse_geocoding https://noti.st/spinscale/ACCnKE/running-a-serverless-lucene-reverse-geocoder
This presentation talks about the possibility of running a reverse geocoder based on lucene in a serverless environment. The talk features the serverless framework, lucene geo capabilities using points and shapes, and last but not least mentions graalvm to reduce start up times. This talk also shows AWS Lambda, Google Cloud Run and does a brief comparison.