向微服务发送异步消息

Send Async message to microservice

我有一个 BE 服务 A,它使用 Feign 客户端向微服务 B 发送 Rest JSON 消息:

@FeignClient(name = "mail-service")
@LoadBalancerClient(name = "mail-service", configuration = LoadBalancerConfiguration.class)
public interface EmailClient {

    @RequestMapping(method = RequestMethod.POST, value = "/engine/emails/register")
    void setUserRegistration(CreateUserDTO createUserDTO);
}

端点:

@RestController
@RequestMapping("/emails")
public class EmailController {

    @RequestMapping(method = RequestMethod.POST, value = "/register", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<?> register(@Valid @RequestBody CreateUserDTO createUserDTO) {

        emailRestService.processCreateUserMessage(createUserDTO);
        // Implementation of service to send mail to AWS SES
        return new ResponseEntity<>(HttpStatus.OK);
    }
}

Rest Endpoint 正在向 AWS Ses 邮件或其他邮件提供商发送邮件。

问题是 Feign 的拳头调用可能需要 5 秒或更长时间。我需要让它异步,以便 FE 客户端不等待邮件发送。

我如何才能使从 Feign Async 发出的 Rest 调用没有预期的 HTTP 响应 OK 等待时间?有没有更好的解决方案来实现这个?

AFAIK,Feign 不允许非阻塞 IO,它是 work in progress

但是您可以实现 EmailRestService 异步。考虑以下代码(我不知道 processCreateUserMessage 是否也负责发送电子邮件,但建议的解决方案应在必要时在功能上扩展到该代码):

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

//...

@Service
public class EmailRestServiceImpl implements EmailRestService {
  //...
  
  @Async
  public void processCreateUserMessage(CreateUserDTO createUserDTO) {
    // Implementation of service to send mail to AWS SES
    // ...
  }

}

请注意 @Async 注释定义。

要启用 Spring 异步处理,您需要在主配置或特定配置中定义 @EnableAsync 注释:

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;

@Configuration
@EnableAsync
public class AsyncConfiguration {

}

无需更改 Controller,但如果您愿意,可以 return 更方便的 HTTP 状态代码:

@RestController
@RequestMapping("/emails")
public class EmailController {

    @RequestMapping(method = RequestMethod.POST, value = "/register", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<?> register(@Valid @RequestBody CreateUserDTO createUserDTO) {
        // Will be executed asynchronously and return immediately
        emailRestService.processCreateUserMessage(createUserDTO);
        return new ResponseEntity<>(HttpStatus.ACCEPTED);
    }
}