


Day 017 - 100DaysAWSIaCDevopsChallenge
Today in my series of 100 days of code challenge, I will show you how to decouple microservices developed with springboot using Amazon SQS.
What is Amazon SQS ?
Amazon SQS (Simple Queue Service) is a cloud service that helps applications communicate by sendyg, storing and receiving messages in a queue. It's like a waiting line where are stored until a consumer is ready to process them. This prevents systems from getting overhelmed and make sure no message is lost.
Consume a SQS Messages using Springboot application
To demonstrate how to consume SQS messages by creating a Spring Boot app that processes each message from an SQS queue. The infrastructure, built using CDK (Java), will include:
- a VPC with a public Subnet to host an EC2 instance where the Spring Boot app will run.
- An Internet Gateway for the EC2 instance to access the internet and download dependencies.
- A SQS Queue and Dead Letter Queue for message storage.
- An EC2 Instance for hosting SpringBoot App.
- An IAM Role to allow the EC2 instance to retrieve messages from the SQS queue (very important).
Create the Infrastructure
Set up the necessary infrastructure using CDK (Java)
VPC & Subne Internet Gateway
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; } }
This cdk construct will create:
?? A VPC named my-vpc and enable DNS hostname enabled.
?? A public subnet named Public-Subnet which allows resources to attach a public IP (if configured with one).
?? An Internet Gateway to enable internet traffic.
SQS Queue & Dead Letter Queue
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; } }
The above CDK construct will create the following resources:
- A Queue named my-queue, which will be used in the Spring Boot app.
- A DeadLetter Queue named my-queue-dlq which captures failed messages so they can be analysed and fixed later, without blocking the main queue.
EC2 Instance for Hosting the Spring Boot Application
// 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()); } }
The above CDK construct will create the following resources:
- A Security Group named Webserver-security-group that allow inbound traffic on Port 22 for SSH connections and allow inbound traffic on Port 8089, which is the application connection port.
- A Key Pair named ws-keypair that will be used to connect to the app host via SSH. Since we are using CDK to build the infrastructure, if you need to download the private key (PEM file) after deployment, refer to my previous article on How the retrieve the private key file PEM after Cloudformation or CDK stack creation[↗].
- An Ec2 Instance named Webserver-Instance.
- An IAM Role for the Ec2 Instance named webserver-role, which allows the spring Boot application hosted on the Ec2 Instance to establish connections with the Amazon SQS Queue (already created) and perform actions: Delete Message, Receive Message, Send Message, Get Queue Attributes and Get Queue Url.
Create the stack
// 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(); } }
Create SpringBoot Consumer Application
To keep things simple and avoid complicating my life, I will use Spring Cloud AWS Docs[↗]
Spring Cloud AWS simplifies using AWS managed services in a Spring Framework and Spring Boot applications. It offers a convenient way to interact with AWS provided services using well-known Spring idioms and APIs.
To configure the SQS service in my project, I will add the following beans in the configuration class:
@Configuration public class ApplicationConfiguration { @Bean public AwsRegionProvider customRegionProvider() { return new InstanceProfileRegionProvider(); } @Bean public AwsCredentialsProvider customInstanceCredProvider() { return InstanceProfileCredentialsProvider.builder() .build(); } }
And the listener that captures all new message and prints their content.
@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("************************************************"); } }
You can find the full project in my GitHub repo[↗]
Deployment
⚠️⚠️ Before run the deployment commands ensure that you have java installed on your host machine. I used Java 21 under MacOs to build this insfrastructure.
Open the terminal anywhere and run the following commands:
<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>
Resut
Your can find the full source code on GitHub Repo↗
The above is the detailed content of Building a Spring Boot Consumer Application with Amazon SQS: Setup Infrastructure Using Cloud Development Kit (CDK). For more information, please follow other related articles on the PHP Chinese website!

The article discusses using Maven and Gradle for Java project management, build automation, and dependency resolution, comparing their approaches and optimization strategies.

The article discusses creating and using custom Java libraries (JAR files) with proper versioning and dependency management, using tools like Maven and Gradle.

The article discusses implementing multi-level caching in Java using Caffeine and Guava Cache to enhance application performance. It covers setup, integration, and performance benefits, along with configuration and eviction policy management best pra

The article discusses using JPA for object-relational mapping with advanced features like caching and lazy loading. It covers setup, entity mapping, and best practices for optimizing performance while highlighting potential pitfalls.[159 characters]

Java's classloading involves loading, linking, and initializing classes using a hierarchical system with Bootstrap, Extension, and Application classloaders. The parent delegation model ensures core classes are loaded first, affecting custom class loa


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

SublimeText3 Chinese version
Chinese version, very easy to use

mPDF
mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),

DVWA
Damn Vulnerable Web App (DVWA) is a PHP/MySQL web application that is very vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, to help web developers better understand the process of securing web applications, and to help teachers/students teach/learn in a classroom environment Web application security. The goal of DVWA is to practice some of the most common web vulnerabilities through a simple and straightforward interface, with varying degrees of difficulty. Please note that this software

Dreamweaver Mac version
Visual web development tools

SecLists
SecLists is the ultimate security tester's companion. It is a collection of various types of lists that are frequently used during security assessments, all in one place. SecLists helps make security testing more efficient and productive by conveniently providing all the lists a security tester might need. List types include usernames, passwords, URLs, fuzzing payloads, sensitive data patterns, web shells, and more. The tester can simply pull this repository onto a new test machine and he will have access to every type of list he needs.