스프링캠프에서 발표한 세션내용입니다. http://www.springcamp.io/2018/
마이크로서비스가 본격적으로 확산이되면 API 제공자와 사용자간의 dependency가 생겨서 마이크로서비스 API의 개선과정이 매우 복잡해지고 느려지게됩니다. 이 문제를 해결하기 위해 Consumer Driven Contract기법을 적용한 Spring cloud contract 프로젝트의 활용방법에 대해 소개하고 샘플 애플리케이션을 통해 개발자들이 API를 개발하고 테스트하며 개선하는 방식에 대해 알아봅니다
3. Spring Camp 2018 3
Message from Marcin
Spring Cloud developer at Pivotal working mostly on
● Spring Cloud Sleuth
● Spring Cloud Contract
● Spring Cloud Pipelines
Connect with me
● Twitter: @mgrzejszczak
● Blog: http://toomuchcoding.com
10. Spring Camp 2018 10
우리의 IT환경은 점점
• 마이크로 서비스팀이 점점 작아지고 많아짐
• API contract 개선이 더 잦아짐(Agile)
• 다른 시간대(Timezone)의 팀간의 협업이 요구됨
11. Spring Camp 2018 11
풀기 어려운 문제
1. Consumer에 영향없이 Producer서비스에 새로운 것을
추가하거나 삭제할 수 있을까?
2. Consumer가 Producer서비스를 어떻게 사용하고 있는지를
Producer서비스 개발자가 알 수 있을까?
3. Producer서비스의 릴리즈 사이클을 짧게 할 수 있을까?
12. Spring Camp 2018 12
웹서비스 진화를 위한 패턴
• Single Message Argument
• Dataset Amendment
• Tolerant Reader
• Schema Versioning
• Consumer-Driven Contracts
http://www.servicedesignpatterns.com/WebServiceEvolution
15. Spring Camp 2018 15
Consumer Driven Contracts의 장점
• Producer는 불필요한 서비스 개발을 줄일 수 있음
(make the right thing)
• Producer는 개선에 대한 통찰을 얻을 수 있음
• Agile실현을 위한 자동화을 가속화함
16. Spring Camp 2018 16
Consumer Driven Contracts가 성공하려면
Contract(API) 스펙 정의
API 문서화
REST API 테스트
API스펙과 일치하는 테스트코드 유지
API동작을 모니터링/제어
API Gateway
Consumer Driven Contract의
핵심은 커뮤니케이션
26. Spring Camp 2018 26
Spring Cloud Contract 목표
1. Contract를 공유하는 메커니즘을 제공 (Consumer Driven Contract)
- 정의하고 읽기 쉬운 형태로 Contract 형식(DSL)
- REST, Messaging 지원
2. Contract를 적용할 때 자동화를 통해 확신을 주자
- Producer는 Contract를 만족하는 Producer Stubs를 자동 생,
Producer테스트에 활용
- Consumer의 테스트코드는 Producer가 테스트에 활용한 그 stub을 다
운로드, stub은 정합성이 보장
- 서비스로 넘어가기전에 Fail-Fast
27. Spring Camp 2018 27
Spring Cloud Contract Maven Plugin
Spring cloud Contract verifier
<dependency>
<groupId>org.Springframework.cloud</groupId>
<artifactId>Spring-cloud-starter-contract-verifier</artifactId>
<scope>test</scope>
</dependency>
Spring cloud Contract stub runner
<dependency>
<groupId>org.Springframework.cloud</groupId>
<artifactId>Spring-cloud-contract-stub-runner</artifactId>
<scope>test</scope>
</dependency>
28. Spring Camp 2018 28
Contract로 부터 자동으로 stub.jar 생성
$ mvn clean install OutputsReads
Producer테스트용
Junit 테스트케이스
Contract.make {
request{
url "/check"
method POST()
body(
age: value(regex('[2-9][0-9]')))
headers{
contentType(applicationJson()) } }
response{
status 200
body("""
{"status": "OK" }
"””)
}
Producer-stub.jar
• Contract정의파일
• Wiremock stub 정의(json)
29. Spring Camp 2018 29
Consumer는 자동으로 stub을 내려받아
Mock서버를 생성
Producer-stub.jar
Spring-cloud-contract-stub-runner
자동 다운로드
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureWireMock
@AutoConfigureStubRunner(workOffline=true,
ids="com.example:beer-server:+:stubs:8081")
public class BeerClientApplicationTests {
@Test
public void old_enough_stubs() {
…
}
30. Spring Camp 2018 30
Spring Cloud Contract workflow
Contract 정의/테스트
(stub runner offline
mode)
Contract 구현/테스트
Contract stubs.jar 자동생성
(sub runner offline mode)
Contract 정의
Pull Request
Consumer Project Producer Project
stub.jar 업로드
Stub.jar
자동 다운로드
Contract stubs.jar를
이용한 consumer테스트
(stub runner online
mode)
31. Spring Camp 2018 31
활용 시나리오 데모
1. 기본동작
2. Stateful 시나리오 지원
3. Stub을 Mock Server로 실행하기
4. Spring cloud 지원
5. Contract 파일 관리 방안
6. 다양한 언어 지원
7. PACT 파일 지원
8. Spring cloud pipeline에 활용
38. Spring Camp 2018 38
State-machine처럼 이전상태에 기반한 상태전이
테스트가 가능
Consumer
SOBER
Producer stub
TIPSY
Drunk
curl X POST localhost/beer
=> {"currentStatus":"TIPSY","previousStatus":"SOBER”}
curl X POST localhost/beer
=> {"currentStatus":”DRUNK","previousStatus":"TIPSY”}
WASTED curl X POST localhost/beer
=> {"currentStatus":”WASTED","previousStatus":”DRUNK”}
https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/master/
producer
39. Spring Camp 2018 39
시나리오 순서대로 Contract를 정의
request {
method 'POST'
url '/beer'
body( name: "marcin”)
}
response {
status 200
body(
previousStatus: "SOBER",
currentStatus: "TIPSY"
)
request {
method 'POST'
url '/beer'
body( name: "marcin”)
}
response {
status 200
body(
previousStatus: "TIPSY",
currentStatus: "DRUNK"
)
43. Spring Camp 2018 43
Spring cloud를 연동하는 테스트케이스 지원
Beer-client-controller.java
ResponseEntity<Response> response =
this.restTemplate.exchange(
RequestEntity
.post(URI.create("http://beer-api-from-eureka/check"))
.body(person),
Response.class);
테스트 코드
@@AutoConfigureMockMvc
public class BeerControllerTest {
Stub runner boot
beer-api-from-eureka
https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/master/
consumer_with_discovery
44. Spring Camp 2018 44
Spring cloud를 연동하는 테스트케이스 지원
Beer-client-controller.java
stubrunner:
idsToServiceIds:
beer-api-stub: beer-api-from-eureka
Test/
applicaton.yml
ResponseEntity<Response> response =
this.restTemplate.exchange(
RequestEntity
.post(URI.create("http://beer-api-from-eureka/check"))
.body(person),
Response.class);
테스트 코드
@@AutoConfigureMockMvc
@AutoConfigureStubRunner(workOffline = true, ids =
"com.example:beer-api-stub")
public class BeerControllerTest {
Stub runner boot
beer-api-from-eureka
beer-api-stub
45. Spring Camp 2018 45
Spring cloud eureka에 stub자동등록 지원
Stub runner boot
Spring cloud
Stub runner boot
eureka에 stub들을
자동으로 등록
Stub runner boot
API호출
Consumer
https://github.com/Spring-cloud-samples/github-analytics-stub-runner-boot
49. Spring Camp 2018 49
방안2: Consumer와 Producer가 접근할 수 있는
공통의 프로젝트 구성
Contract Project
- Contract 파일 관리
- maven-assembly-plugin 빌드
Producer Project
- Pom.xml에 contractDependency 설정
<plugin>
<artifactId>Spring-cloud-contract-maven-plugin
<configuration>
<contractDependency>
<groupId>com.example</groupId>
<artifactId>beer-contracts</artifactId>
</contractDependency>
https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/master/
beer_contracts
60. Spring Camp 2018 60
Messaging 지원
Contract.make {
label 'accepted_verification'
input {
triggeredBy('clientIsOldEnough()')
}
outputMessage {
sentTo 'verifications'
body(
eligible: true
)
headers {
header("contentType",
applicationJsonUtf8())
}
}
Producer프로젝트:
- Spring-cloud-stream-test-support
Consumer프로젝트:
Spring-cloud-stream-test-support
Spring-cloud-starter-stream-rabbit
Spring-cloud-starter-contract-stub-runner
• Apache Camel
• Spring Integration
• Spring Cloud Stream
• Spring AMQP
필요한 dependency
61. Spring Camp 2018 61
Summary
Consumer Driven Contract패턴을 지원하는 Spring Cloud
Contract를 활용하여 마이크로서비스 API를 안전하게 개선
• Contract 스펙정의에 필요한 도구 제공
• Contract를 만족하는 Producer Stubs를 자동 생성
• Consumer는 Producer 서비스 테스트에 활용한 그 stub을 사용(일관성)
• Stub 패턴을 활용하여 의존성이 있는 service를 배포할 필요없고 빠른
feedback제공(failfast)
• 테스트 파이프라인에 쉽게 적용, 테스트 자동화 가능
• Dependency가 복잡한 마이크로 서비스 테스트에 효과적
• contract를 개선할 때 Producer /Consumer조율 시간과 비용을 줄일 수 있음
62. Spring Camp 2018 62
Learn More. Stay Connected.
▪ 데모샘플
https://github.com/myminseok/Spring-cloud-contract-beer-sample
▪ Read the docs
http://cloud.Spring.io/Spring-cloud-contract/
▪ Talk to us on Gitter
https://gitter.im/Spring-cloud/Spring-cloud-contract
Twitter: twitter.com/Springcentral
YouTube: Spring.io/video
LinkedIn: Spring.io/linkedin
Google Plus: Spring.io/gplus