Spring BOOT에서 분산처리 가능한 마이크로 서비스 아키텍처를 채택하기위해 SpringBootCloud및 파편화되는 모놀리식과 함께
Spring Boot를 Cluster화하는 작동가능한 코드와 함께 AkkaCluster의 특징을 알아보겠습니다.
Spring Boot Cloud
SpringBoot Cloud는 쿠버가 표준화 되기전까지 마이크로 서비스 아키텍처를 지원하는 매력적인 장치가 많이있었으나
쿠버클러스터 내에서도 상호연동해 더 매력적인 요소가 될수도 있겠지만~ 애매하게 겹치는 부분때문에 비슷한요소를 Java기반에 서버를 하나더 운영해야한다는 것은 부담이 될수 있습니다.
쿠버도입시 대체가능한 Spring Boot Cloud요소
Spring Cloud Component | Kubernetes 대체 요소 |
Config Server | ConfigMap, Secret |
Service Discovery (Eureka) | DNS, Service |
API Gateway (Zuul, Gateway) | Ingress, Ingress Controller |
추가(고급 통신 관리) | Service Mesh (Istio, Linkerd) |
- 쿠버는 사실상 표준이 되었으며~ 쿠버등장이전 Spring Cloud가 지원하는 장치는 매력적임에 분명합니다.
파편화된 모놀리스
때때로 "파편화된 모놀리스"라고 불리는 안티 패턴도 있습니다. 서로 독립적으로 빌드되고 배포되는 여러 서비스가 있지만, 공유 클러스터, 서비스 API 호출에 대한 공유 코드 및 종속성 또는 공유 데이터베이스 스키마와 같이 이를 매우 위험하게 만드는 긴밀한 결합이 있습니다. 코드와 배포 단위의 물리적 분리로 인해 자율성에 대한 잘못된 감각이 있지만, 한 서비스의 구현 변경 사항이 다른 서비스의 동작으로 누출되어 문제가 발생할 가능성이 높습니다.
이런 상황에 처한 조직은 종종 여러 서비스의 배포를 중앙에서 조정하려고 시도하여 대응하는데, 이때는 마이크로서비스의 주요 이점을 잃고 비용을 떠안게 됩니다. 실제로 분리할 수 없는 것들을 별도로 빌드하고 배포하는 중간 상태에 있습니다. 어떤 사람들은 이렇게 하고, 어떤 사람들은 이를 작동하게 만들지만, 이는 권장할 만한 일이 아니며 신중하게 관리해야 합니다.
- 싱글톤 확장
- 단일어플리케이션에서 싱글톤패턴으로 작성된 기능은 중복수행을 하게됩니다. 이 모듈이 일정산이고 중복작동하면 비즈니스의 치명적인 결함을 가져올수 있습니다.
- 세션확장
- 어플리케이션이 수평확장되지만 어플리케이션간 정보를 공유하지 못함으로 세션을 중앙관리할 외부장치를 도입하게 됩니다.
- 단일지점 병목
- RDB단일지점 병목현상이 빠르게 증가합니다. 이때도 Nosql을 포함 다양한 외부장치를 도입하게 됩니다.
모놀리식 확장의 대부분의 문제는 설계없이 즉각 도입한 장치를 사용하고 파편화된 저장소를 계속 만들어가면서 파편화되는 모놀리식을 양산하는데 있으며 마치 이것이
마이크로 서비스의 확장으로 착각하는 경우가 있습니다.
Akka Cluster의 경우 모놀리식으로도 구성이 가능하며 필요하면 분리작동 시킬수 있습니다. 여기서는 모놀리식이란 표현보다 StandAlone으로 작동도 하고 필요하면 특정기능을 분산배치할수도 있는
AkkaCluster의 특징을 살펴보겠습니다.
AkkaCluster 마이크로서비스 특징
경계를 구분하고 분산처리가능 한 클러스터 시스템이 StandAlone 로 구성이 가능하며, 필요하면 특정 기능만 독립적으로 분리 작동시킬수도 있습니다.
전통적인 모놀리식이 확장됨에 따라 어떠한 요소가 필요로하게 되는지 먼저 살펴보겠습니다.
모놀리식으로 구성후 코드의 변경없이 단일지점처리/분산처리를 구성요소 변경만으로 확장할수 있는것이 AkkaCluster의 장점입니다.
모놀리식의 가장 큰장점은 로컬에서 전체가 작동되며 디버깅도 가능하다란 점입니다. 이 지점이 개발을 가속화하는 모놀리식의 특징중 하나입니다.
로컬 디벙깅이 가능하다란점은 유닛테스트로 확장할수도 있다란점이며, 모놀리식의 장점을 잃은 파편화된 모놀리식은 대부분 디버깅능력과 함께 유닛테스트 방법까지 함께 잃게되는 단점이있습니다.
클라우드의 발전과 함께 PaaS를 채택해 로컬에서 수행못하게 되는 경우도 있을수 있지만 로컬에서 AllinOne 작동되고 디버깅되는 StandAlone 방법을 먼저 준비하고
클러스터화된 멀티노드를 유닛테스트 할수 있는 방법까지 살펴보겠습니다.
Gradle Multi Runner
### Standalone ``` shell ./gradlew bootRun -PserverPort=9090 -PclusterConfig=standalone ``` ### Seed Node ``` shell ./gradlew bootRun -PserverPort=9090 -PclusterConfig=lighthouse ``` ### Node1 ``` shell ./gradlew bootRun -PserverPort=9091 -PclusterConfig=cluster1 ``` ### Node2 ``` shell ./gradlew bootRun -PserverPort=9092 -PclusterConfig=cluster2 ```
build.gradle.kts
tasks.named<org.springframework.boot.gradle.tasks.run.BootRun>("bootRun") { doFirst { val args = mutableListOf<String>() if (project.hasProperty("serverPort")) { args.add("-Dserver.port=${project.property("serverPort")}") } if (project.hasProperty("clusterConfig")) { args.add("-DCluster=${project.property("clusterConfig")}") } if (args.isNotEmpty()) { jvmArgs = args } } }