Reputation: 91
How do I keep an API Gateway Websocket API with a Lambda Java back end from timing out after 30 seconds?
The AWS API Gateway and re:invent videos mention using pings or heartbeats to keep the Websocket connection alive but I haven't found a straight-forward working example (in Java). The front end is using HTML 5 Websockets (vanilla javascript).
I'm including my Lambda test driver in Java. It causes the API Gateway WS API to timeout after 30 seconds as documented. The driver will return successfully if you remove the delay. Any help is appreciated...
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Map;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
import com.fasterxml.jackson.databind.ObjectMapper;
public class TestWSClient implements RequestStreamHandler {
public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) {
try {
//
// How do we keep API Gateway from timing out after 30 seconds?
// Is something like this even needed in the lambda?
//
new Thread(() -> {
while(true) {
try {
// Ping client every 15 seconds
Thread.sleep(15000);
//outputStream.write(); // What to write -- 0x89 0x00?
outputStream.flush();
} catch(Exception e) { e.printStackTrace(); }
}
}).start();
//
// Simulate long processing time or streaming
//
// NOTE: commenting sleep enables service to return w/o a timeout
// connection from API Gateway
//
try { Thread.sleep(60000); } catch(Exception e) {}
var response = Map.of(
"statusCode", 200,
"headers", Map.of("Content-Type", "text/csv"),
"body", "Hello,World"
);
ObjectMapper om = new ObjectMapper();
outputStream.write(om.writeValueAsBytes(response));
outputStream.flush();
} catch(Exception e) { e.printStackTrace(); }
finally { try { outputStream.close(); } catch(Exception e) {} }
}
}
Upvotes: 4
Views: 15740
Reputation: 71
I just faced the same problem. And I discovered that even with the websocket connection open for until 2h, the processing of the API (first lambda called) will timeout in 29s.
To workaround that, you must use an async strategy. So, create a proxy that will receive the input and call the desired lambda through an SNS topic or an SQS queue.
For more info, this link is very useful: https://repost.aws/questions/QUFXpcneknSgmhseduEh18dw/api-gateway-websocket-api-30s-timeout
Upvotes: 0
Reputation: 11
It looks like a NAT Gateway is required for a Lambda to call the postToConnection function provided by the AWS ApiGatewayManagementApi SDK.
Its a shame this requirement isn't specified anywhere regarding Websockets API or API Gateway.
Search for 'NAT' on this page, and read that sentence:
Upvotes: -2
Reputation: 181
I do not think I understand your problem correctly but here is how WebSocket API work in my experience. client(s) <-(1)-> API Gateway <-(2)-> Lambda
1) is the web socket connection which stays open for a maximum of 2 hours, with idle timeout of 10 minutes as mentioned here. https://docs.aws.amazon.com/apigateway/latest/developerguide/limits.html
2 )communication is managed using @connection https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-how-to-call-websocket-api-connections.html
I believe you want to use @connection for talking to your API Gateway from lambda.
Upvotes: 3