Propagate traceId from Microservice and Kafka - spring

I am using Spring Sleuth to generate logs that gets me traceId and spanId. I want to propagate these to Kafka topic, maybe in the header, and from there to another microservice that will consume from the header through that topic, so that traces are consistent for the same payload. Are there any properties I can configure to make this work?

Related

Kafka Transactions in Interceptors in streams with EOS

We are using spring kafka streams for processing data streams. We are currently using the processing.guarantee: exactly_once configuration to make sure it adheres to Exactly-once semantics of data processing.
We have a new requirement to have some metadata emitted via interceptors. The interceptor uses kafka template to publish metadata (mostly skimming header data of messages) to a kafka topic.
The reason to have it on interceptor is the pipeline to process streams, including multiple applications/topic and it would be easy to wire the interceptors to individual apps.
Question I have is, will the kafka template used in my interceptor require #Transactional annotation or will it use the transaction semantics generated by processing.gaurantee config. And will it be able to rollback data and not commit when primary streams consumer/producer failed to commit?
Any pointers towards this is highly appreciated.
The KafkaTemplate cannot participate in the stream's transaction. It would need a separate transaction, which would break EOS.
For exactly once, either everything has to be done with streams, or everything with spring-kafka.

Spring Sleuth Zipkin Extra Field Propagation

I am new to distributed logging and I need help around the propagation of extra fields across Http Request and Messaging Request.
Currently, I am able to propagate the traceId and spanId, but I need to pass correlationId to be propagated across all the microservices.
spring:
sleuth:
correlation-fields:
- x-correlation-id
remote-fields:
- x-correlation-id
logback.xml
%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p [${appName},%X{traceId:-},%X{parentId:-},%X{spanId:-},%X{correlation-id:-}]) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%t]){faint} %clr(%logger{20}:%line){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}
I am a bit curious about how to pass the correlation id to other services.
In case the message starts from Service A -
Service A (Message Started,CorrelationID-123) -> ServiceB (CorrelationID-123) -> ServiceC(CorrelationID-123)
In case if it started with Service B
Service B (Message Started,CorrelationID-123) -> ServiceA (CorrelationID-123) -> ServiceC(CorrelationID-123)
How the correlation id will be passed to Kafka messages?
How the correlation id will be passed to Http requests?
Is it possible to use existing tracedId from other service?
I think what you call correlationId is in fact the traceId, if you are new to distributed tracing, I highly recommend reading the docs of spring-cloud-sleuth, the introduction section will give you a basic understanding while the propagation will tell you well, how your fields are propagated across services.
I also recommend this talk: Distributed Tracing: Latency Analysis for Your Microservices - Grzejszczak, Krishna.
To answer your exact questions:
How the correlation id will be passed to Kafka messages?
Kafka has headers, I assume the fields are propagated through Kafka headers.
How the correlation id will be passed to Http requests?
Through HTTP Headers.
Is it possible to use existing tracedId from other service?
Not just possible, Sleuth does this for you out of the box. If there is a traceId in the incoming request/message/event/etc. Sleuth will not create a new one but it will use it (see the docs I linked above).

Get underlying low-level Kafka consumers and Producers in Spring Cloud Stream

I have a usecase where I want to get the underlying Kafka producer (KafkaTemplate) in a Spring Cloud Stream application. While navigating the code I stumbled upon KafkaProducerMessageHandler which has a getKafkaTemplate method. However, it fails to auto-wire.
Also, if I directly auto-wire KafkaTemplate, the template is initialized with default properties and it ignores the broker in the binder key of the SCSt configuration
How can I access the underlying KafkaTemplate or a producer/consumer in a Spring Cloud Stream app?
EDIT: Actually my SCSt app has multiple Kafka binders and I want to get the KafkaTemplate or Kafka producer corresponding to each binder. Is that possible somehow?
It's not entirely clear why you would need to do that, but you can capture the KafkaTemplates by adding a ProducerMessageHandlerCustomizer #Bean to the application context.

Spring Integration - Kafka Message Driven Channel - Auto Acknowledge

I have used the sample configuration as was listed in the spring io docs and it is working fine.
<int-kafka:message-driven-channel-adapter
id="kafkaListener"
listener-container="container1"
auto-startup="false"
phase="100"
send-timeout="5000"
channel="nullChannel"
message-converter="messageConverter"
error-channel="errorChannel" />
However, when i was testing it with downstream application where i consume from kafka and publish it to downstream. If downstream is down, the messages were still getting consumed and was not replayed.
Or lets say after consuming from kafka topic , in case i find some exception in service activator, i want to throw some exception as well which should rollback the transaction so that kafka messages can be replayed.
In brief, if the consuming application is having some issue , then i want to roll back the transaction so that messages are not automatically acknowledged and are replayed back again and again unless it is succesfuly processed.
That's not how Apache Kafka works. There is the TX semantics similar to JMS. The offset in Kafka topic has nothing with rallback or redelivery.
I suggest you to study Apache Kafka closer from their official resource.
Spring Kafka brings nothing over the regular Apache Kafka protocol, however you can consider to use retry capabilities in the Spring Kafka to redeliver the same record locally : http://docs.spring.io/spring-kafka/docs/1.2.2.RELEASE/reference/html/_reference.html#_retrying_deliveries
And yes, the ack mode must be MANUAL, do not commit offset into the Kafka automatically after consuming.

Spring Cloud DataFlow for HTTP request/response exchange

I would like to use streams to handle an HTTP request/response exchange. I didn't see any Spring Cloud Stream App Starters with HTTP sink functionality. Will I need to build a custom sink to handle the response? If so, do I pass the request through my processing pipeline, then use the request in my sink to form the response? I don't think I've misunderstood the use case of Spring Cloud DataFlow and Spring Cloud Stream. Perhaps there are app starters available for this pattern.
Spring Cloud Stream/Dataflow is for unidirectional (stream) processing; it is not intended for request/reply processing.
You could, however, utilize a Stream from a Spring Integration Application; for example, with the rabbitmq binder...
http-inbound-gateway -> amqp-outbound-gateway
Where the outbound gateway is configured to expect the reply from a specific queue and then your stream could be...
:requestQueue > processor1 | ... | processorn > :replyQueue
Spring Integration doesn't currently have an outbound gateway for Kafka. I opened an issue.

Resources