无法使用 @SQSListener 为 AWS Xray 创建子分段

问题描述 投票:0回答:1

我的应用程序配置为在收到请求发送 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

示例代码和配置

pom.xml

<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>

AmazonSQSSenderImpl.java

@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);
  }
}

AwsSqsListener.java

@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();
  }
}

XRayInspector.java

@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() {
  }
}

WebConfig.java

@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());
  }
}

应用程序.java

@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 实施创建子分段

spring-boot spring-aop aws-xray sqslistener
1个回答
0
投票

XRay 数据模型要求子段必须有一个父段,该父段是从 ThreadLocal 检索的,否则用户会收到

ContextMissing
错误。

您能否尝试按照 X-Ray 文档 来检测传入请求?它将自动为传入请求生成分段,并且稍后将成为 SQS 子分段的父分段。

© www.soinside.com 2019 - 2024. All rights reserved.