>  기사  >  Java  >  Amazon SQS를 사용하여 Spring Boot 소비자 애플리케이션 구축: CDK(클라우드 개발 키트)를 사용하여 인프라 설정

Amazon SQS를 사용하여 Spring Boot 소비자 애플리케이션 구축: CDK(클라우드 개발 키트)를 사용하여 인프라 설정

Susan Sarandon
Susan Sarandon원래의
2024-10-07 22:08:30564검색
017일 - 100일AWSIaCDevopsChallenge

오늘 100일 코드 챌린지 시리즈에서는 Amazon SQS를 사용하여 springboot로 개발된 마이크로서비스를 분리하는 방법을 보여 드리겠습니다.

Amazon SQS란 무엇입니까?

Amazon SQS(Simple Queue Service)는 애플리케이션이 sendyg를 통해 통신하고 대기열에 메시지를 저장하고 수신할 수 있도록 도와주는 클라우드 서비스입니다. 이는 소비자가 처리할 준비가 될 때까지 저장되는 대기줄과 같습니다. 이렇게 하면 시스템이 과부하되는 것을 방지하고 메시지가 손실되지 않도록 할 수 있습니다.

Springboot 애플리케이션을 사용하여 SQS 메시지 사용

SQS 대기열의 각 메시지를 처리하는 Spring Boot 앱을 생성하여 SQS 메시지를 사용하는 방법을 보여줍니다. CDK(Java)를 사용하여 구축된 인프라에는 다음이 포함됩니다.

  • Spring Boot 앱이 실행될 EC2 인스턴스를 호스팅하기 위한 공개 서브넷이 있는 VPC
  • EC2 인스턴스가 인터넷에 액세스하고 종속성을 다운로드하기 위한 인터넷 게이트웨이
  • 메시지 저장을 위한 SQS 대기열배달 못한 편지 대기열
  • SpringBoot 앱 호스팅을 위한 EC2 인스턴스
  • EC2 인스턴스가 SQS 대기열에서 메시지를 검색할 수 있도록 하는 IAM 역할(매우 중요).

인프라 구축

CDK(Java)를 사용하여 필요한 인프라 설정

Building a Spring Boot Consumer Application with Amazon SQS: Setup Infrastructure Using Cloud Development Kit (CDK)

VPC 및 서브넷 인터넷 게이트웨이


public class NetworkContruct extends Construct {
  private final IVpc vpc;
  public NetworkContruct(Construct scope, String id, StackProps props) {
    super(scope, id);
    this.vpc =
        new Vpc(
            this,
            "VpcResource",
            VpcProps.builder()
                .vpcName("my-vpc")
                .enableDnsHostnames(true)
                .enableDnsSupport(true)
                .createInternetGateway(true)
                .ipProtocol(IpProtocol.IPV4_ONLY)
                .ipAddresses(IpAddresses.cidr("10.0.0.1/16"))
                .maxAzs(1)
                .subnetConfiguration(
                    List.of(
                        SubnetConfiguration.builder()
                            .name("Public-Subnet")
                            .mapPublicIpOnLaunch(true)
                            .subnetType(SubnetType.PUBLIC)
                            .build()))
                .build());
  }
  public IVpc getVpc() {
    return vpc;
  }
}


이 CDK 구성은 다음을 생성합니다.
?? my-vpc라는 이름의 VPC와 DNS 호스트 이름 활성화가 활성화되었습니다.
?? 리소스가 퍼블릭 IP를 연결할 수 있도록 하는 Public-Subnet이라는 퍼블릭 서브넷(구성된 경우).
?? 인터넷 트래픽을 활성화하는 인터넷 게이트웨이입니다.

SQS 대기열 및 배달 못한 편지 대기열


public class QueueConstruct extends Construct {
  private final IQueue queue;
  public QueueConstruct(Construct scope, String id, IVpc vpc, StackProps props) {
    super(scope, id);
    IQueue dlq =
        new Queue(
            this,
            "DeadLetterQueue",
            QueueProps.builder()
                .deliveryDelay(Duration.millis(0))
                .retentionPeriod(Duration.days(10))
                .queueName("my-queue-dlq")
                .build());
    DeadLetterQueue deadLetterQueue = DeadLetterQueue.builder()
        .queue(dlq)
        .maxReceiveCount(32)
        .build();

    this.queue =
        new Queue(
            this,
            "SQSQueueResource",
            QueueProps.builder()
                .queueName("my-queue")
                .retentionPeriod(Duration.minutes(15))
                .visibilityTimeout(Duration.seconds(90))
                .deadLetterQueue(deadLetterQueue)
                .build());
  }

  public IQueue getQueue() {
    return queue;
  }
}


