Slide 1

Slide 1 text

SPRING BOOT ON AMAZON WEB SERVICES WITH SPRING CLOUD AWS MACIEJ WALKOWIAK MATEJ NEDIC

Slide 2

Slide 2 text

@maciejwalkowiak @matejnedic1

Slide 3

Slide 3 text

@maciejwalkowiak @matejnedic1

Slide 4

Slide 4 text

@maciejwalkowiak @matejnedic1 MACIEJ WALKOWIAK - independent consultant - Spring Cloud AWS Lead - working with

Slide 5

Slide 5 text

@maciejwalkowiak @matejnedic1 https://youtube.com/springacademy

Slide 6

Slide 6 text

@maciejwalkowiak @matejnedic1 MATEJ NEDIC - Software Engineer - Spring Cloud AWS Core team member - working at

Slide 7

Slide 7 text

@maciejwalkowiak @matejnedic1 SPRING CLOUD AWS

Slide 8

Slide 8 text

@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

Slide 9

Slide 9 text

@maciejwalkowiak @matejnedic1 SPRING CLOUD AWS MACIEJ WALKOWIAK MATEJ NEDIC EDDU MELENDEZ

Slide 10

Slide 10 text

@maciejwalkowiak @matejnedic1 SPRING CLOUD AWS https://github.com/awspring/spring-cloud-aws

Slide 11

Slide 11 text

@maciejwalkowiak @matejnedic1 SPRING CLOUD AWS https://github.com/awspring/spring-cloud-aws

Slide 12

Slide 12 text

@maciejwalkowiak @matejnedic1

Slide 13

Slide 13 text

@maciejwalkowiak @matejnedic1 SPRING BOOT ON AMAZON WEB SERVICES WITH SPRING CLOUD AWS

Slide 14

Slide 14 text

@maciejwalkowiak @matejnedic1 Application RDBMS

Slide 15

Slide 15 text

@maciejwalkowiak @matejnedic1 EC2 •Updates •Backups •Security •Scaling •High Availability RDS •Updates •Backups •Security •Scaling •High Availability

Slide 16

Slide 16 text

@maciejwalkowiak @matejnedic1 EC2 •! Updates •! Backups •! Security •! Scaling •! High Availability RDS •✅ Updates •✅ Backups •✅ Security •✅ Scaling •✅ High Availability

Slide 17

Slide 17 text

@maciejwalkowiak @matejnedic1 EC2 •! Updates •! Backups •! Security •! Scaling •! High Availability RDS •✅ Updates •✅ Backups •✅ Security •✅ Scaling •✅ High Availability #

Slide 18

Slide 18 text

@maciejwalkowiak @matejnedic1

Slide 19

Slide 19 text

@maciejwalkowiak @matejnedic1 Application RDS

Slide 20

Slide 20 text

@maciejwalkowiak @matejnedic1 Application RDS - Primary

Slide 21

Slide 21 text

@maciejwalkowiak @matejnedic1 Application RDS - Primary RDS - Read Replica

Slide 22

Slide 22 text

@maciejwalkowiak @matejnedic1 Application RDS - Primary RDS - Read Replica Asynchronous Replication

Slide 23

Slide 23 text

@maciejwalkowiak @matejnedic1 Application RDS - Primary RDS - Read Replica Asynchronous Replication

Slide 24

Slide 24 text

@maciejwalkowiak @matejnedic1 Application RDS - Primary RDS - Read Replica Asynchronous Replication

Slide 25

Slide 25 text

@maciejwalkowiak @matejnedic1 Application RDS - Primary RDS - Read Replica Asynchronous Replication Write Read

Slide 26

Slide 26 text

@maciejwalkowiak @matejnedic1 Application RDS - Primary RDS - Read Replica #1 Asynchronous Replication Write Read RDS - Read Replica #2 RDS - Read Replica #3 Read Read

Slide 27

Slide 27 text

@maciejwalkowiak @matejnedic1 spring: datasource: url: jdbc:postgresql://springone.c0x5be2ybrmz.eu-west-2.rds.amazonaws.com:5432/postgres username: postgres password: postgres

Slide 28

Slide 28 text

@maciejwalkowiak @matejnedic1 cloud: aws: rds: instances: - db-instance-identifier: springone database-name: postgres username: postgres password: postgres

Slide 29

Slide 29 text

