You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot调用AWS SES发送邮件速度慢的问题求助

Spring Boot调用AWS SES发送邮件耗时远超Python的原因及解决办法

我在Spring Boot中调用AWS SES发送单封邮件耗时约300ms,但用Python调用仅需0.3ms。我的Spring Boot实现参考了一个AWS SES的Spring Cloud示例,下面是Python的示例代码,想请教这种差异的原因以及优化方案。

import boto3
from botocore.exceptions import ClientError
import time
# 替换为你的发件人地址,必须已在SES验证
SENDER = " <info@researchkernel.org>"
# 替换为收件人地址,若账号处于沙箱模式,该地址也需验证
RECIPIENT = "prakritidevverma@gmail.com"
# 配置集名称,若不需要可注释
CONFIGURATION_SET = "ConfigSet"
# 替换为你使用的AWS区域
AWS_REGION = "us-west-2"
# 邮件主题
SUBJECT = "iimjobs.com - Your Personalized Jobfeed"
# 纯文本邮件内容
BODY_TEXT = """"""
# HTML格式邮件内容
BODY_HTML = """<html>
<head></head>
<body>
  <h1>Amazon SES Test (SDK for Python)</h1>
  <p>This email was sent with
    <a href='https://aws.amazon.com/ses/'>Amazon SES</a> using the
    <a href='https://aws.amazon.com/sdk-for-python/'>
      AWS SDK for Python (Boto)</a>.</p>
      <p>Delhi is a crowded city. There are very few rich people who travel by their own vehicles. The majority of the people cannot afford to hire a taxi or a three-wheeler. They have to depend on D.T.C. buses, which are the cheapest mode of conveyance. D.T.C. buses are like blood capillaries of our body spreading all over in Delhi. One day I had to go to railway station to receive my uncle. I had to reach there by 9.30 a.m. knowing the irregularity of D.T.C. bus service; I left my home at 7.30 a.m. and reached the bus stop. There was a long queue. Everybody was waiting for the bus but the buses were passing one after another without stopping. I kept waiting for about an hour. I was feeling very restless and I was afraid that I might not be able to reach the station in time. It was 8.45. Luckily a bus stopped just in front of me. It was overcrowded but somehow I managed to get into the bus. Some passengers were hanging on the footboard, so there was no question of getting a seat. It was very uncomfortable. We were feeling suffocated. All of a sudden, an old man declared that his pocket had been picked. He accused the man standing beside him. The young man took a knife out of his pocket and waved it in the air. No body dared to catch him. I thanked God when the bus stopped at the railway station. I reached there just in time.</P>
      <p>Delhi is a crowded city. There are very few rich people who travel by their own vehicles. The majority of the people cannot afford to hire a taxi or a three-wheeler. They have to depend on D.T.C. buses, which are the cheapest mode of conveyance. D.T.C. buses are like blood capillaries of our body spreading all over in Delhi. One day I had to go to railway station to receive my uncle. I had to reach there by 9.30 a.m. knowing the irregularity of D.T.C. bus service; I left my home at 7.30 a.m. and reached the bus stop. There was a long queue. Everybody was waiting for the bus but the buses were passing one after another without stopping. I kept waiting for about an hour. I was feeling very restless and I was afraid that I might not be able to reach the station in time. It was 8.45. Luckily a bus stopped just in front of me. It was overcrowded but somehow I managed to get into the bus. Some passengers were hanging on the footboard, so there was no question of getting a seat. It was very uncomfortable. We were feeling suffocated. All of a sudden, an old man declared that his pocket had been picked. He accused the man standing beside him. The young man took a knife out of his pocket and waved it in the air. No body dared to catch him. I thanked God when the bus stopped at the railway station. I reached there just in time.</p>
</body>
</html>
            """
# 邮件字符编码
CHARSET = "UTF-8"
# 创建SES客户端
client = boto3.client('ses',region_name=AWS_REGION)
start = time.time()
# 尝试发送邮件
try:
    response = client.send_email(
        Destination={
            'ToAddresses': [
                RECIPIENT,
            ],
        },
        Message={
            'Body': {
                'Html': {
                    'Charset': CHARSET,
                    'Data': BODY_HTML,
                },
                'Text': {
                    'Charset': CHARSET,
                    'Data': BODY_TEXT,
                },
            },
            'Subject': {
                'Charset': CHARSET,
                'Data': SUBJECT,
            },
        },
        Source=SENDER,
        # 若不使用配置集,注释或删除下面一行
        # ConfigurationSetName=CONFIGURATION_SET,
    )
except ClientError as e:
    print(e.response['Error']['Message'])
else:
    print("Email sent! Message ID:"),
    print(response['MessageId'])
end = time.time()
print("time taken : SES : "+ str(end-start))

差异原因分析

  • 客户端复用与连接池差异
    Python的boto3客户端默认复用连接,初始化开销在脚本启动时一次性完成;而如果Spring Boot代码每次发送都重新创建SES客户端,或者连接池配置不合理,会导致每次请求都要重新建立TCP连接,大幅增加耗时。
  • SDK实现与运行时开销
    AWS Java SDK的序列化、签名、参数校验等逻辑比Python SDK更重,加上Spring容器的上下文加载、日志拦截等额外处理,会拉长单次调用的总耗时。
  • 首次调用预热差异
    Spring Boot首次调用时会触发类加载、客户端初始化、凭证加载等一次性操作,而Python脚本的初始化本身更轻量,且调用统计包含了初始化时间但整体耗时仍低。

优化解决办法

  • 复用SES客户端实例
    在Spring Boot中把SES客户端配置为单例Bean,避免重复初始化:

    @Configuration
    public class AwsSesConfig {
        @Bean
        public AmazonSimpleEmailService amazonSimpleEmailService() {
            return AmazonSimpleEmailServiceClientBuilder.standard()
                    .withRegion(Regions.US_WEST_2)
                    .build();
        }
    }
    

    业务类中注入该Bean复用即可。

  • 优化连接池配置
    调整AWS Java SDK的HTTP客户端连接池参数,减少连接建立开销:

    @Bean
    public AmazonSimpleEmailService amazonSimpleEmailService() {
        HttpClientConfig httpClientConfig = HttpClientConfig.builder()
                .maxConnections(50)
                .connectionTimeout(Duration.ofSeconds(5))
                .socketTimeout(Duration.ofSeconds(10))
                .build();
        return AmazonSimpleEmailServiceClientBuilder.standard()
                .withRegion(Regions.US_WEST_2)
                .withHttpClient(ApacheHttpClient.builder().withConfig(httpClientConfig).build())
                .build();
    }
    
  • 改用异步调用
    使用Spring的@Async注解或者AWS的异步客户端AmazonSimpleEmailServiceAsync,让邮件发送逻辑后台执行,避免阻塞主线程,降低接口响应耗时。

  • 减少非核心开销
    检查并移除邮件发送方法上不必要的日志、拦截器或AOP逻辑,减少额外处理步骤。

  • 提前预热客户端
    应用启动后,提前调用一次SES的轻量接口(如listIdentities),完成初始化和连接建立,避免首次业务调用的额外开销。

内容的提问来源于stack exchange,提问作者Prakitidev Verma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 16:11:16