在java中发送邮件花费太多时间,我如何克服这一问题
在我的spring boot项目中,我有一个功能,发送电子邮件,在电子邮件中,在事务中发送要花费太多的时间在java中发送邮件花费太多时间,我如何克服这一问题,java,email,spring-boot,Java,Email,Spring Boot,在我的spring boot项目中,我有一个功能,发送电子邮件,在电子邮件中,在事务中发送要花费太多的时间 //service layer @Transaction function inviteUser() { // insert in invitation table // insert in invitation sub-table // sending mail to user (30 seconds) } 发送邮件大约需要30
//service layer
@Transaction
function inviteUser() {
// insert in invitation table
// insert in invitation sub-table
// sending mail to user (30 seconds)
}
发送邮件大约需要30秒,我如何克服这一点。有没有其他特定的方法来实现这类功能。在应用程序中,我们通常必须从各种来源获取数据,例如第三方Web服务、分布式数据通道,甚至是在我们的应用程序微服务中,这些微服务是跨网络分布的。让我们假设一个场景,在这个场景中,您需要从多个源获取数据,并将其合并为单个结果并返回给调用者。例如,我们有GetMyDataService,它调用以下服务: 服务1->从webservices mywebservice.com获取数据(响应时间10秒,超时15秒) 服务2->从第三方api获取数据,www.free.com/api/getData(响应时间5秒,超时15秒) 服务3->从您自己的微服务/myMicroservice/api/getData中获取数据(响应时间1秒,超时15秒) 因此,在同步模式下,GetMyDataService至少需要10+5+1=16秒,即使这三个服务都正常运行。假设服务1和服务2已关闭。现在GetMyDataService的响应时间将是15+15+1=31秒以获得响应。(响应仅包括服务3的结果) 如果没有配置超时怎么办???应用程序将被挂起,永远等待响应 为了克服上述情况,有来自Netflix的救援者“Hystrix”。在本项目中,我们将演示以下解决方案: GetMyDataService将调用所有3个服务,超时时间为15秒。我们将在最多15秒或更短的时间内收到任何响应。 在任何服务失败或超时时,我们都会回退,中断正在等待服务的线程并返回空白结果 有关Hystrix检查的详细说明:
@服务
公共类邮件服务扩展了HystrixCommand{
受保护的邮件服务(){
super(HystrixCommandGroupKey.Factory.asKey(MailService.class.getSimpleName());
}
受保护的布尔getFallback(){
返回新的布尔值;
}
@凌驾
受保护的列表运行()引发异常{
//在这里寄信
}
}
用这个来称呼它
@Service
public class MyService {
@Autowired
MailService mailService;
public Boolean sendMail() throws InterruptedException, ExecutionException {
Boolean isMailSend=new Boolean;
Observable.merge(mailService.observe().subscribeOn(Schedulers.io())).toBlocking().subscribe(new Action1<Boolean>() {
@Override
public void call(Boolean b) {
isMailSend = b;
}
});
return isMailSend;
}
}
@服务
公共类MyService{
@自动连线
邮递服务;
public Boolean sendMail()引发InterruptedException,ExecutionException{
布尔值isMailSend=新布尔值;
Observable.merge(mailService.Observable().subscribeOn(Schedulers.io()).toBlocking().subscribe(new Action1()){
@凌驾
公共无效调用(布尔b){
isMailSend=b;
}
});
返回isMailSend;
}
}
在应用程序中,我们通常必须从各种来源获取数据,如第三方Web服务、分布式数据通道,甚至是在我们的应用程序微服务中,这些微服务是跨网络分布的。让我们假设一个场景,在这个场景中,您需要从多个源获取数据,并将其合并为单个结果并返回给调用者。例如,我们有GetMyDataService,它调用以下服务:
服务1->从webservices mywebservice.com获取数据(响应时间10秒,超时15秒)
服务2->从第三方api获取数据,www.free.com/api/getData(响应时间5秒,超时15秒)
服务3->从您自己的微服务/myMicroservice/api/getData中获取数据(响应时间1秒,超时15秒)
因此,在同步模式下,GetMyDataService至少需要10+5+1=16秒,即使这三个服务都正常运行。假设服务1和服务2已关闭。现在GetMyDataService的响应时间将是15+15+1=31秒以获得响应。(响应仅包括服务3的结果)
如果没有配置超时怎么办???应用程序将被挂起,永远等待响应
为了克服上述情况,有来自Netflix的救援者“Hystrix”。在本项目中,我们将演示以下解决方案:
GetMyDataService将调用所有3个服务,超时时间为15秒。我们将在最多15秒或更短的时间内收到任何响应。
在任何服务失败或超时时,我们都会回退,中断正在等待服务的线程并返回空白结果
有关Hystrix检查的详细说明:
@服务
公共类邮件服务扩展了HystrixCommand{
受保护的邮件服务(){
super(HystrixCommandGroupKey.Factory.asKey(MailService.class.getSimpleName());
}
受保护的布尔getFallback(){
返回新的布尔值;
}
@凌驾
受保护的列表运行()引发异常{
//在这里寄信
}
}
用这个来称呼它
@Service
public class MyService {
@Autowired
MailService mailService;
public Boolean sendMail() throws InterruptedException, ExecutionException {
Boolean isMailSend=new Boolean;
Observable.merge(mailService.observe().subscribeOn(Schedulers.io())).toBlocking().subscribe(new Action1<Boolean>() {
@Override
public void call(Boolean b) {
isMailSend = b;
}
});
return isMailSend;
}
}
@服务
公共类MyService{
@自动连线
邮递服务;
public Boolean sendMail()引发InterruptedException,ExecutionException{
布尔值isMailSend=新布尔值;
Observable.merge(mailService.Observable().subscribeOn(Schedulers.io()).toBlocking().subscribe(new Action1()){
@凌驾
公共无效调用(布尔b){
isMailSend=b;
}
});
返回isMailSend;
}
}
在spring boot中,您可以使用@Async annotation
@Transactional
public void register() {
//after success call that method
emailService.sendWelcomeMail();
}
@Service
@Configuration
@EnableAsync
public class EmailService {
// for sending email
@Async
public void sendWelcomeMail(){}
}
在spring boot中,您可以使用@Async注释
@Transactional
public void register() {
//after success call that method
emailService.sendWelcomeMail();
}
@Service
@Configuration
@EnableAsync
public class EmailService {
// for sending email
@Async
public void sendWelcomeMail(){}
}
根据@Kayaman和@JerryChin的评论,可能不需要在DB事务中发送电子邮件: //服务层
// Inject r/w transaction template.
// No @Transactional annotation
function inviteUser() {
txTemplate.execute(new TransactionCallback<Object>() {
public Object doInTransaction(TransactionStatus txStatus) {
// insert in invitation table
// insert in invitation sub-table
...
}
});
// sending mail to user
}
//注入r/w事务模板。
//无@Transactional注释
函数inviteUser(){
execute(新TransactionCallback(){
公共对象doInTransaction(TransactionStatus txStatus){
//在邀请表中插入
//在邀请子表中插入
...
}
});
//向用户发送邮件
}
卡亚曼和杰里钦评论了什么