@maciejwalkowiak @matejnedic1 cloud: aws: rds: instances: - db-instance-identifier: springone database-name: postgres username: postgres password: postgres read-replica-support: true

Slide 30

Slide 30 text

@maciejwalkowiak @matejnedic1 @Service class UserService { @Transactional void registerUser(User user) { ... } @Transactional(readOnly=true) User findUser(Long id) { ... } }

Slide 31

Slide 31 text

@maciejwalkowiak @matejnedic1 https://vladmihalcea.com/read-write-read-only-transaction-routing-spring/

Slide 32

Slide 32 text

@maciejwalkowiak @matejnedic1 •Only Tomcat connection pool supported (will change in 3.0) •No Aurora support (will change in 3.0) WHAT IS MISSING?

Slide 33

Slide 33 text

@maciejwalkowiak @matejnedic1 •Aurora support •IAM Authentication •RDS Proxy Support •Secrets Manager JDBC authentication (?) WHAT IS COMING?

Slide 34

Slide 34 text

@maciejwalkowiak @matejnedic1 MESSAGING ON AWS

Slide 35

Slide 35 text

@maciejwalkowiak @matejnedic1 Service A Service B HTTP

Slide 36

Slide 36 text

@maciejwalkowiak @matejnedic1 Service A Service B

Slide 37

Slide 37 text

@maciejwalkowiak @matejnedic1 Service A Service B

Slide 38

Slide 38 text

@maciejwalkowiak @matejnedic1 Service A Service B

Slide 39

Slide 39 text

@maciejwalkowiak @matejnedic1 Service A Service B

Slide 40

Slide 40 text

@maciejwalkowiak @matejnedic1 Service A Service B

Slide 41

Slide 41 text

@maciejwalkowiak @matejnedic1

Slide 42

Slide 42 text

@maciejwalkowiak @matejnedic1

Slide 43

Slide 43 text

@maciejwalkowiak @matejnedic1 https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-basic-architecture.html

Slide 44

Slide 44 text

@maciejwalkowiak @matejnedic1 @Service public class RegistrationService { void register(Attendee attendee) { // persist attendee, send confirmation email } }

Slide 45

Slide 45 text

@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); } }

Slide 46

Slide 46 text

@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); } }

Slide 47

Slide 47 text

@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); } }

Slide 48

Slide 48 text

@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(); } } }

Slide 49

Slide 49 text

@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); } } }

Slide 50

Slide 50 text

@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 } }

Slide 51

Slide 51 text

@maciejwalkowiak @matejnedic1 Service A Service C Service B SNS

Slide 52

Slide 52 text

@maciejwalkowiak @matejnedic1 Service A Service C Service B SNS

Slide 53

Slide 53 text

@maciejwalkowiak @matejnedic1 Service A Service C Service B SNS

Slide 54

Slide 54 text

@maciejwalkowiak @matejnedic1 Service A Service C Service B SNS

Slide 55

Slide 55 text

@maciejwalkowiak @matejnedic1 Service A Service C Service B SNS

Slide 56

Slide 56 text

@maciejwalkowiak @matejnedic1 Service A Service C Service B SNS

Slide 57

Slide 57 text

@maciejwalkowiak @matejnedic1 Service A Service C Service B SNS

Slide 58

Slide 58 text

@maciejwalkowiak @matejnedic1 Service A Service C Service B SNS HTTP HTTP HTTP

Slide 59

Slide 59 text

@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); } }

Slide 60

Slide 60 text

@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(); } }

Slide 61

Slide 61 text

@maciejwalkowiak @matejnedic1 •Performance … •Reactive support •Spring Cloud Stream SQS (?) WHAT IS COMING?

Slide 62

Slide 62 text

@maciejwalkowiak @matejnedic1 •Performance … •Reactive support •Spring Cloud Stream SQS (?) WHAT IS COMING?

Slide 63

Slide 63 text

@maciejwalkowiak @matejnedic1 STORING CONFIGURATION WITH SECRETS MANAGER AND PARAMETER STORE

Slide 64

Slide 64 text

@maciejwalkowiak @matejnedic1 https://cloud.spring.io/spring-cloud-config/reference/html/ Service A Service B Service C

Slide 65

Slide 65 text

@maciejwalkowiak @matejnedic1 https://cloud.spring.io/spring-cloud-config/reference/html/ Service A Service B Service C Spring Cloud Config

