今日は、100 日間のコードチャレンジ シリーズで、Springboot で開発されたマイクロサービスを Amazon SQS を使用して分離する方法を説明します。
Amazon SQS (Simple Queue Service) は、アプリケーションが sendyg によって通信し、メッセージをキューに保存および受信するのを支援するクラウド サービスです。これは、消費者が処理する準備ができるまで保存される待機列のようなものです。これにより、システムが過剰に制御されるのを防ぎ、メッセージが失われないようにします。
SQS キューからの各メッセージを処理する Spring Boot アプリを作成して、SQS メッセージを使用する方法を示します。 CDK (Java) を使用して構築されたインフラストラクチャには以下が含まれます:
CDK (Java) を使用して必要なインフラストラクチャをセットアップする
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 ホスト名を有効にします。
?? Public-Subnet という名前のパブリック サブネット。リソースがパブリック IP を接続できるようにします (パブリック IP が設定されている場合)。
??インターネット トラフィックを有効にするインターネット ゲートウェイ。
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 コンストラクトは次のリソースを作成します:
// 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 コンストラクトは次のリソースを作成します:
// 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(); } }
物事をシンプルにして、生活が複雑になるのを避けるために、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>
完全なソース コードは GitHub リポジトリで見つけることができます↗
以上がAmazon SQS を使用した Spring Boot コンシューマ アプリケーションの構築: クラウド開発キット (CDK) を使用したインフラストラクチャのセットアップの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。