我在SNS主题中创建了Http订阅。 SNS订阅中提到的网址是一个EC2实例。
需要知道在EC2实例中将从何处接收SNS订阅请求。
要订阅http请求,我必须在EC2中安装哪些应用程序。使用的端口是8080。
答案 0 :(得分:0)
如基于SNS HTTP(S)的Amazon Doc订阅中所述...... more
在为主题订阅HTTP或HTTPS终端节点之前,必须确保HTTP或HTTPS终端节点可以处理Amazon SNS用于发送订阅确认和通知消息的HTTP POST请求。当您订阅HTTP终端节点时,Amazon SNS向其发送订阅确认请求。创建预订时,您的端点必须准备好接收和处理此请求,因为 Amazon SNS当时发送了此请求。在您确认订阅之前,Amazon SNS不会将通知发送到终端。确认订阅后,当对已订阅主题执行发布操作时,Amazon SNS将向终端发送通知。
在处理 SubscriptionConfirmation 请求之前,状态始终为待确认状态,并且不会收到任何 Notification 消息。
以下是自动处理 SubscriptionConfirmation , Notification 和 UnsubscribeConfirmation messageType请求以及 Content-Type 的代码段>对于由AWS SNS触发的上述请求,始终采用 文本/纯文本 格式。
使用带有以下代码的SNS使用者使用Spring-boot的主要优点是,您无需依赖任何AWS指定配置及其依赖项。如果您的微服务是使用spring-boot
而不是spring-cloud-aws-messaging
构建的,则这是一种实用的方法。客户方应用程序中需要执行以下步骤。
将以下注释添加到请求处理程序方法中以进行处理 SubscriptionConfirmation 和 UnsubscribeConfirmation messageType。
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface SNSSubscriptionUnSubscriptionConfirmation {
}
如果使用@SNSSubscriptionUnSubscriptionConfirmation,
注释的请求处理程序方法将触发以下方面,则该方法将处理基于Http的 SubscriptionConfirmation 和 UnsubscribeConfirmation messageTypes (s)请求标头x-amz-sns-message-type
。
@Aspect
@Component
@Slf4j
public class SNSSubscriptionUnSubscriptionActivation {
@Before(value = "@annotation(SNSSubscriptionUnSubscriptionConfirmation)")
public void SNSSubscriptionUnSubscriptionConfirmationActivation(JoinPoint joinPoint) {
Object[] args = joinPoint.getArgs();
HttpServletRequest httpServletRequest = (HttpServletRequest)args[0];
String requestBody = (String)args[1];
String messageType = httpServletRequest.getHeader("x-amz-sns-message-type");
String topicArn = httpServletRequest.getHeader("x-amz-sns-topic-arn");
if(!StringUtils.isEmpty(messageType)){
if("SubscriptionConfirmation".equals(messageType)){
activateSNSSubscriptionUnSubscription(requestBody, messageType, topicArn, "SubscribeURL");
} else if("UnsubscribeConfirmation".equals(messageType)){
activateSNSSubscriptionUnSubscription(requestBody, messageType, topicArn, "UnsubscribeURL");
}
}
}
private void activateSNSSubscriptionUnSubscription(String requestBody, final String messageType, String topicArn, String subscribeUnsubscribeURLKey) {
log.info(messageType + " payload: {}", requestBody);
JsonMapper mapper = JsonMapper.builder()
.configure(JsonReadFeature.ALLOW_UNQUOTED_FIELD_NAMES, true)
.build();
try {
Map<String, String> maps = mapper.readValue(requestBody, new TypeReference<Map<String, String>>() {
});
String subscribeUnsubscribeURL = maps.get(subscribeUnsubscribeURLKey);
RestTemplate restTemplate = new RestTemplate();
//Manually activating the subscribe and UnsubscribeURL requests by making direct HTTP call using rest controller
ResponseEntity<Void> response = restTemplate.exchange(subscribeUnsubscribeURL, HttpMethod.GET, null, Void.class);
if (response.getStatusCode().is2xxSuccessful())
log.info("topicArn: {} messageType: {} Successful: {}", topicArn, messageType, response.getStatusCode());
else {
log.error("topicArn: {} messageType: {} failure Status: {}", topicArn, messageType, response.getStatusCode());
}
} catch (JsonProcessingException e){
log.error("topicArn: {} messageType: {} failure error: {}", topicArn, messageType, e.getMessage());
}catch(HttpClientErrorException e) {
log.error("topicArn: {} messageType: {} failure error: {}", topicArn, messageType, e.getResponseBodyAsString());
}
}
}
控制器的处理程序方法处理 Notification (消息类型),因为其余两个messageTypes由SNSSubscriptionUnSubscriptionActivation
处理,作为带有@SNSSubscriptionUnSubscriptionConfirmation()
注释的请求处理程序方法。
@Slf4j
@RestController
public class AWSSNSConsumerController {
@PostMapping(value = "subscribed-endpoint", consumes = MediaType.TEXT_PLAIN_VALUE)
@SNSSubscriptionUnSubscriptionConfirmation()
public ResponseEntity<Void> notification(HttpServletRequest httpServletRequest, @RequestBody() String requestBody) {
log.info("Notification payload: {}", requestBody);
String topicArn = httpServletRequest.getHeader("x-amz-sns-topic-arn");
String messageType = httpServletRequest.getHeader("x-amz-sns-message-type");
if ("Notification".equals(messageType)) {
JsonMapper mapper = JsonMapper.builder()
.configure(JsonReadFeature.ALLOW_UNQUOTED_FIELD_NAMES, true)
.build();
try {
Map<String, String> maps = mapper.readValue(requestBody, new TypeReference<Map<String, String>>() {
});
String message = maps.get("Message");
log.info("topic : {} message: {} ", topicArn, message);
} catch (JsonProcessingException e) {
log.error("topic : {} Notification failure error: {}", topicArn, e.getMessage());
} catch (HttpClientErrorException e) {
log.error("topic : {} Notification failure error: {}", topicArn, e.getResponseBodyAsString());
}
}
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
}
如果您使用的是 spring-cloud-aws ,请遵循此出色的tutorial