Slide 66

Slide 66 text

@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

Slide 67

Slide 67 text

@maciejwalkowiak @matejnedic1 But what if your storage for properties goes down?

Slide 68

Slide 68 text

@maciejwalkowiak @matejnedic1 AWS PARAMETER STORE

Slide 69

Slide 69 text

@maciejwalkowiak @matejnedic1

Slide 70

Slide 70 text

@maciejwalkowiak @matejnedic1 Service A Service B Parameter store

Slide 71

Slide 71 text

No content

Slide 72

Slide 72 text

@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/

Slide 73

Slide 73 text

@maciejwalkowiak @matejnedic1 @Value("${message}") String message; spring.cloud.config.server.git.refreshRate=${refresh}

Slide 74

Slide 74 text

@maciejwalkowiak @matejnedic1 AWS SECRETS MANAGER

Slide 75

Slide 75 text

Parameter store Secret Manager

Slide 76

Slide 76 text

Service A Parameter store Secret Manager

Slide 77

Slide 77 text

Service A RDS Parameter store Secret Manager

Slide 78

Slide 78 text

@maciejwalkowiak @matejnedic1 spring.config.import=aws-secretmanager:/secret/db/prod/url spring.config.import=optional:aws-secretmanager:/secret/common spring.datasoruce.url=${url}

Slide 79

Slide 79 text

@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

Slide 80

Slide 80 text

@maciejwalkowiak @matejnedic1 •Secret rotation support •Refreshing context on parameter and secret change WHAT IS COMING?

Slide 81

Slide 81 text

@maciejwalkowiak @matejnedic1 OTHER SUPPORTED SERVICES •S3 •EC2 metadata •Cloud Watch •ElastiCache (Redis & Memcached) •SES (Simple Email Service) •Cloud Formation

Slide 82

Slide 82 text

@maciejwalkowiak @matejnedic1

Slide 83

Slide 83 text

@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

Slide 84

Slide 84 text

@maciejwalkowiak @matejnedic1 •AWS SDK: •AWS SDK v1 •AWS SDK v2 WHEN SPRING CLOUD AWS IS NOT ENOUGH

Slide 85

Slide 85 text

@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

Slide 86

Slide 86 text

@maciejwalkowiak @matejnedic1 TESTING

Slide 87

Slide 87 text

@maciejwalkowiak @matejnedic1 TESTING WITH LOCALSTACK

Slide 88

Slide 88 text

@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

Slide 89

Slide 89 text

@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

Slide 90

Slide 90 text

@maciejwalkowiak @matejnedic1 $ aws sqs create-queue --queue-name “hello-springone" --endpoint-url http://localhost:4566 LOCALSTACK

Slide 91

Slide 91 text

@maciejwalkowiak @matejnedic1 $ aws sqs create-queue --queue-name “hello-springone" --endpoint-url http://localhost:4566 LOCALSTACK { "QueueUrl": "http://localhost:4566/000000000000/hello-springone" }

Slide 92

Slide 92 text

@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

Slide 93

Slide 93 text

@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" ] }

Slide 94

Slide 94 text

@maciejwalkowiak @matejnedic1 cloud.aws.sqs.endpoint: http://localhost:4566 LOCALSTACK cloud.aws.sns.endpoint: http://localhost:4566

Slide 95

Slide 95 text

@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

Slide 96

Slide 96 text

@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

Slide 97

Slide 97 text

@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

Slide 98

Slide 98 text

@maciejwalkowiak @matejnedic1 LOCALSTACK https://localstack.dev

Slide 99

Slide 99 text

@maciejwalkowiak @matejnedic1 FUTURE

Slide 100

Slide 100 text

@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

Slide 101

Slide 101 text

@maciejwalkowiak @matejnedic1 SPRING CLOUD AWS SAMPLES

Slide 102

Slide 102 text

@maciejwalkowiak @matejnedic1 https://github.com/awspring/spring-cloud-aws/tree/2.3.x/spring-cloud-aws-samples

Slide 103

Slide 103 text

https://awspring.io/

Slide 104

Slide 104 text

https://stratospheric.dev/ BJÖRN WILMSMANN PHILIP RIECKS TOM HOMBERGS

Slide 105

Slide 105 text

@maciejwalkowiak @matejnedic1 THANK YOU!