Spring Boot on Amazon Web Services with Spring Cloud AWS

VMware Tanzu
VMware TanzuVMware Tanzu
SPRING BOOT
ON AMAZON WEB SERVICES
WITH SPRING CLOUD AWS
MACIEJ
WALKOWIAK
MATEJ
NEDIC
@maciejwalkowiak @matejnedic1
@maciejwalkowiak @matejnedic1
@maciejwalkowiak @matejnedic1
MACIEJ WALKOWIAK
- independent consultant
- Spring Cloud AWS Lead
- working with
@maciejwalkowiak @matejnedic1
https://youtube.com/springacademy
@maciejwalkowiak @matejnedic1
MATEJ NEDIC
- Software Engineer
- Spring Cloud AWS Core team member
- working at
@maciejwalkowiak @matejnedic1
SPRING CLOUD AWS
@maciejwalkowiak @matejnedic1
SPRING CLOUD AWS
•Created by Agim Emruli and Alain Shall
•First commit in February 2011
•Community project
•April 2020 - not a part of Spring
Cloud release train
•May 2020 - new maintainers
@maciejwalkowiak @matejnedic1
SPRING CLOUD AWS
MACIEJ
WALKOWIAK
MATEJ
NEDIC
EDDU
MELENDEZ
@maciejwalkowiak @matejnedic1
SPRING CLOUD AWS
https://github.com/awspring/spring-cloud-aws
@maciejwalkowiak @matejnedic1
SPRING CLOUD AWS
https://github.com/awspring/spring-cloud-aws
@maciejwalkowiak @matejnedic1
@maciejwalkowiak @matejnedic1
SPRING BOOT
ON AMAZON WEB
SERVICES
WITH SPRING CLOUD AWS
@maciejwalkowiak @matejnedic1
Application RDBMS
@maciejwalkowiak @matejnedic1
EC2
•Updates
•Backups
•Security
•Scaling
•High Availability
RDS
•Updates
•Backups
•Security
•Scaling
•High Availability
@maciejwalkowiak @matejnedic1
EC2
•! Updates
•! Backups
•! Security
•! Scaling
•! High Availability
RDS
•✅ Updates
•✅ Backups
•✅ Security
•✅ Scaling
•✅ High Availability
@maciejwalkowiak @matejnedic1
EC2
•! Updates
•! Backups
•! Security
•! Scaling
•! High Availability
RDS
•✅ Updates
•✅ Backups
•✅ Security
•✅ Scaling
•✅ High Availability
#
@maciejwalkowiak @matejnedic1
@maciejwalkowiak @matejnedic1
Application RDS
@maciejwalkowiak @matejnedic1
Application
RDS - Primary
@maciejwalkowiak @matejnedic1
Application
RDS - Primary
RDS - Read Replica
@maciejwalkowiak @matejnedic1
Application
RDS - Primary
RDS - Read Replica
Asynchronous
Replication
@maciejwalkowiak @matejnedic1
Application
RDS - Primary
RDS - Read Replica
Asynchronous
Replication
@maciejwalkowiak @matejnedic1
Application
RDS - Primary
RDS - Read Replica
Asynchronous
Replication
@maciejwalkowiak @matejnedic1
Application
RDS - Primary
RDS - Read Replica
Asynchronous
Replication
Write
Read
@maciejwalkowiak @matejnedic1
Application
RDS - Primary
RDS - Read Replica #1
Asynchronous
Replication
Write
Read
RDS - Read Replica #2
RDS - Read Replica #3
Read
Read
@maciejwalkowiak @matejnedic1
spring:
datasource:
url: jdbc:postgresql://springone.c0x5be2ybrmz.eu-west-2.rds.amazonaws.com:5432/postgres
username: postgres
password: postgres
@maciejwalkowiak @matejnedic1
cloud:
aws:
rds:
instances:
-
db-instance-identifier: springone
database-name: postgres
username: postgres
password: postgres
@maciejwalkowiak @matejnedic1
cloud:
aws:
rds:
instances:
-
db-instance-identifier: springone
database-name: postgres
username: postgres
password: postgres
read-replica-support: true
@maciejwalkowiak @matejnedic1
@Service
class UserService {
@Transactional
void registerUser(User user) {
...
}
@Transactional(readOnly=true)
User findUser(Long id) {
...
}
}
@maciejwalkowiak @matejnedic1
https://vladmihalcea.com/read-write-read-only-transaction-routing-spring/
@maciejwalkowiak @matejnedic1
•Only Tomcat connection pool supported (will change
in 3.0)
•No Aurora support (will change in 3.0)
WHAT IS MISSING?
@maciejwalkowiak @matejnedic1
•Aurora support
•IAM Authentication
•RDS Proxy Support
•Secrets Manager JDBC authentication (?)
WHAT IS COMING?
@maciejwalkowiak @matejnedic1
MESSAGING ON AWS
@maciejwalkowiak @matejnedic1
Service A Service B
HTTP
@maciejwalkowiak @matejnedic1
Service A Service B
@maciejwalkowiak @matejnedic1
Service A Service B
@maciejwalkowiak @matejnedic1
Service A Service B
@maciejwalkowiak @matejnedic1
Service A Service B
@maciejwalkowiak @matejnedic1
Service A Service B
@maciejwalkowiak @matejnedic1
@maciejwalkowiak @matejnedic1
@maciejwalkowiak @matejnedic1
https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-basic-architecture.html
@maciejwalkowiak @matejnedic1
@Service
public class RegistrationService {
void register(Attendee attendee) {
// persist attendee, send confirmation email
}
}
@maciejwalkowiak @matejnedic1
@Service
public class RegistrationService {
private final QueueMessagingTemplate queueMessagingTemplate;
public RegistrationService(QueueMessagingTemplate queueMessagingTemplate)
this.queueMessagingTemplate = queueMessagingTemplate;
}
void register(Attendee attendee) {
// persist attendee, send confirmation email
queueMessagingTemplate.convertAndSend("springone-queue", attendee);
}
}
@maciejwalkowiak @matejnedic1
@Component
public class AttendeeListener {
private AttendeeRepository attendeeRepository;
public AttendeeListener(AttendeeRepository attendeeRepository) {
this.attendeeRepository = attendeeRepository;
}
@SqsListener("springone-queue")
void handle(Attendee attendee) {
attendeeRepository.save(attendee);
}
}
@maciejwalkowiak @matejnedic1
@Component
public class AttendeeListener {
private AttendeeRepository attendeeRepository;
public AttendeeListener(AttendeeRepository attendeeRepository) {
this.attendeeRepository = attendeeRepository;
}
@SqsListener("springone-queue")
void handle(Attendee attendee, @Header("header-name") String header) {
attendeeRepository.save(attendee);
}
}
@maciejwalkowiak @matejnedic1
@Component
public class AttendeeListener {
private AttendeeRepository attendeeRepository;
public AttendeeListener(AttendeeRepository attendeeRepository) {
this.attendeeRepository = attendeeRepository;
}
@SqsListener("springone-queue")
void handle(Attendee attendee, Acknowledgment acknowledgment) {
if (...) {
acknowledgment.acknowledge();
}
}
}
@maciejwalkowiak @matejnedic1
@Component
public class AttendeeListener {
private AttendeeRepository attendeeRepository;
public AttendeeListener(AttendeeRepository attendeeRepository) {
this.attendeeRepository = attendeeRepository;
}
@SqsListener("springone-queue")
void handle(Attendee attendee, Visibility visibility) {
if (...) {
visibility.extend(2);
}
}
}
@maciejwalkowiak @matejnedic1
@Component
public class AttendeeListener {
private AttendeeRepository attendeeRepository;
public AttendeeListener(AttendeeRepository attendeeRepository) {
this.attendeeRepository = attendeeRepository;
}
@SqsListener("springone-queue")
@SendTo("tickets-queue")
Ticket handle(Attendee attendee) {
attendeeRepository.save(attendee);
// return ticket
}
}
@maciejwalkowiak @matejnedic1
Service A Service C
Service B
SNS
@maciejwalkowiak @matejnedic1
Service A Service C
Service B
SNS
@maciejwalkowiak @matejnedic1
Service A Service C
Service B
SNS
@maciejwalkowiak @matejnedic1
Service A Service C
Service B
SNS
@maciejwalkowiak @matejnedic1
Service A Service C
Service B
SNS
@maciejwalkowiak @matejnedic1
Service A Service C
Service B
SNS
@maciejwalkowiak @matejnedic1
Service A Service C
Service B
SNS
@maciejwalkowiak @matejnedic1
Service A Service C
Service B
SNS
HTTP
HTTP
HTTP
@maciejwalkowiak @matejnedic1
@Component
public class SnsNotificationSender {
private final NotificationMessagingTemplate
notificationMessagingTemplate;
public SnsNotificationSender(
NotificationMessagingTemplate notificationMessagingTemplate)
{
this.notificationMessagingTemplate =
notificationMessagingTemplate;
}
public void send(String subject, String message) {
this.notificationMessagingTemplate.sendNotification(
"physicalTopicName", message, subject);
}
}
@maciejwalkowiak @matejnedic1
@Controller
@RequestMapping("/springone-topic")
public class NotificationController {
@NotificationSubscriptionMapping
public void handleSubscriptionMessage(NotificationStatus status) {
//We subscribe to start receive the message
status.confirmSubscription();
}
@NotificationMessageMapping
public void handleNotificationMessage(@NotificationSubject String subject,
@NotificationMessage String message) {
// ...
}
@NotificationUnsubscribeConfirmationMapping
public void handleUnsubscribeMessage(NotificationStatus status) {
//e.g. the client has been unsubscribed and we want to "re-subscribe"
status.confirmSubscription();
}
}
@maciejwalkowiak @matejnedic1
•Performance …
•Reactive support
•Spring Cloud Stream SQS (?)
WHAT IS COMING?
@maciejwalkowiak @matejnedic1
•Performance …
•Reactive support
•Spring Cloud Stream SQS (?)
WHAT IS COMING?
@maciejwalkowiak @matejnedic1
STORING CONFIGURATION WITH
SECRETS MANAGER
AND
PARAMETER STORE
@maciejwalkowiak @matejnedic1
https://cloud.spring.io/spring-cloud-config/reference/html/
Service A
Service B
Service C
@maciejwalkowiak @matejnedic1
https://cloud.spring.io/spring-cloud-config/reference/html/
Service A
Service B
Service C
Spring Cloud Config
@maciejwalkowiak @matejnedic1
https://cloud.spring.io/spring-cloud-config/reference/html/
Service A
Service B
Service C
Spring Cloud Config
DB
File
System
Vault
Git
@maciejwalkowiak @matejnedic1
But what if your
storage for properties
goes down?
@maciejwalkowiak @matejnedic1
AWS PARAMETER STORE
@maciejwalkowiak @matejnedic1
@maciejwalkowiak @matejnedic1
Service A Service B
Parameter store
Spring Boot on Amazon Web Services with Spring Cloud AWS
@maciejwalkowiak @matejnedic1
spring.config.import=aws-parameterstore:/config/spring/
spring.config.import=optional:aws-parameterstore:/config/common/;/config/urls/
spring:
config:
import:
- aws-parameterstore:/config/spring/
- optional:aws-parameterstore:/config/common/;/config/urls/
@maciejwalkowiak @matejnedic1
@Value("${message}") String message;
spring.cloud.config.server.git.refreshRate=${refresh}
@maciejwalkowiak @matejnedic1
AWS SECRETS MANAGER
Parameter store
Secret Manager
Service A
Parameter store
Secret Manager
Service A
RDS
Parameter store
Secret Manager
@maciejwalkowiak @matejnedic1
spring.config.import=aws-secretmanager:/secret/db/prod/url
spring.config.import=optional:aws-secretmanager:/secret/common
spring.datasoruce.url=${url}
@maciejwalkowiak @matejnedic1
Parameter Store
• Type: Supports
StringList,String,
SecureString.
• 4KB char max
• Can’t be referenced cross
account
• Can’t rotate secrets
• Cheaper
Secret manager
• Can be referenced cross
account
• Automatic Secret rotation
• More expensive
• Can store more characters 10kb
• Built in password generator
• Supports secret cross region
replication
@maciejwalkowiak @matejnedic1
•Secret rotation support
•Refreshing context on parameter and secret change
WHAT IS COMING?
@maciejwalkowiak @matejnedic1
OTHER SUPPORTED SERVICES
•S3
•EC2 metadata
•Cloud Watch
•ElastiCache (Redis & Memcached)
•SES (Simple Email Service)
•Cloud Formation
@maciejwalkowiak @matejnedic1
@maciejwalkowiak @matejnedic1
WHEN SPRING CLOUD AWS IS NOT ENOUGH
•Spring Cloud Stream Kinesis Binder
https://github.com/spring-cloud/spring-cloud-stream-binder-aws-kinesis
•Spring Integration AWS
https://github.com/spring-projects/spring-integration-aws
•Spring Cloud Config Server
https://github.com/spring-cloud/spring-cloud-config
•Spring Data DynamoDB
https://github.com/boostchicken/spring-data-dynamodb
@maciejwalkowiak @matejnedic1
•AWS SDK:
•AWS SDK v1
•AWS SDK v2
WHEN SPRING CLOUD AWS IS NOT ENOUGH
@maciejwalkowiak @matejnedic1
•AWS SDK v2
•$ GraalVM Native Image compatible
•$ Non Blocking - Spring WebFlux friendly!
•$ Pluggable HTTP client
•$ Does not conflict with SDK v1
•% Still no feature parity with 1.x
WHEN SPRING CLOUD AWS IS NOT ENOUGH
@maciejwalkowiak @matejnedic1
TESTING
@maciejwalkowiak @matejnedic1
TESTING WITH LOCALSTACK
@maciejwalkowiak @matejnedic1
version: '3.1'
services:
localstack:
image: localstack/localstack:latest
environment:
- SERVICES=sqs,s3
ports:
- ‘4566:4566'
- ‘4571:4571’
volumes:
- "${TEMPDIR:-/tmp/localstack}:/tmp/localstack"
- "/var/run/docker.sock:/var/run/docker.sock"
LOCALSTACK
@maciejwalkowiak @matejnedic1
$ docker-compose up
localstack_1 |
localstack_1 | __ _______ __ __
localstack_1 | / / ____ _________ _/ / ___// /_____ ______/ /__
localstack_1 | / / / __ / ___/ __ `/ /__ / __/ __ `/ ___/ //_/
localstack_1 | / /___/ /_/ / /__/ /_/ / /___/ / /_/ /_/ / /__/ ,<
localstack_1 | /_____/____/___/__,_/_//____/__/__,_/___/_/|_|
localstack_1 |
localstack_1 | & LocalStack CLI 0.12.17.3
localstack_1 |
localstack_1 | [16:23:49] starting LocalStack in host mode & localstack.py:101
localstack_1 | ──────────────── LocalStack Runtime Log (press CTRL-C to quit) ─────────────────
localstack_1 | 2021-09-01 16:23:50,722 INFO success: infra entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
localstack_1 |
localstack_1 | LocalStack version: 0.12.17.3
localstack_1 | LocalStack Docker container id: 67fb82278492
localstack_1 | LocalStack build date: 2021-09-01
localstack_1 | LocalStack build git hash: 637d9bfa
localstack_1 |
localstack_1 | Starting edge router (https port 4566)...
localstack_1 | Starting mock S3 service on http port 4566 ...
localstack_1 | 2021-09-01T16:23:54:INFO:localstack.multiserver: Starting multi API server process on port 44089
localstack_1 | [2021-09-01 16:23:54 +0000] [21] [INFO] Running on https://0.0.0.0:4566 (CTRL + C to quit)
localstack_1 | 2021-09-01T16:23:54:INFO:hypercorn.error: Running on https://0.0.0.0:4566 (CTRL + C to quit)
localstack_1 | [2021-09-01 16:23:54 +0000] [21] [INFO] Running on http://0.0.0.0:44089 (CTRL + C to quit)
localstack_1 | 2021-09-01T16:23:54:INFO:hypercorn.error: Running on http://0.0.0.0:44089 (CTRL + C to quit)
localstack_1 | Waiting for all LocalStack services to be ready
localstack_1 | Starting mock SQS service on http port 4566 ...
localstack_1 | Ready.
LOCALSTACK
@maciejwalkowiak @matejnedic1
$ aws sqs create-queue --queue-name “hello-springone" --endpoint-url http://localhost:4566
LOCALSTACK
@maciejwalkowiak @matejnedic1
$ aws sqs create-queue --queue-name “hello-springone" --endpoint-url http://localhost:4566
LOCALSTACK
{
"QueueUrl": "http://localhost:4566/000000000000/hello-springone"
}
@maciejwalkowiak @matejnedic1
$ aws sqs create-queue --queue-name “hello-springone" --endpoint-url http://localhost:4566
LOCALSTACK
{
"QueueUrl": "http://localhost:4566/000000000000/hello-springone"
}
$ aws sqs list-queues --endpoint-url http://localhost:4566
@maciejwalkowiak @matejnedic1
$ aws sqs create-queue --queue-name “hello-springone" --endpoint-url http://localhost:4566
LOCALSTACK
{
"QueueUrl": "http://localhost:4566/000000000000/hello-springone"
}
$ aws sqs list-queues --endpoint-url http://localhost:4566
{
"QueueUrls": [
"http://localhost:4566/000000000000/testqueue",
"http://localhost:4566/000000000000/hello-springone"
]
}
@maciejwalkowiak @matejnedic1
cloud.aws.sqs.endpoint: http://localhost:4566
LOCALSTACK
cloud.aws.sns.endpoint: http://localhost:4566
@maciejwalkowiak @matejnedic1
@SpringBootTest
@Testcontainers
class DemoApplicationTests {
@Container
static LocalStackContainer localstack =
new LocalStackContainer(DockerImageName.parse("localstack/localstack:0.12.17"))
.withServices(LocalStackContainer.Service.SQS);
@DynamicPropertySource
static void localstackProperties(DynamicPropertyRegistry registry) {
registry.add("clous.aws.sqs.endpoint",
() -> localstack.getEndpointOverride(LocalStackContainer.Service.SQS));
}
// ..
}
LOCALSTACK
@maciejwalkowiak @matejnedic1
LOCALSTACK
• ACM
• API Gateway
• CloudFormation
• CloudWatch
• CloudWatch Logs
• DynamoDB
• DynamoDB Streams
• EC2
• Elasticsearch Service
• EventBridge
(CloudWatch Events)
• Firehose
• IAM
• Kinesis
• KMS
• Lambda
• Redshift
• STS
• Route53
• S3
• SecretsManager
• SES
• SNS
• SQS
• SSM
• StepFunctions
@maciejwalkowiak @matejnedic1
LOCALSTACK
• Amplify
• API Gateway V2
(WebSockets support)
• AppConfig
• Application
AutoScaling
• AppSync
• Athena
• Backup
• Batch
• CloudFront
• CloudTrail
• CodeCommit
• Cognito
• CostExplorer
• DocumentDB
• ECR/ECS/EKS
• ElastiCache
• ElasticBeanstalk
• ELB/ELBv2
• EMR
• Glacier / S3 Select
• Glue
• IAM Security Policy
Enforcement
• IoT
• Kinesis Data Analytics
• Lambda Layers &
Container Images
@maciejwalkowiak @matejnedic1
LOCALSTACK
https://localstack.dev
@maciejwalkowiak @matejnedic1
FUTURE
@maciejwalkowiak @matejnedic1
•Migrate from AWS SDK v1 to AWS SDK v2
•CloudMap integration (PR ready)
•Spring Data Dynamo DB (?)
•Drop support for: ElastiCache, CloudFormation
•Improve startup times
•GraalVM Native Image compatibility
FUTURE  SPRING CLOUD AWS 3.X
@maciejwalkowiak @matejnedic1
SPRING CLOUD AWS
SAMPLES
@maciejwalkowiak @matejnedic1
https://github.com/awspring/spring-cloud-aws/tree/2.3.x/spring-cloud-aws-samples
https://awspring.io/
https://stratospheric.dev/
BJÖRN WILMSMANN
PHILIP RIECKS
TOM HOMBERGS
@maciejwalkowiak @matejnedic1
THANK YOU!
1 of 105

