Skip to content

Clarify relationship between messaging, faas, and RPC #652

Description

@anuraaga

I want to clarify the relationship between messaging, RPC, and FaaS which is confusing to me right now. Let me give an example, based on my understanding of the current spec, and let me know if this aligns with expectations. This is an example of lambda + sqs, something I'm working on now and is sufficiently complicated that hopefully other cases are simpler.

SQS - an HTTP-based RPC API for publishing and receiving messages
Lambda - a FaaS that can be integrated with SQS. Lambda runtime polls for messages using SQS's RPC API, and when a message comes in, it runs a function with the received batch of messages

SQS Queue - NiceQueue
Lambda function - process_function

So I can invision many spans. These are all for the same request so up to the producer spans is all in the same trace
Request - Request span for the "trace", with current span lasts until end of production
Message1 - Message 1
Message2 - Message 2
Producer1 - Producer Span for Message 1
Producer2 - Producer Span for Message 2
APIPublish1 - Client span using SQS API to send Message1
APIPublish2 - Client span using SQS API to send Message2
PollMessages - Internal, infinite? span that corresponds to the lambda runtime process itself
APIReceive - Client span using SQS API to poll for messages and receive Message 1 and 2
FaaSInitialize - Span encompassing lambda function initialization and invocation. May have cold start
FaaSInvoke - Span encompassing lambda function invocation by runtime
FaasFunction - Span encmpassing lambda function execution in user's app
Receive - Consumer span encompassing the recived batch
Process1 - Processing span for Message1
Process2 - Processing span for Message2

Trace 1
|--------------------------OrderService.ProcessOrders-------------------------|
 |NiceQueue send|                                    |NiceQueue send|
                     |SQS.SendMessage|                               |SQS.SendMessage|


Trace 2
|-------------------------pollmessages------------------------------------------------------------------------------------------|
|APIReceive||APIReceive||APIReceive||APIReceive||APIReceive||APIReceive||APIReceive|
                                                                                    |-----FaaSInitialize-----------------|                                                                                                                  
                                                                                               |---FaasInvoke--------------|
                                                                                               |---FaasFunction------------|
                                                                                                  |--Receive--------------|
                                                                                                   |Process1||Process2|

Phew lots of spans. So does it look like this?

id name kind duration parent link semantic types owner
Request OrderService.ProcessOrders SERVER 50ms none none rpc,http user
Producer1 NiceQueue send PRODUCER 0 Request none messaging user
ApiPublish1 SQS.SendMessage CLIENT 20ms Producer1 none rpc,http user
Producer2 NiceQueue send PRODUCER 0 Request none messaging user
ApiPublish2 SQS.SendMessage CLIENT 20ms Producer2 none rpc, http user
PollMessages pollmessages INTERNAL infinity none none none infra
APIReceive SQS.ReceiveMessage CLIENT 30ms PollMessages none rpc, http infra
FaaSInitialize Lambda::Initialize INTERNAL 500ms none none none infra
FaaSInvoke Lambda::Invoke INTERNAL 300ms FaasInitialize none none infra
FaaSFunction process_function INTERNAL 300ms FaaSInvoke none faas user
Receive NiceQueue receive CONSUMER 250ms FaaSFunction none messaging user
Process1 NiceQueue process CONSUMER 100ms Receive Producer1 messaging user
Process2 NiceQueue process CONSUMER 100ms Receive Producer2 messaging user

My currently open questions

  • This is an ideal case, but especially when using auto instrumentation, it may not be possible to have Process1 and Process2 - Lambda presents the entire batch to the user. Should Receive also have links to Producer1 and Producer2? Should Receive be a process span instead of a receive span?

  • How to connect the API calls and the messaging spans. Completely separate like I listed? It means there are mysterious 0 duration producer spans and APIPublish are child or PRODUCER. Or combine e.g., Producer1 and ApiPublish1? Would the name be NiceQueue.send but we still include rpc.service == SQS, rpc.method == SendMessage to not lose that information? Is such a span's kind producer or client?

  • Are FaaSInvoke and Receive separate or should be combined? In reality, if the runtime is a cloud provider, there may not be control and FaasInvoke is automatically created.

  • APIReceive is a CLIENT span so I wouldn't expect it to be a parent of the rest - is it basically an orphan span? Anyways, while I may be able to model it as a parent of something if I was implementing all this myself, it wouldn't be for lambda = SQS.

Appreciate any guidance :)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions