How to communicate microservices
- @FeignClient (ApiClient)
- Kafka (Use Event)
- RestTemplate (communicate with REST API)
- Circuit Breaker (Fault Tolerant Design Pattern)
Spring Cloud
a framework for building robust cloud(strong and healthy) applications. (= microservices)
Spring Cloud Stream
A lightweight event-driven microservices framework to quickly build applications that can connect to external systems. Simple declarative model to send and receive messages using Apache Kafka(middleware) or RabbitMQ between Spring Boot apps.
@FeignClient
- Microservices communication method in Spring Boot
- @EnableFeignClients
user-service
build.gradle
1
2
3
dependencies {
implementation group: 'org.springframework.cloud', name: 'spring-cloud-starter-openfeign', version: '2.1.1.RELEASE'
}
user-service
1
2
3
4
@EnableFeignClients
public class ApiClientConfiguration {
...
}
departments-service
1
2
3
4
5
6
7
8
@FeignClient(name = "user", contextId = "userEnvironmentSetting", url = "${...}")
@RequestMapping(path="/users", consumes = "application/json")
interface UserEnvironmentSettingClient {
@Override
@GetMapping("/users/environmentSetting")
Map<String, String> getEnvironmentSetting();
}
- name : LoadBalancer client name
- contextId : bean name instead of name if present
- issue : λμΌ name μΌλ‘ λκ°μ class μμ μ§μ νλ©΄ μ€λ₯ λ°μ
- reference: https://techblog.woowahan.com/2630/
RestTemplate
- Spring Http communication template (Rest API μλΉμ€λ₯Ό μμ² ν μλ΅λ°μ λ μ£Όλ‘ μ¬μ©)
- For communiating over the microservices
- Synchronize (Async : org.springframework.web.client.AsyncRestTemplate)
- will be deprecated
build.gradle
1
implementation 'org.springframework.boot:spring-boot-starter-web'
RestTemplate VS WebCLient
Β | RestTemplate | WebCLient |
---|---|---|
Β | Sync | Async (= AsyncRestTemplate) |
Dependency | implementation βorg.springframework.boot:spring-boot-starter-webβ | implementation βorg.springframework.boot:spring-boot-starter-webfluxβ |
- reference
https://backtony.github.io/spring/2021-07-12-spring-basic-8/
https://blog.naver.com/hj_kim97/222295259904
https://sjh836.tistory.com/141
Blocking VS Non-Blocking VS Sync VS Async
- Blocking / Non-blocking
- λ€λ₯Έ μ£Όμ²΄κ° μμ ν λ μμ μκ² μμ μ μμ μ λν μ μ΄κΆμ΄ μλμ§ μλμ§
Β | Blocking | Non-blocking |
---|---|---|
Β | νΈμΆλ ν¨μκ° μμ μ μμ
μ λͺ¨λ λ§μΉ λκΉμ§ νΈμΆν ν¨μμκ² μ μ΄κΆμ λκ²¨μ£Όμ§ μκ³ λκΈ°νκ² λ§λ λ€λ©΄ (executes βin seriesβ) | νΈμΆλ ν¨μκ° λ°λ‘ 리ν΄ν΄μ νΈμΆν ν¨μμκ² μ μ΄κΆμ λκ²¨μ£Όκ³ , νΈμΆν ν¨μκ° λ€λ₯Έ μΌμ ν μ μλ κΈ°νλ₯Ό μ€ μ μμΌλ©΄ (executes in parallel) |
Example | μ§μμ΄ μμ¬μκ² μλ₯λ₯Ό μ μΆνκ³ , μμ¬κ° μλ₯λ₯Ό λ€ μ½μ λκΉμ§ μ리μμ κΈ°λ€λ¦¬λ μν© | μ§μμ΄ μμ¬μκ² μλ₯λ₯Ό μ μΆνμ§λ§, μμ¬κ° μλ₯λ₯Ό λ€ μ½μ΄λ³Ό λμ μ리μ κ°μ μμ μ μΌμ μ²λ¦¬νλ μν© |
- Sync / Async
- κ·Έκ²μ μμ²ν μμκ° μ§μΌμ§λκ° μλκ° (νΈμΆλλ ν¨μμ μμ μλ£ μ¬λΆλ₯Ό λκ° μ κ²½μ°λ)
Β | Synchronous | Asynchronous |
---|---|---|
Β | μμ
μ λμμ μννκ±°λ, λμμ λλκ±°λ, λλλ λμμ μμν¨ (κ²°κ³Όλ₯Ό 리ν΄λ°μμ λ λ°λ‘ κ·Έ κ²°κ³Όμ μ§μ€ν¨ / scheduled, real-time) | μμ, μ’
λ£κ° μΌμΉνμ§ μμΌλ©° λλλ λμμ μμμ νμ§ μμ (κ²°κ³Όλ₯Ό λ°λ‘ μ²λ¦¬νμ§ μμλ λ¨ / on your own time, no need schedule / use callback) |
Β | When a work is requested, the result value of the request is directly returned. | When a work is requested, the result value of the request is indirectly received |
Β | μμ²μ λ³΄λΈ ν μλ΅μ λ°μμΌμ§λ§ λ€μ λμμ΄ μ΄λ£¨μ΄μ§ | μΉ νμ΄μ§ μ 체λ₯Ό μλ‘κ³ μΉ¨ νμ§μκ³ λ°μ΄ν°λ₯Ό λΆλ¬μ€λ λ°©μ |
Β | λΉλκΈ° λ°©μμ λΉν΄ μ€κ³κ° λ§€μ° κ°λ¨νκ³ μ§κ΄μ μ΄μ§λ§ κ²°κ³Όκ° μ£Όμ΄μ§ λ κΉμ§ μ무 κ²λ λͺ»νκ³ λκΈ°ν΄μΌν¨ | λΉλκΈ° λ°©μμ μ΄μ©ν κ²½μ°, νμν λΆλΆμ λ°μ΄ν°λ§ λΆλ¬μ μ¬μ© κ°λ₯. κ²°κ³Όκ° μ£Όμ΄μ§λλ° μκ°μ΄ 걸리λλΌλ κ·Έ μκ°λμ λ€λ₯Έ μμ μ ν μ μμΌλ―λ‘ μμμ ν¨μ¨μ μ¬μ© κ°λ₯ |
Example | μμ¬κ° μλ₯λ₯Ό λ€ μ½κ³ κ²°κ³Όλ₯Ό 리ν΄ν΄μ£Όλ©΄ μ§μμ λ°λ‘ κ·Έ κ²°κ³Όμ κ΄μ¬μ κ°κ² λ©λλ€. | μμ¬κ° 리ν΄ν κ²°κ³Όλ₯Ό λ°λ‘ μ²λ¦¬ν μ§, λμ€μ μ²λ¦¬ν μ§λ₯Ό κ²°μ ν μ μμ΅λλ€. |
common used : sync-blocking, sync-nonblocking, async-nonblocking (most efficient)
reference
https://studyandwrite.tistory.com/486
https://baek-kim-dev.site/38
CircuitBreaker (Design pattern using netfilx hystrix)
- Hystrix
- library form Netflix (spring-cloud-starter-netflix), isolates the points of access between the services, stops cascading failures across thhem and provides the fallback options
- Fallback
- provides an alternative solution during a service request failure
- Circuit Breaker Pattern
- prevents failure cascading and gives a default behavior when services fail
- Netflix Hystrix
- allows us to introduce fault tolerance and latency tolerance by isolating failure and by preventing them from cascading into the other part of the system building a more robust distributed application.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Service
public class GreetingService {
@HystrixCommand(fallbackMethod = "defaultGreeting")
public String getGreeting(String username) {
return new RestTemplate()
.getForObject("http://localhost:9090/greeting/{username}",
String.class, username);
}
private String defaultGreeting(String username) {
return "Hello User!";
}
}
- @EnableCircuitBreaker
- will scan the classpath for any compatible Circuit Breaker implementation.
1
2
3
4
5
6
7
@SpringBootApplication
@EnableCircuitBreaker
public class RestConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(RestConsumerApplication.class, args);
}
}
Hystrix VS Resilience4J
- common feature : fault tolerant library
Hystrix | Resilience4J |
---|---|
embraces an Object-Oriented design where calls to external systems have to be wrapped in a HystrixCommand offering multiple functionalities. | relies on function composition to let you stack the specific decorators you need. |
- reference
https://engineering.linecorp.com/ko/blog/circuit-breakers-for-distributed-services/
https://www.baeldung.com/spring-cloud-netflix-hystrix
https://digitalvarys.com/what-is-circuit-breaker-design-pattern/
API Gateway (Load balancing)
Service : Cloud-gateway
spring-cloud-starter-gateway
bulid.gradle
1
2
3
dependencies {
compile 'org.springframework.cloud:spring-cloud-starter-gateway:2.1.0.RELEASE'
}
application.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
server:
port: 9191
spring:
cloud:
gateway:
routes:
- id: USER-SERVICE
url: ${cloud-gateway.user-url}
predicates:
- Path=/users/ **
- id: DEPARTMENT-SERVICE
url: ${cloud-gateway.department-url}
predicates:
- Path=/departments/ **
filter:
- name: CircuitBreaker
args:
name: USER-SERVICE
fallbackuri: forward:/userServiceFallBack
cloud-gateway:
user-url: http://cloud-user-service:9001
department-url: http://cloud-department-service:9002
Meaning:
when you call http://localhost:9191/users/1, it goes to http://localhost:9001/users/1
when you call http://localhost:9191/departments/1, it goes to http://localhost:9002/departments/1
reference : https://cloud.spring.io/spring-cloud-gateway/reference/html/#configuration
Spring-boot-starter-actuator
bulid.gradle
1
2
3
dependencies {Β
compile("org.springframework.boot:spring-boot-starter-actuator")
}
application.yml
From spring boot 2.x, you have to custom management
part in application.yml because the default setting is not exposing most datas.
1
2
3
4
5
management:
endpoints:
web:
exposure:
include: health
Meaning : expose the health
information
1
2
3
4
5
management:
endpoints:
web:
exposure:
exclude: env, beans
Meaning : expose the information except for env, beans
the property exclude
is prior than include
, so if you declared some information on exclude, you canβt see it even if you declared that on include.
- reference : https://jeong-pro.tistory.com/160
Spring Cloud Stream
- μ΄λ²€νΈ μ€μ¬ microservcieλ₯Ό ꡬμΆνκΈ° μν νλ μμν¬
- Apache Kafka λλ RabbitMQ λ±μ μ¬μ©νμ¬ Spring Boot μ΄ν리μΌμ΄μ κ³Ό λ©μΈμ§λ₯Ό 보λ΄κ³ λ°μ.
https://saramin.github.io/2019-08-28-2/
Comments powered by Disqus.