More Related Content

What's hot(20)

Json web tokenJson web token
Json web token
Mayank Patel2.9K views
Spring Boot and REST APISpring Boot and REST API
Spring Boot and REST API
07.pallav630 views
Spring MVCSpring MVC
Spring MVC
Aaron Schram2K views
Spring Framework - MVCSpring Framework - MVC
Spring Framework - MVC
Dzmitry Naskou10.7K views
Testing Spring Boot ApplicationsTesting Spring Boot Applications
Testing Spring Boot Applications
VMware Tanzu1.4K views
Introduction to Spring BootIntroduction to Spring Boot
Introduction to Spring Boot
Purbarun Chakrabarti1K views
Spring - Part 1 - IoC, Di and Beans Spring - Part 1 - IoC, Di and Beans
Spring - Part 1 - IoC, Di and Beans
Hitesh-Java1.3K views
Understanding JWT ExploitationUnderstanding JWT Exploitation
Understanding JWT Exploitation
AkshaeyBhosale206 views
Spring Boot in Action Spring Boot in Action
Spring Boot in Action
Alex Movila3K views
Introduction to Node.jsIntroduction to Node.js
Introduction to Node.js
AMD Developer Central 4.4K views
AngularAngular
Angular
Lilia Sfaxi22.9K views
Apigee Products OverviewApigee Products Overview
Apigee Products Overview
Apigee | Google Cloud6.5K views
REST APIs with SpringREST APIs with Spring
REST APIs with Spring
Joshua Long25.6K views
PUC SE Day 2019 - SpringBootPUC SE Day 2019 - SpringBoot
PUC SE Day 2019 - SpringBoot
Josué Neis696 views
Spring BootSpring Boot
Spring Boot
HongSeong Jeon3.9K views
Spring Boot TutorialSpring Boot Tutorial
Spring Boot Tutorial
Naphachara Rattanawilai7.8K views
Weblogic application serverWeblogic application server
Weblogic application server
Anuj Tomar1.5K views
Spring BootSpring Boot
Spring Boot
Jiayun Zhou2.5K views

