简体   繁体   English

Springboot、Micrometer 和 Aws Lambda function

[英]Springboot, Micrometer and Aws Lambda function

I'm trying to send metrics to AWS cloudwatch by using micrometer, however, I'm facing a problem with the AWS credentials.我正在尝试使用千分尺将指标发送到 AWS cloudwatch,但是,我遇到了 AWS 凭证问题。

ERROR i.m.c.CloudWatchMeterRegistry - error sending metric data. 
com.amazonaws.SdkClientException: Unable to load AWS credentials from any provider in the chain: 
[com.amazonaws.auth.EC2ContainerCredentialsProviderWrapper@b23c49d: Failed to connect to service endpoint: , com.amazonaws.auth.profile.ProfileCredentialsProvider@7edf67de: profile file cannot be null]
    at com.amazonaws.auth.AWSCredentialsProviderChain.getCredentials(AWSCredentialsProviderChain.java:136)r 
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.getCredentialsFromContext(AmazonHttpClient.java:1257)r   
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.runBeforeRequestHandlers(AmazonHttpClient.java:833)r 
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:783)r    
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:770)r 
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:744)r  
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.access$500(AmazonHttpClient.java:704)r   
    at com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.java:686)r  at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:550)r  
    at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:530)r  at com.amazonaws.services.cloudwatch.AmazonCloudWatchClient.doInvoke(AmazonCloudWatchClient.java:2587)r 
    at com.amazonaws.services.cloudwatch.AmazonCloudWatchClient.invoke(AmazonCloudWatchClient.java:2554)r   
    at com.amazonaws.services.cloudwatch.AmazonCloudWatchClient.invoke(AmazonCloudWatchClient.java:2543)r   
    at com.amazonaws.services.cloudwatch.AmazonCloudWatchClient.executePutMetricData(AmazonCloudWatchClient.java:2297)r 
    at com.amazonaws.services.cloudwatch.AmazonCloudWatchAsyncClient$27.call(AmazonCloudWatchAsyncClient.java:1215)r    
    at com.amazonaws.services.cloudwatch.AmazonCloudWatchAsyncClient$27.call(AmazonCloudWatchAsyncClient.java:1209)r    
    at java.base/java.util.concurrent.FutureTask.run(Unknown Source)r   
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)r at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)r    
    at java.base/java.lang.Thread.run(Unknown Source)r

The AmazonHttpClient is trying to retrieve the credentials using either the EC2ContainerCredentialsProviderWrapper or ProfileCredentialsProvider , but in the lambda environment the credentials are available through an execution role and also we have specific environment variables called AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY . AmazonHttpClient 正在尝试使用EC2ContainerCredentialsProviderWrapperProfileCredentialsProvider检索凭据,但在 lambda 环境中,凭据可通过执行角色获得,而且我们还有名为AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY的特定环境变量。

So, is there any ways to tell micrometer to use a different AwsCredentials provider, for example EnvironmentVariableCredentialsProvider ?那么,有什么方法可以告诉千分尺使用不同的 AwsCredentials 提供程序,例如EnvironmentVariableCredentialsProvider

Have you tried using a Configuration file to change the Bean for that?您是否尝试过使用Configuration文件为此更改Bean

@Configuration
public class ManualAWSCredentialProviderConfiguration {
  @Value("${AWS_ACCESS_KEY_ID}")
  protected String accessKey;

  @Value("${AWS_SECRET_ACCESS_KEY}")
  protected String secretKey;

  @Bean
  @Primary
  public AWSCredentialsProvider buildAWSCredentialsProviderManually() {
    return new AWSStaticCredentialsProvider(
      new BasicAWSCredentials(accessKey, secretKey)
    );
  }
}

After some research, I was able to send the metrics by creating a custom CloudWatchMeterRegistry bean as follow:经过一些研究,我能够通过创建自定义CloudWatchMeterRegistry bean 来发送指标,如下所示:

@Bean
@Primary
public CloudWatchMeterRegistry customCloudWatchMeterRegistry(
        CloudWatchConfig config, Clock clock, AwsRegionProperties awsRegionProperties) {

    AmazonCloudWatchAsync amazonCloudWatchAsync = AmazonCloudWatchAsyncClient
            .asyncBuilder()
            .withCredentials(new EnvironmentVariableCredentialsProvider())
            .withRegion(awsRegionProperties.getStatic())
            .build();

    return new CloudWatchMeterRegistry(config, clock, amazonCloudWatchAsync);
}

As you can see, now I can configure a custom Credentials Provider, in my case the EnvironmentVariableCredentialsProvider .如您所见,现在我可以配置自定义凭证提供程序,在我的例子中是EnvironmentVariableCredentialsProvider

Important hint: The name of the bean shouldn't be cloudWatchMeterRegistry because this class org.springframework.cloud.aws.autoconfigure.metrics.CloudWatchExportAutoConfiguration already has a declared bean with that name.重要提示: bean 的名称不应该是cloudWatchMeterRegistry ,因为这个 class org.springframework.cloud.aws.autoconfigure.metrics.CloudWatchExportAutoConfiguration已经有一个使用该名称声明的 bean。

When you add aws-java-sdk-sts to your dependencies (and thous having it on your classpath) will result in an extended provider chain.当您将aws-java-sdk-sts添加到您的依赖项(并且将它放在您的类路径中)时,将导致扩展的提供程序链。 Then the execution role should get used.然后应该使用执行角色。

For maven:对于 maven:

<dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>aws-java-sdk-sts</artifactId>
    <version>1.12.52</version>
</dependency>

For gradle:对于 gradle:

implementation group: 'com.amazonaws', name: 'aws-java-sdk-sts', version: '1.12.52'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM