Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Spring Boot On Amazon Web services with Spring Cloud AWS

Spring Boot On Amazon Web services with Spring Cloud AWS

Spring Cloud AWS is a community project that helps developers use the rich ecosystem of AWS-managed services within a Spring Boot application in a familiar, idiomatic way.

In this talk, you'll learn how to speed up the development process using Spring Cloud AWS features, latest additions to the framework, and plans for the future.

2da55e1342d18933f0bcaf804a02f200?s=128

Maciej Walkowiak

September 02, 2021
Tweet

More Decks by Maciej Walkowiak

Other Decks in Programming

Transcript

  1. SPRING BOOT ON AMAZON WEB SERVICES WITH SPRING CLOUD AWS

    MACIEJ WALKOWIAK MATEJ NEDIC
  2. @maciejwalkowiak @matejnedic1

  3. @maciejwalkowiak @matejnedic1

  4. @maciejwalkowiak @matejnedic1 MACIEJ WALKOWIAK - independent consultant - Spring Cloud

    AWS Lead - working with
  5. @maciejwalkowiak @matejnedic1 https://youtube.com/springacademy

  6. @maciejwalkowiak @matejnedic1 MATEJ NEDIC - Software Engineer - Spring Cloud

    AWS Core team member - working at
  7. @maciejwalkowiak @matejnedic1 SPRING CLOUD AWS

  8. @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
  9. @maciejwalkowiak @matejnedic1 SPRING CLOUD AWS MACIEJ WALKOWIAK MATEJ NEDIC EDDU

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

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

  12. @maciejwalkowiak @matejnedic1

  13. @maciejwalkowiak @matejnedic1 SPRING BOOT ON AMAZON WEB SERVICES WITH SPRING

    CLOUD AWS
  14. @maciejwalkowiak @matejnedic1 Application RDBMS

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

    •Updates •Backups •Security •Scaling •High Availability
  16. @maciejwalkowiak @matejnedic1 EC2 •! Updates •! Backups •! Security •!

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

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

  19. @maciejwalkowiak @matejnedic1 Application RDS

  20. @maciejwalkowiak @matejnedic1 Application RDS - Primary

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

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

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

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

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

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

    #1 Asynchronous Replication Write Read RDS - Read Replica #2 RDS - Read Replica #3 Read Read
  27. @maciejwalkowiak @matejnedic1 spring: datasource: url: jdbc:postgresql://springone.c0x5be2ybrmz.eu-west-2.rds.amazonaws.com:5432/postgres username: postgres password: postgres

  28. @maciejwalkowiak @matejnedic1 cloud: aws: rds: instances: - db-instance-identifier: springone database-name:

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

    postgres username: postgres password: postgres read-replica-support: true
  30. @maciejwalkowiak @matejnedic1 @Service class UserService { @Transactional void registerUser(User user)

    { ... } @Transactional(readOnly=true) User findUser(Long id) { ... } }
  31. @maciejwalkowiak @matejnedic1 https://vladmihalcea.com/read-write-read-only-transaction-routing-spring/

  32. @maciejwalkowiak @matejnedic1 •Only Tomcat connection pool supported (will change in

    3.0) •No Aurora support (will change in 3.0) WHAT IS MISSING?
  33. @maciejwalkowiak @matejnedic1 •Aurora support •IAM Authentication •RDS Proxy Support •Secrets

    Manager JDBC authentication (?) WHAT IS COMING?
  34. @maciejwalkowiak @matejnedic1 MESSAGING ON AWS

  35. @maciejwalkowiak @matejnedic1 Service A Service B HTTP

  36. @maciejwalkowiak @matejnedic1 Service A Service B

  37. @maciejwalkowiak @matejnedic1 Service A Service B

  38. @maciejwalkowiak @matejnedic1 Service A Service B

  39. @maciejwalkowiak @matejnedic1 Service A Service B

  40. @maciejwalkowiak @matejnedic1 Service A Service B

  41. @maciejwalkowiak @matejnedic1

  42. @maciejwalkowiak @matejnedic1

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

  44. @maciejwalkowiak @matejnedic1 @Service public class RegistrationService { void register(Attendee attendee)

    { // persist attendee, send confirmation email } }
  45. @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); } }
  46. @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); } }
  47. @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); } }
  48. @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(); } } }
  49. @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); } } }
  50. @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 } }
  51. @maciejwalkowiak @matejnedic1 Service A Service C Service B SNS

  52. @maciejwalkowiak @matejnedic1 Service A Service C Service B SNS

  53. @maciejwalkowiak @matejnedic1 Service A Service C Service B SNS

  54. @maciejwalkowiak @matejnedic1 Service A Service C Service B SNS

  55. @maciejwalkowiak @matejnedic1 Service A Service C Service B SNS

  56. @maciejwalkowiak @matejnedic1 Service A Service C Service B SNS

  57. @maciejwalkowiak @matejnedic1 Service A Service C Service B SNS

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

    HTTP HTTP
  59. @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); } }
  60. @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(); } }
  61. @maciejwalkowiak @matejnedic1 •Performance … •Reactive support •Spring Cloud Stream SQS

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

    (?) WHAT IS COMING?
  63. @maciejwalkowiak @matejnedic1 STORING CONFIGURATION WITH SECRETS MANAGER AND PARAMETER STORE

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

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

    Cloud Config
  66. @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
  67. @maciejwalkowiak @matejnedic1 But what if your storage for properties goes

    down?
  68. @maciejwalkowiak @matejnedic1 AWS PARAMETER STORE

  69. @maciejwalkowiak @matejnedic1

  70. @maciejwalkowiak @matejnedic1 Service A Service B Parameter store

  71. None
  72. @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/
  73. @maciejwalkowiak @matejnedic1 @Value("${message}") String message; spring.cloud.config.server.git.refreshRate=${refresh}

  74. @maciejwalkowiak @matejnedic1 AWS SECRETS MANAGER

  75. Parameter store Secret Manager

  76. Service A Parameter store Secret Manager

  77. Service A RDS Parameter store Secret Manager

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

  79. @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
  80. @maciejwalkowiak @matejnedic1 •Secret rotation support •Refreshing context on parameter and

    secret change WHAT IS COMING?
  81. @maciejwalkowiak @matejnedic1 OTHER SUPPORTED SERVICES •S3 •EC2 metadata •Cloud Watch

    •ElastiCache (Redis & Memcached) •SES (Simple Email Service) •Cloud Formation
  82. @maciejwalkowiak @matejnedic1

  83. @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
  84. @maciejwalkowiak @matejnedic1 •AWS SDK: •AWS SDK v1 •AWS SDK v2

    WHEN SPRING CLOUD AWS IS NOT ENOUGH
  85. @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
  86. @maciejwalkowiak @matejnedic1 TESTING

  87. @maciejwalkowiak @matejnedic1 TESTING WITH LOCALSTACK

  88. @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
  89. @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
  90. @maciejwalkowiak @matejnedic1 $ aws sqs create-queue --queue-name “hello-springone" --endpoint-url http://localhost:4566

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

    LOCALSTACK { "QueueUrl": "http://localhost:4566/000000000000/hello-springone" }
  92. @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
  93. @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" ] }
  94. @maciejwalkowiak @matejnedic1 cloud.aws.sqs.endpoint: http://localhost:4566 LOCALSTACK cloud.aws.sns.endpoint: http://localhost:4566

  95. @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
  96. @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
  97. @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
  98. @maciejwalkowiak @matejnedic1 LOCALSTACK https://localstack.dev

  99. @maciejwalkowiak @matejnedic1 FUTURE

  100. @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
  101. @maciejwalkowiak @matejnedic1 SPRING CLOUD AWS SAMPLES

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

  103. https://awspring.io/

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

  105. @maciejwalkowiak @matejnedic1 THANK YOU!