위의 CDK 구성은 다음 리소스를 생성합니다.

  • Spring Boot 앱에서 사용되는 my-queue라는 이름의 큐
  • my-queue-dlq라는 이름의 DeadLetter 대기열실패한 메시지를 캡처하여 나중에 기본 대기열을 차단하지 않고 분석하고 수정할 수 있습니다.

Spring Boot 애플리케이션 호스팅을 위한 EC2 인스턴스


// ComputerProps.java
public record ComputerProps(IVpc vpc, String sqsQueueArn) {}

// ComputerConstruct.java
public class ComputerConstruct extends Construct {
  private final IInstance computer;
  public ComputerConstruct(
      Construct scope, String id, ComputerProps computerProps, StackProps props) {
    super(scope, id);
    SecurityGroup securityGroup =
        new SecurityGroup(
            this,
            "WebserverSGResource",
            SecurityGroupProps.builder()
                .allowAllOutbound(true)
                .securityGroupName("Webserver-security-group")
                .disableInlineRules(true)
                .vpc(computerProps.vpc())
                .description("Allow trafic from/to webserver instance")
                .build());

    securityGroup.addIngressRule(Peer.anyIpv4(), Port.SSH, "Allow ssh traffic");
    securityGroup.addIngressRule(Peer.anyIpv4(), Port.tcp(8089), "Allow traffic from 8089 port");

    KeyPair keyPair =
        new KeyPair(
            this,
            "KeyPairResource",
            KeyPairProps.builder()
                .keyPairName("ws-keypair")
                .account(Objects.requireNonNull(props.getEnv()).getAccount())
                .type(KeyPairType.RSA)
                .format(KeyPairFormat.PEM)
                .build());

    new CfnOutput(
        this, "KeyPairId", CfnOutputProps.builder().value(keyPair.getKeyPairId()).build());

    Instance ec2Instance =
        new Instance(
            this,
            "WebServerInstanceResource",
            InstanceProps.builder()
                .securityGroup(securityGroup)
                .keyPair(keyPair)
                .instanceName("Webserver-Instance")
                .machineImage(
                    MachineImage.lookup(
                        LookupMachineImageProps.builder()
                            .name("*ubuntu*")
                            .filters(
                                Map.ofEntries(
                                    Map.entry("image-id", List.of("ami-0e86e20dae9224db8")),
                                    Map.entry("architecture", List.of("x86_64"))))
                            .windows(false)
                            .build()))
                .vpc(computerProps.vpc())
                .role(buildInstanceRole(computerProps))
                .instanceType(InstanceType.of(InstanceClass.T2, InstanceSize.MICRO))
                .associatePublicIpAddress(true)
                .blockDevices(
                    List.of(
                        BlockDevice.builder()
                            .mappingEnabled(true)
                            .deviceName("/dev/sda1")
                            .volume(
                                BlockDeviceVolume.ebs(
                                    10,
                                    EbsDeviceOptions.builder()
                                        .deleteOnTermination(true)
                                        .volumeType(EbsDeviceVolumeType.GP3)
                                        .build()))
                            .build()))
                .userDataCausesReplacement(true)
                .vpcSubnets(SubnetSelection.builder().subnetType(SubnetType.PUBLIC).build())
                .build());

    UserData userData = UserData.forLinux();
    userData.addCommands(readFile("./webserver-startup.sh"));

    ec2Instance.addUserData(userData.render());

    this.computer = ec2Instance;
  }

  public IInstance getComputer() {
    return computer;
  }

  private String readFile(String filename) {

    InputStream scriptFileStream = getClass().getClassLoader().getResourceAsStream(filename);

    try {
      assert scriptFileStream != null;
      try (InputStreamReader isr = new InputStreamReader(scriptFileStream, StandardCharsets.UTF_8);
          BufferedReader br = new BufferedReader(isr)) {
        StringBuilder content = new StringBuilder();
        String line;
        while ((line = br.readLine()) != null) {
          content.append(line).append("\n");
        }
        return content.toString();
      }
    } catch (IOException e) {
      throw new RuntimeException(e.getMessage());
    }
  }

  private IRole buildInstanceRole(ComputerProps props) {
    return new Role(
        this,
        "WebserverInstanceRoleResource",
        RoleProps.builder()
            .roleName("webserver-role")
            .assumedBy(new ServicePrincipal("ec2.amazonaws.com"))
            .path("/")
            .inlinePolicies(
                Map.ofEntries(
                    Map.entry(
                        "sqs",
                        new PolicyDocument(
                            PolicyDocumentProps.builder()
                                .assignSids(true)
                                .statements(
                                    List.of(
                                        new PolicyStatement(
                                            PolicyStatementProps.builder()
                                                .effect(Effect.ALLOW)
                                                .actions(
                                                    List.of(
                                                        "sqs:DeleteMessage",
                                                        "sqs:ReceiveMessage",
                                                        "sqs:SendMessage",
                                                        "sqs:GetQueueAttributes",
                                                        "sqs:GetQueueUrl"))
                                                .resources(List.of(props.sqsQueueArn()))
                                                .build())))
                                .build()))))
            .build());
  }
}


