How to make AWS Lambda work reliably with Neptune over websockets? - amazon-web-services

So I've built this API. It consists of a Lambda function (accessible via API Gateway) which talks to a Neptune graph database instance via websockets.
Everything is wired up and working. But I recently started noticing intermittent 500's coming from the API. After some investigation I found that the Neptune Gremlin server was dropping/refusing connections whenever multiple requests would come in close together.
I found this page which suggests that the ephemeral nature of serverless doesn't play nice with websockets, so the websocket connection should be closed manually after each request. But after implementing that I found no difference – still 500's.
The page also suggests that when using Gremlin on Neptune you should probably send HTTP requests to Neptune rather than using websockets,
Alternatively, if you are using Gremlin, consider submitting requests to the Gremlin HTTP REST endpoint rather than the WebSockets endpoint, thereby avoiding the need to create and manage the lifetime of a connection pool.
The downside to this approach is that we would then have to use string-based queries (which means re-writing a large portion of the project). Another downside is that the Gremlin HTTP endpoint returns pretty unstructured data.
So what I'm wondering is whether anyone has got Lambda reliably talking to Neptune over websockets? If so, how?
Edit:
Since I'm using the AWS Chalice framework I don't think I really have direct access to the handler function. Below is what my lambda looks like.
And here is the code that connect() is calling:
import os
from gremlin_python.structure.graph import Graph
from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection
def connect():
conn_string = os.environ.get('GRAPH_DB')
global g
g = Graph().traversal().withRemote(DriverRemoteConnection(conn_string, 'g'))
So when the app starts (when a lambda instance is spun up), that connect function is called and the app gets a connection to Neptune. From there the app passes around that global g variable so as to use the same connection instance for that invocation. I was then calling close() on the DriverRemoteConnection object before returning the results of a request (and that's where I found I was still getting 500's).

Yes, it is possible to use WebSockets within a Lambda function to communicate with Neptune. There are different nuances for doing this depending on the programming language that you're using. Ultimately, it comes down instantiating the client connection and closing the connection within the handler() of the Lambda function.
If using Java [1], you can create the cluster object outside of the handler so that it can be reused per each Lambda invocation. But the client that is configured from that cluster object must be instantiated and closed during each invocation.
Do you have a snippet of code that you're using that you could share for review?
[1] https://docs.aws.amazon.com/neptune/latest/userguide/best-practices-gremlin-java-close-connections.html

Related

Best practices to handle session established with external system in AWS lambda

We are designing a new serverless application in AWS for fist time that makes API call to external system to perform certain operations. Before performing any API call related to certain functionality we need to establish a session with that external system and that session Id needs to be passed with every API call . Here comes my questions
It was suggested to create a separate lambda to perform login operations. In that case how this lambda can share session details with other lambda ?
To share the session we thought of having it in cache. But then another suggestion came to use an adapter. We are totally clueless about what adapter is ??
If session gets expired how we can get another session established ??

Use fastapi with AWS websocket api gateway

I have a FastAPI working on an EC2 under REST api with some endpoints. Now I would like to use it under a websocket api. To do this I have a few questions:
On my FastAPI, what shoud I do? I have read they introduce mangnum and a handler main for magnum, but they always have only one endpoint and I have several endpoints.
Also, they always use a lambda function. Could I use an EC2?
How do $connection and $disconnection work in this case? What do I have to introduce in my fastapi so I can still use my endpoints?
Processes inside my fastapi can take long to answer (eg. 20s). Therefore, I need to move to websocket to avoid timeouts. If you think I can have a better solution in a different way I'll happy to know about it.
I have spent weeks on this same issue. I tried countless configurations and in the end I ended up not using FastAPI. I replaced my #app.websocket with a basic lambda_handler(event, context) function so that I could use the the connect, disconnect and sendmessage handlers as per AWS documentation. To the day I still can't figure out how to do it with FastAPI and it bugs me. Have you found a solution to this?
This helped - https://docs.aws.amazon.com/code-samples/latest/catalog/code-catalog-python-cross_service-apigateway_websocket_chat.html
Editing this to add that I am using python.

How to test a Spring Cloud Function using message stream

I'm currently attempting to port an existing Spring Cloud Stream app over to using Spring Cloud Function instead. When running the application, we use bindings to map from an input queue (either Kafka or IBMMQ). Messages sent on the queue are passed through a custom MessageConverter and then passed to our custom routing function.
In Spring Cloud Stream, the bindings allowed for direct access to the testing queues (via calling input()) for example, and one could simply send a message on that queue to start the process rolling.
What I'm trying to find is a similar mechanism for sending messages to the queue that the Spring Cloud Function is bound to. The problem is that I can't seem to figure out how to do that.
I've seen how one can access the routingFunction via HTTP, but unfortunately, this bypasses my MessageConverter so I still can't really do an end-to-end test.
Has anyone got any ideas or pointers to how I might get this to work with Cloud Function?

Alexa Smart Home Skill - Use Lambda to just forward events

I'm building an Alexa Smart Home skill.
Each of my users owns a hub device in their homes which is maintains an permanently open connection to my servers.
Now, Smart Home Skills require the usage of AWS Lambda, which I actually do not want to use, since I already have my own servers.
The idea is to use Lambda to just forward every incoming event to my servers via https and answering all requests asynchronously.
Since I imagine there are other people that want to forward lambda calls to their own servers, I wonder if there is already open source software for doing just that?
You can certainly use your Lambda as a pass-through or proxy, send the request to your server to send an asynchronous response.
However, another approach could be to handle the Alexa specific logic in your Lambda, and then call your server/API via HTTP to just get what it needs (state/device info) for any request from Alexa. This decouples your logic better IMO, with separation of concerns.
There's no open source software to do this for you either, as essentially you'll need to map your device/state data to the format for Alexa. The docs are pretty good though.

Architecture Design for API of Cloud Service

Background:
I've a local application that process the user input for 3 second (approximately) and then return an answer (output) to the user.
(I don't want to go into details about my application in purpose of not complicate the question and keep it a pure architectural question)
My Goal:
I want to make my application a service in the cloud and expose API
(for the upcoming website and for clients that will connect the service without install the software locally)
Possible Solutions:
Deploy WCF on the cloud and use my application there, so clients can invoke the service and use my application on the cloud. (RPC style)
Use a Web-API that will insert the request into queue and then a worker role will dequeue requests and post the results to a DB, so the client will send one request for creating a request in the queue, and another request for getting the result (which the Web-API will get from the DB).
The Problems:
If I go with the WCF solution (#1) I cant handle great loads of requests, maybe 10-20 simultaneously.
If I go with the WebAPI-Queue-WorkerRole solution (#2) sometimes the client will need to request the results multiple times its can be a problem.
If I go with the WebAPI-Queue-WorkerRole solution (#2) the process isn't sync, the client will not get the result once the process of his request is done, he need to request the result.
Questions:
In the WebAPI-Queue-WorkerRole solution (#2), can I somehow alert the client once his request has processed and done ? so I can save the client multiple request (for the result).
Asking multiple times for the result isn't old stuff ? I remmemeber that 10 - 15 years ago its was accepted but now ? I know that VirusTotal API use this kind of design.
There is a better solution ? one that will handle great loads and will be sync or async (returning result to the client once it done) ?
Thank you.
If you're using Azure, why not simply fire up more servers and use load balancing to handle more load? In that way, as your load increases, you have more servers to handle the requests.
Microsoft recently made available the Azure Service Fabric, which gives you a lot of control over spinning up and shutting down these services.