本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
在工作线程中使用检测的客户端
当用户在游戏中获胜后,Scorekeep 使用工作线程向 Amazon SNS 发布通知。发布通知的时间会比请求操作其余部分的总时间更长,并且不会影响客户端或用户。因此,以异步方式执行任务是一种改进响应时间的好方法。
但是,在创建线程时,适用于 Java 的 X-Ray 开发工具包不知道哪个分段处于活动状态。因此,当您尝试在线程中使用检测的AWS SDK for Java客户端时,它将引发 SegmentNotFoundException
,从而导致线程崩溃。
例 Web-1.error.log
Exception in thread "Thread-2" com.amazonaws.xray.exceptions.SegmentNotFoundException: Failed to begin subsegment named 'AmazonSNS': segment cannot be found.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
...
为了解决这个问题,应用程序使用 GetTraceEntity
来获取对主线程中的分段的引用,并获取 Entity.run()
以安全地运行包含对该分段的上下文具有访问权限的工作线程代码。
例 src/main/java/scorekeep/MoveFactory.java
- 将跟踪上下文传递到工作线程
import com.amazonaws.xray.AWSXRay;
import com.amazonaws.xray.AWSXRayRecorder;
import com.amazonaws.xray.entities.Entity;
import com.amazonaws.xray.entities.Segment;
import com.amazonaws.xray.entities.Subsegment;
...
Entity segment = recorder.getTraceEntity();
Thread comm = new Thread() {
public void run() {
segment.run(() -> {
Subsegment subsegment = AWSXRay.beginSubsegment("## Send notification");
Sns.sendNotification("Scorekeep game completed", "Winner: " + userId);
AWSXRay.endSubsegment();
}
}
现在,由于请求在对 Amazon SNS 的调用前已解析,应用程序会为线程创建一个单独的子分段。这可以防止 X-Ray 开发工具包在记录来自 Amazon SNS 的响应之前关闭分段。如果在 Scorekeep 解析请求时未打开任何子分段,来自 Amazon SNS 的响应可能会丢失。
有关多线程处理的更多信息,请参阅在多线程应用程序中的线程之间传递分段上下文。