위의 CDK 구성은 다음 리소스를 생성합니다.

  • SSH 연결을 위해 포트 22에서 인바운드 트래픽을 허용하고 애플리케이션 연결 포트인 포트 8089에서 인바운드 트래픽을 허용하는 Webserver-security-group이라는 보안 그룹입니다.
  • SSH를 통해 앱 호스트에 연결하는 데 사용되는 ws-keypair라는 키 쌍입니다. 우리는 CDK를 사용하여 인프라를 구축하고 있으므로 배포 후 개인 키(PEM 파일)를 다운로드해야 하는 경우 Cloudformation 또는 CDK 스택 생성 후 개인 키 파일 PEM을 검색하는 방법에 대한 이전 기사를 참조하세요[↗].
  • Webserver-Instance라는 Ec2 인스턴스.
  • Ec2 인스턴스에 호스팅된 spring Boot 애플리케이션이 Amazon SQS 대기열(이미 생성됨)과의 연결을 설정하고 메시지 삭제, 메시지 수신, 메시지 보내기 작업을 수행할 수 있게 해주는 webserver-role이라는 Ec2 인스턴스용 IAM 역할 , 대기열 속성 가져오기 및 대기열 URL 가져오기

스택 생성


// MyStack.java
public class MyStack extends Stack {
  public MyStack(final Construct scope, final String id, final StackProps props) {
    super(scope, id, props);
    IVpc vpc = new NetworkContruct(this, "NetworkResource", props).getVpc();
    IQueue queue = new QueueConstruct(this, "QueueResource", vpc, props).getQueue();
    IInstance webserver =
        new ComputerConstruct(
                this, "ComputerResource", new ComputerProps(vpc, queue.getQueueArn()), props)
            .getComputer();
  }
}

// Day17App.java
public class Day017App {
  public static void main(final String[] args) {
    App app = new App();
    new MyStack(app,"Day017Stack",
        StackProps.builder()
                .env(
                    Environment.builder()
                        .account(System.getenv("CDK_DEFAULT_ACCOUNT"))
                        .region(System.getenv("CDK_DEFAULT_REGION"))
                        .build())
                .build());
    app.synth();
  }
}


SpringBoot 소비자 애플리케이션 생성

일을 단순하게 유지하고 인생을 복잡하게 만들지 않기 위해 Spring Cloud AWS Docs를 사용하겠습니다.[↗]

Spring Cloud AWS는 Spring Framework 및 Spring Boot 애플리케이션에서 AWS 관리형 서비스 사용을 단순화합니다. 잘 알려진 Spring 관용어와 API를 사용하여 AWS 제공 서비스와 상호 작용하는 편리한 방법을 제공합니다.

내 프로젝트에서 SQS 서비스를 구성하기 위해 구성 클래스에 다음 Bean을 추가하겠습니다.


@Configuration
public class ApplicationConfiguration {
    @Bean
    public AwsRegionProvider customRegionProvider() {
        return new InstanceProfileRegionProvider();
    }
    @Bean
    public AwsCredentialsProvider customInstanceCredProvider() {
        return  InstanceProfileCredentialsProvider.builder()
                .build();
    }
}


모든 새로운 메시지를 캡처하고 해당 내용을 인쇄하는 청취자입니다.


@Slf4j
@Component
public class ExampleSQSConsumer {
    @SqsListener(queueNames = { "my-queue" }) // ??
    public void listen(String payload) {
        log.info("*******************  SQS Payload ***************");
        log.info("Message Content: {}", payload);
        log.info("Received At: {}", Date.from(Instant.now()));
        log.info("************************************************");
    }
}


내 GitHub 저장소에서 전체 프로젝트를 찾을 수 있습니다[↗]

전개

⚠️⚠️ 배포 명령을 실행하기 전에 호스트 컴퓨터에 Java가 설치되어 있는지 확인하세요. 이 인프라를 구축하기 위해 MacO에서 Java 21을 사용했습니다.

어디에서든 터미널을 열고 다음 명령을 실행하세요.


<p>git clone https://github.com/nivekalara237/100DaysTerraformAWSDevops.git<br>
cd 100DaysTerraformAWSDevops/day_017<br>
cdk bootstrap --profile cdk-user<br>
cdk deploy --profile cdk-user Day017Stack</p>




다시

Building a Spring Boot Consumer Application with Amazon SQS: Setup Infrastructure Using Cloud Development Kit (CDK)


GitHub Repo에서 전체 소스 코드를 찾을 수 있습니다↗

위 내용은 Amazon SQS를 사용하여 Spring Boot 소비자 애플리케이션 구축: CDK(클라우드 개발 키트)를 사용하여 인프라 설정의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.