Similar to Spring Boot on Amazon Web Services with Spring Cloud AWS(20)

Spring MVC Intro / Gore - Nov NHJUGSpring MVC Intro / Gore - Nov NHJUG
Spring MVC Intro / Gore - Nov NHJUG
Ted Pennings1.5K views
Multi Client Development with SpringMulti Client Development with Spring
Multi Client Development with Spring
Joshua Long2.2K views
To Microservices and BeyondTo Microservices and Beyond
To Microservices and Beyond
Matt Stine2.3K views
Agile integration workshop   AtlantaAgile integration workshop   Atlanta
Agile integration workshop Atlanta
Jeremy Davis305 views
What’s New in ASP.NET 4What’s New in ASP.NET 4
What’s New in ASP.NET 4
Todd Anglin4.6K views

Recently uploaded(20)

Omni AIOmni AI
Omni AI
mdrahman2004008 views
C-SCORE eng.pdfC-SCORE eng.pdf
C-SCORE eng.pdf
info9269315 views
Build and Modernize Intelligent Apps​Build and Modernize Intelligent Apps​
Build and Modernize Intelligent Apps​
Lorenzo Barbieri39 views
Green Cloud - Measure cloud emissionsGreen Cloud - Measure cloud emissions
Green Cloud - Measure cloud emissions
Green Software Development28 views

Spring Boot on Amazon Web Services with Spring Cloud AWS