New Lambda streaming, can't get basic demos to work as expected, TTFB = full running time

3

Hello everyone,

I've been toying with the newly introduced response streaming for my application.

I managed to get both functionurls and @aws-sdk invocation to return the payloads... But there's no actual streaming happening.

The behaviour I'm observing is as follows:

  • Function is called
  • Data is streamed inside the function
  • When the stream is FINISHED, the data gets pushed out of the function all at once.

This appears to be the case no matter if I invoke with a function URL or with @aws-sdk.

I then proceeded to clone and deploy the example here: https://github.com/aws-samples/serverless-patterns/tree/main/lambda-streaming-ttfb-write-sam

Literally just executed sam deploy and followed the instructions (deploying in us-east-1). Results appear to be absolutely identical (no streaming whatsoever in practice).

I attach my testing results with cURL

$ curl --request GET 'https://an6ke7jhzxvqceai5dcem3p3yu0xxfvk.lambda-url.us-east-1.on.aws/' --user <omitted>  --aws-sigv4 'aws:amz:us-east-1:lambda' -vkN -w "Connect: %{time_connect} TTFB: %{time_starttransfer} Total time: %{time_total} \n"
Note: Unnecessary use of -X or --request, GET is already inferred.
*   Trying 34.237.128.22:443...
* Connected to an6ke7jhzxvqceai5dcem3p3yu0xxfvk.lambda-url.us-east-1.on.aws (34.237.128.22) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS header, Finished (20):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS header, Finished (20):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server did not agree to a protocol
* Server certificate:
*  subject: CN=*.lambda-url.us-east-1.on.aws
*  start date: Jan 25 00:00:00 2023 GMT
*  expire date: Feb 24 23:59:59 2024 GMT
*  issuer: C=US; O=Amazon; CN=Amazon RSA 2048 M02
*  SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
* Server auth using AWS_SIGV4 with user '<omitted>'
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
> GET / HTTP/1.1
> Host: an6ke7jhzxvqceai5dcem3p3yu0xxfvk.lambda-url.us-east-1.on.aws
> Authorization: <omitted>
> X-Amz-Date: 20230428T135031Z
> User-Agent: curl/7.81.0
> Accept: */*
>
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Fri, 28 Apr 2023 13:50:35 GMT
< Content-Type: text/html
< Transfer-Encoding: chunked
< Connection: keep-alive
< x-amzn-RequestId: 1158cbe9-5b6b-4071-9ee1-e5f1d47a935d
< x-custom-header: Example-Custom-Header
< X-Amzn-Trace-Id: root=1-644bcf27-0b4f283715bc43f77c6f5e95;sampled=0
<
<html><p>First write2!</p><h1>Streaming h1</h1><h2>Streaming h2</h2><h3>Streaming h3</h3><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque vitae mi tincidunt tellus ultricies dignissim id et diam. Morbi pharetra eu nisi et finibus. Vivamus diam nulla, vulputate et nisl cursus, pellentesque vehicula libero. Cras imperdiet lorem ante, non posuere dolor sollicitudin a. Vestibulum ipsum lacus, blandit nec augue id, lobortis dictum urna. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Morbi auctor orci eget tellus aliquam, non maximus massa porta. In diam ante, pulvinar aliquam nisl non, elementum hendrerit sapien. Vestibulum massa nunc, mattis non congue vitae, placerat in quam. Nam vulputate lectus metus, et dignissim erat varius a.</p><p>DONE!</p>* TLSv1.2 (IN), TLS header, Supplemental data (23):
* Connection #0 to host an6ke7jhzxvqceai5dcem3p3yu0xxfvk.lambda-url.us-east-1.on.aws left intact
Connect: 0.081320 TTFB: 4.397358 Total time: 4.397620

It seems that TTFB is basically exactly equal to the full runtime of the function.

Same result with @aws-sdk

import { Lambda, InvokeWithResponseStreamCommand } from "@aws-sdk/client-lambda"
import { Readable, Transform } from "stream"
const test = async () => {
    const lambda = new Lambda({});    
    console.log(Date.now())
    const r = await lambda.send(new InvokeWithResponseStreamCommand({ FunctionName: "lambda-streaming-ttfb-write-sam-StreamingFunction-F2fitaTVUmF3" }));
    console.log(r)
    for await (const event of r.EventStream) {
        console.log("received", Date.now())
        console.log(Buffer.from(event.PayloadChunk?.Payload ?? "<end>").toString("utf-8"))
    }
};

test()

and the output

1682689911868
{
  '$metadata': {
    httpStatusCode: 200,
    requestId: '6d33da19-738c-4a85-8ab3-2490fb9d926d',
    extendedRequestId: undefined,
    cfId: undefined,
    attempts: 1,
    totalRetryDelay: 0
  },
  ExecutedVersion: '$LATEST',
  ResponseStreamContentType: 'application/vnd.amazon.eventstream',
  EventStream: {
    [Symbol(Symbol.asyncIterator)]: [AsyncGeneratorFunction: [Symbol.asyncIterator]]
  },
  StatusCode: 200
}
received 1682689916354
{"statusCode":200,"headers":{"Content-Type":"text/html","X-Custom-Header":"Example-Custom-Header"}}<html><p>First write2!</p><h1>Streaming h1</h1>
received 1682689916355
<h2>Streaming h2</h2>
received 1682689916355
<h3>Streaming h3</h3>
received 1682689916355
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque vitae mi tincidunt tellus ultricies dignissim id et diam. Morbi pharetra eu nisi et finibus. Vivamus diam nulla, vulputate et nisl cursus, pellentesque vehicula libero. Cras imperdiet lorem ante, non posuere dolor sollicitudin a. Vestibulum ipsum lacus, blandit nec augue id, lobortis dictum urna. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Morbi auctor orci eget tellus aliquam, non maximus massa porta. In diam ante, pulvinar aliquam nisl non, elementum hendrerit sapien. Vestibulum massa nunc, mattis non congue vitae, placerat in quam. Nam vulputate lectus metus, et dignissim erat varius a.</p>
received 1682689916356
<p>DONE!</p>
received 1682689916356
<end>

Note the timestamps are essentially identical and the TTFB is basically equal to the runtime.

Are there any special caveats, or special adjustment needed, or explicit request to be made, for the actual streaming function to be enabled? The results above are for the example repos, deployed without modifying anything (I just wrote some code to test the output).

Because the current situation appears to be that TTFB is completely unaffacted by this setup.

  • Can you please post your code to make sure there is no coding issue?

asked a year ago508 views
3 Answers
2
Accepted Answer

I had the same issue. I swapped my region from US-EAST-1 to US-EAST-2 and the same code worked like charm! Either this feature is broken in US-EAST-1 or it may not be available yet (contrary to the announcements)

answered a year ago
0

I have the same issue!

answered a year ago
-1

To indicate to the runtime that Lambda should stream your function’s responses, you must wrap your function handler with the streamifyResponse() decorator. This tells the runtime to use the correct stream logic path, allowing the function to stream responses.

RESPONSE_STREAM enables your function to stream payload results as they become available if you wrap the function with the streamifyResponse() decorator. Lambda invokes your function using the InvokeWithResponseStream API. If InvokeWithResponseStream invokes a function that is not wrapped with streamifyResponse(), Lambda does not stream the response and instead returns a buffered response which is subject to the 6 MB size limit.

Reference : https://aws.amazon.com/blogs/compute/introducing-aws-lambda-response-streaming/

profile pictureAWS
EXPERT
answered a year ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions