我的应用程序配置为在收到请求发送 SQS 的 HTTP 调用时为 sqs 添加子段。
我已按照 AWS 指南 [1] 添加了库。
这样就可以添加发送消息的子分段,而无需使用 @SQSListner 接收消息。
但是,我一直在使用 @SQSListner 实现 AWS xray,并出现以下错误。
我已经尝试在启动 receiveMessage 之前添加 AOP 切入点以创建名为“AmazonSQS”的子段。
但是,这不是我期望的工作,这就是我注册这张票的原因。
如果您已使用@SQSListener 实现或了解我的错误以及如何修复它,请指导我。
java.lang.RuntimeException: Failed to begin subsegment named 'AmazonSQS': segment cannot be found.
at com.amazonaws.xray.strategy.LogErrorContextMissingStrategy.contextMissing(LogErrorContextMissingStrategy.java:36)
at com.amazonaws.xray.contexts.ThreadLocalSegmentContext.beginSubsegment(ThreadLocalSegmentContext.java:39)
at com.amazonaws.xray.AWSXRayRecorder.beginSubsegment(AWSXRayRecorder.java:616)
at com.amazonaws.xray.handlers.TracingHandler.beforeRequest(TracingHandler.java:186)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.runBeforeRequestHandlers(AmazonHttpClient.java:853)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:794)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:781)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:755)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.access$500(AmazonHttpClient.java:715)
at com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.java:697)
at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:561)
at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:541)
at com.amazonaws.services.sqs.AmazonSQSClient.doInvoke(AmazonSQSClient.java:2329)
at com.amazonaws.services.sqs.AmazonSQSClient.invoke(AmazonSQSClient.java:2296)
at com.amazonaws.services.sqs.AmazonSQSClient.invoke(AmazonSQSClient.java:2285)
at com.amazonaws.services.sqs.AmazonSQSClient.executeReceiveMessage(AmazonSQSClient.java:1715)
at com.amazonaws.services.sqs.AmazonSQSClient.receiveMessage(AmazonSQSClient.java:1683)
at org.springframework.cloud.aws.messaging.listener.SimpleMessageListenerContainer$AsynchronousMessageListener.run(SimpleMessageListenerContainer.java:336)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
2023-09-19 09:51:05.731 ERROR 11360 --- [enerContainer-1] c.a.x.s.LogErrorContextMissingStrategy : Suppressing AWS X-Ray context missing exception (SegmentNotFoundException): No segment in progress.
2023-09-19 09:51:05.731 DEBUG 11360 --- [enerContainer-1] c.a.x.s.LogErrorContextMissingStrategy : Attempted to find context at:
java.lang.RuntimeException: No segment in progress.
at com.amazonaws.xray.strategy.LogErrorContextMissingStrategy.contextMissing(LogErrorContextMissingStrategy.java:36)
at com.amazonaws.xray.AWSXRayRecorder.getCurrentSegment(AWSXRayRecorder.java:668)
at com.amazonaws.xray.handlers.TracingHandler.beforeRequest(TracingHandler.java:194)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.runBeforeRequestHandlers(AmazonHttpClient.java:853)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:794)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:781)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:755)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.access$500(AmazonHttpClient.java:715)
at com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.java:697)
at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:561)
at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:541)
at com.amazonaws.services.sqs.AmazonSQSClient.doInvoke(AmazonSQSClient.java:2329)
at com.amazonaws.services.sqs.AmazonSQSClient.invoke(AmazonSQSClient.java:2296)
at com.amazonaws.services.sqs.AmazonSQSClient.invoke(AmazonSQSClient.java:2285)
at com.amazonaws.services.sqs.AmazonSQSClient.executeReceiveMessage(AmazonSQSClient.java:1715)
at com.amazonaws.services.sqs.AmazonSQSClient.receiveMessage(AmazonSQSClient.java:1683)
at org.springframework.cloud.aws.messaging.listener.SimpleMessageListenerContainer$AsynchronousMessageListener.run(SimpleMessageListenerContainer.java:336)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
[1] https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-java-aop-spring.html
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-bom</artifactId>
<version>1.12.468</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-xray-recorder-sdk-bom</artifactId>
<version>2.14.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- (...) -->
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-aws</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-aws-messaging</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-sqs</artifactId>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>amazon-sqs-java-messaging-lib</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-xray-recorder-sdk-core</artifactId>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-xray-recorder-sdk-apache-http</artifactId>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-xray-recorder-sdk-aws-sdk</artifactId>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-xray-recorder-sdk-aws-sdk-instrumentor</artifactId>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-xray-recorder-sdk-sql-postgres</artifactId>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-xray-recorder-sdk-slf4j</artifactId>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-xray-recorder-sdk-spring</artifactId>
</dependency>
</dependencies>
@RequiredArgsConstructor
@Service
@XRayEnabled
public class AmazonSQSSenderImpl implements AmazonSQSSender {
@Value("${cloud.aws.sqs.queue.url}")
private String url;
private final ObjectMapper objectMapper;
private final AmazonSQS amazonSQS;
/**
* Send message
*/
@Override
public SendMessageResult sendMessage1(EcmDto msg) throws JsonProcessingException {
Map<String, MessageAttributeValue> messageAttributes = new HashMap<>();
messageAttributes.put("AttributeOne", new MessageAttributeValue()
.withStringValue("This is an attribute sendMessage1")
.withDataType("String"));
SendMessageRequest sendMessageStandardQueue = new SendMessageRequest()
.withQueueUrl(url)
.withMessageBody(objectMapper.writeValueAsString(msg))
.withMessageAttributes(messageAttributes);
return amazonSQS.sendMessage(sendMessageStandardQueue);
}
}
@Slf4j
@Service
@RequiredArgsConstructor
@XRayEnabled
public class AwsSqsListener {
@SqsListener(value = "${cloud.aws.sqs.queue.url}", deletionPolicy = SqsMessageDeletionPolicy.NEVER)
public void listenUdwrDemd(@Payload String info, @Headers Map<String, String> headers, Acknowledgment ack) {
log.info("-------------------------------------start SqsListener url");
log.info("-------------------------------------info {}", info);
log.info("-------------------------------------headers {}", headers);
ack.acknowledge();
}
}
@Aspect
@Component
public class XRayInspector extends BaseAbstractXRayInterceptor {
@Override
protected Map<String, Map<String, Object>> generateMetadata(ProceedingJoinPoint proceedingJoinPoint, Subsegment subsegment) {
return super.generateMetadata(proceedingJoinPoint, subsegment);
}
@Override
@Pointcut("@within(com.amazonaws.xray.spring.aop.XRayEnabled) && bean(*Controller)")
public void xrayEnabledClasses() {
}
}
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Value("${spring.application.name}")
String applicationName;
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*");
}
@Bean
public Filter tracingFilter() {
return new AWSXRayServletFilter(applicationName.toUpperCase());
}
}
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication api = new SpringApplication(Application.class);
api.addListeners(new ApplicationPidFileWriter());
api.run(args);
}
}
使用 @SQSListener 为 AWS Xray 实施创建子分段
XRay 数据模型要求子段必须有一个父段,该父段是从 ThreadLocal 检索的,否则用户会收到
ContextMissing
错误。
您能否尝试按照 X-Ray 文档 来检测传入请求?它将自动为传入请求生成分段,并且稍后将成为 SQS 子分段的父分段。