5.1. κ°œμš”(Overview)

RSocket은 TCP, μ›Ήμ†ŒμΌ“ 그리고 기타 λ‹€λ₯Έ λ°”μ΄νŠΈ 슀트림 전솑을 ν†΅ν•œ λ‹€μ€‘ν™”λœ μ–‘λ°©ν–₯ 톡신을 μœ„ν•œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ ν”„λ‘œν† μ½œμ΄λ‹€. μ•„λž˜ 쀑 ν•˜λ‚˜λ₯Ό μƒν˜Έμž‘μš© λͺ¨λΈλ‘œ μ‚¬μš©ν•œλ‹€.

  • Request-Response - λ©”μ‹œμ§€ ν•˜λ‚˜λ₯Ό μ „μ†‘ν•˜κ³  ν•˜λ‚˜μ˜ 응닡을 λ°›λŠ”λ‹€.
  • Request-Stream - λ©”μ‹œμ§€ ν•˜λ‚˜λ₯Ό μ „μ†‘ν•˜κ³  ν•˜λ‚˜μ˜ 응닡을 슀트림으둜 λ°›λŠ”λ‹€.
  • Channel - μ–‘λ°©ν–₯으둜 λ©”μ‹œμ§€ μŠ€νŠΈλ¦Όμ„ μ „μ†‘ν•œλ‹€.
  • Fire-and-Forget - 단방ν–₯ λ©”μ‹œμ§€λ₯Ό μ „μ†‘ν•œλ‹€.

컀λ„₯μ…˜μ΄ λ§Ίμ–΄μ§€λ©΄, β€œν΄λΌμ΄μ–ΈνŠΈβ€μ™€ β€œμ„œλ²„β€ λΌλŠ” ꡬ뢄은 사라지고, μ–‘μͺ½μ΄ λŒ€μΉ­μ΄ λ˜μ–΄ 각각이 μœ„μ˜ μƒν˜Έμž‘μš© λͺ¨λΈ 쀑 ν•˜λ‚˜λ₯Ό μ‹œμž‘ν•  수 μžˆλ‹€. λ”°λΌμ„œ ν”„λ‘œν† μ½œμ—μ„œ μ°Έμ—¬ν•˜λŠ” μ–‘μͺ½μ„ β€œμš”μ²­μž(requester)”와 β€œμ‘λ‹΅μž(responder)” 라고 λΆ€λ₯΄λ©°, μƒν˜Έ μž‘μš© λͺ¨λΈμ€ β€œμš”μ²­ 슀트림(request streams)” λ˜λŠ” κ°„λ‹¨νžˆ β€œμš”μ²­(requests)” 이라고 λΆ€λ₯Έλ‹€.

λ‹€μŒμ€ RSocket ν”„λ‘œν† μ½œμ˜ μ£Όμš” κΈ°λŠ₯κ³Ό 이점이닀:

  • λ„€νŠΈμ›Œν¬ 경계λ₯Ό κ°€λ‘œμ§€λ₯΄λŠ” λ¦¬μ•‘ν‹°λΈŒ 슀트림 μ‹œλ§¨ν‹±μŠ€ - Request-Streamκ³Ό Channel 같은 슀트리밍 μš”μ²­μ„ μœ„ν•΄μ„œ, λ°±ν”„λ ˆμ…” μ‹ ν˜ΈλŠ” μš”μ²­μžμ™€ μ‘λ‹΅μž 사이λ₯Ό μ˜€κ°€κΈ° λ•Œλ¬Έμ— μš”μ²­μžκ°€ μ‘λ‹΅μžμ˜ 속도λ₯Ό μ œμ–΄ν•  수 μžˆλ‹€. λ”°λΌμ„œ λ„€νŠΈμ›Œν¬ κ³„μΈ΅μ˜ 혼작 μ œμ–΄μ— λŒ€ν•œ μ˜μ‘΄μ„ 쀄이고 λ„€νŠΈμ›Œν¬ 레벨 λ˜λŠ” μ–΄λ–€ λ ˆλ²¨μ—μ„œλ“ μ§€ λ²„νΌλ§μ˜ ν•„μš”μ„±μ„ 쀄인닀.
  • μš”μ²­ 쑰절(Request throttling) - ν•œ μͺ½μ—μ„œ LEASE ν”„λ ˆμž„μ„ μ†‘μ‹ ν•˜λ©΄ μ§€μ •λœ μ‹œκ°„λ™μ•ˆ λ‹€λ₯Έ μͺ½μ€ 보낼 수 μžˆλŠ” μš”μ²­μ΄ μ œν•œλœλ‹€. 이 κΈ°λŠ₯은 β€œLeasing” 이라고 λΆ€λ₯Έλ‹€. μ΄λŠ” 주기적으둜 κ°±μ‹ λœλ‹€.
  • μ„Έμ…˜ 재개(Session resumption) - 컀λ„₯μ…˜μ΄ λŠμ–΄μ§€λ”λΌλ„ 일뢀 μƒνƒœλ₯Ό μœ μ§€ν•΄μ€€λ‹€. μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ— λͺ…ν™•ν•˜κ²Œ μƒνƒœλ₯Ό 관리할 수 있으며, λ°±ν”„λ ˆμ…”μ™€ ν•¨κ»˜ μ‚¬μš©ν•˜λŠ” 경우 μƒμ‚°μž(producer)λ₯Ό μ€‘λ‹¨ν•˜κ³ , ν•„μš”ν•œ μƒνƒœμ˜ 양을 쀄일 수 μžˆλ‹€.
  • 큰 λ©”μ‹œμ§€μ˜ λ‹¨νŽΈν™”(fragmentation)와 재쑰립(re-assembly).
  • Keepalive (heartbeats).

RSocket은 μ—¬λŸ¬ μ–Έμ–΄λ‘œ κ΅¬ν˜„λ˜μ–΄ μžˆλ‹€. μžλ°” λΌμ΄λΈŒλŸ¬λ¦¬λŠ” 전솑을 μœ„ν•œ Project Reactor와 Reactor Nettyλ₯Ό 기반으둜 ν•œλ‹€. 즉, μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ λ¦¬μ•‘ν‹°λΈŒ 슀트림 Publisher의 μ‹ ν˜Έκ°€ Roskcet을 톡해 λ„€νŠΈμ›Œν¬λ₯Ό κ°€λ‘œμ§ˆλŸ¬ 투λͺ…ν•˜κ²Œ μ „νŒŒλœλ‹€λŠ” λœ»μ΄λ‹€.


5.1.1. ν”„λ‘œν† μ½œ(The Protocol)

RSocket의 μž₯점 쀑 ν•˜λ‚˜λŠ” λ„€νŠΈμ›Œν¬λ§μ—μ„œμ˜ λ™μž‘μ΄ 잘 μ •μ˜λ˜μ–΄ 있고 일뢀 ν”„λ‘œν† μ½œ ν™•μž₯(extensions)κ³Ό ν•¨κ»˜ 읽기 μ‰¬μš΄ μŠ€νŽ™(specification)μ΄λΌλŠ” 것이닀. λ”°λΌμ„œ μ–Έμ–΄ κ΅¬ν˜„ 및 μƒμœ„ 레벨 ν”„λ ˆμž„μ›Œν¬ API와 상관없이 μŠ€νŽ™μ‚¬ν•­μ„ μ½μ–΄λ³΄λŠ” 것이 μ’‹λ‹€. 이 μ„Ήμ…˜μ—μ„œλŠ” λ§₯락을 μ •λ¦½ν•˜κΈ° μœ„ν•œ κ°„κ²°ν•œ κ°œμš”λ₯Ό μ œκ³΅ν•œλ‹€.

Connecting

μ΄ˆκΈ°μ— ν΄λΌμ΄μ–ΈνŠΈλŠ” TCP λ˜λŠ” μ›Ήμ†ŒμΌ“κ³Ό 같은 μ €μˆ˜μ€€ 슀트리밍 전솑을 톡해 μ„œλ²„μ™€ μ—°κ²°ν•˜κ³ , 컀λ„₯μ…˜ νŒŒλΌλ―Έν„° 섀정을 μœ„ν•΄ SETUP ν”„λ ˆμž„μ„ μ„œλ²„λ‘œ μ „μ†‘ν•œλ‹€.

μ„œλ²„λŠ” SETUP ν”„λ ˆμž„μ„ κ±°λΆ€ν•  수 μžˆμ§€λ§Œ, 일반적으둜 이 ν”„λ ˆμž„μ„ 전솑(ν΄λΌμ΄μ–ΈνŠΈκ°€)ν•˜κ³  μˆ˜μ‹ (μ„œλ²„κ°€)ν–ˆλ‹€λ©΄, μ–‘μͺ½μ—μ„œ μš”μ²­μ„ μ‹œμž‘ν•  수 μžˆλ‹€. ν•˜μ§€λ§Œ SETUP ν”„λ ˆμž„μ΄ μš”μ²­ 수λ₯Ό μ œν•œν•˜κΈ° μœ„ν•΄ leasing μ‹œλ§¨ν‹±μŠ€λ₯Ό μ‚¬μš©ν–ˆλ‹€λ©΄, μš”μ²­μ„ ν•˜κΈ° μœ„ν•΄ μ–‘μͺ½ λͺ¨λ‘μ—μ„œλŠ” λ‹€λ₯Έ μͺ½μ΄ LEASE ν”„λ ˆμž„μ„ 보내 μš”μ²­μ„ μˆ˜λ½ν•  λ•ŒκΉŒμ§€ κΈ°λ‹€λ €μ•Ό ν•œλ‹€.

Making Requests

ν•œ 번 컀λ„₯μ…˜μ΄ λ§Ίμ–΄μ§€λ©΄, μ–‘μͺ½μ€ REQUEST_RESPONSE, REQUEST_STREAM, REQUEST_CHANNEL, REQUEST_FNF ν”„λ ˆμž„ 쀑 ν•˜λ‚˜λ₯Ό 톡해 μš”μ²­μ„ μ‹œμž‘ν•  수 μžˆλ‹€. 각 ν”„λ ˆμž„μ€ μš”μ²­μžλ‘œλΆ€ν„° μ‘λ‹΅μžμ—κ²Œ λ©”μ‹œμ§€ ν•˜λ‚˜λ₯Ό μ „μ†‘ν•œλ‹€.

μ‘λ‹΅μžλŠ” PAYLOAD ν”„λ ˆμž„μ„ 응닡 λ©”μ‹œμ§€μ™€ ν•¨κ»˜ 보내고, REQUEST_CHANNEL μš”μ²­μΈ 경우, μš”μ²­μžλŠ” PAYLOAD ν”„λ ˆμž„κ³Ό ν•¨κ»˜ μš”μ²­ λ©”μ‹œμ§€λ₯Ό 더 보낼 수 μžˆλ‹€.

μš”μ²­μ— Request-Streamκ³Ό Channelκ³Ό 같은 λ©”μ‹œμ§€ μŠ€νŠΈλ¦Όμ— ν¬ν•¨λœ 경우, μ‘λ‹΅μžλŠ” μš”μ²­μžκ°€ 보낸 μš”κ΅¬ μ‹ ν˜Έ(Demand signals)λ₯Ό μ€€μˆ˜ν•΄μ•Ό ν•œλ‹€. μš”κ΅¬μ‚¬ν•­μ€ λ©”μ‹œμ§€ 수둜 ν‘œν˜„λœλ‹€. 초기 μš”κ΅¬μ‚¬ν•­μ€ REQUEST_STREAM, REQUEST_CHANNEL ν”„λ ˆμž„μ— μ§€μ •ν•œλ‹€. 후속 μš”κ΅¬μ‚¬ν•­μ€ REQUEST_N ν”„λ ˆμž„μ„ ν†΅ν•œλ‹€.

각 츑은 METADATA_PUSH ν”„λ ˆμž„μ„ κ°œλ³„ μš”μ²­μ΄ μ•„λ‹Œ 전체 μ—°κ²°κ³Ό κ΄€λ ¨λœ 메타 데이터 μ•Œλ¦Όμ„ 전솑할 μˆ˜λ„ μžˆλ‹€.

Message Format

RSocket λ©”μ‹œμ§€μ—λŠ” 데이터와 메타 데이터가 ν¬ν•¨λœλ‹€. 메타 λ°μ΄ν„°λŠ” λΌμš°νŒ…, λ³΄μ•ˆ 토큰 등을 μ „μ†‘ν•˜λŠ”λ° μ‚¬μš©λ  수 μžˆλ‹€. 데이터와 메타 λ°μ΄ν„°λŠ” λ‹€λ₯Έ 포맷을 μ‚¬μš©ν•œλ‹€. 각각에 λŒ€ν•œ MIME μœ ν˜•μ€ SETUP ν”„λ ˆμž„μ— μ„ μ–Έλ˜μ–΄ μ§€μ •λœ 컀λ„₯μ…˜μ˜ λͺ¨λ“  μš”μ²­μ— μ μš©λœλ‹€.

λͺ¨λ“  λ©”μ‹œμ§€λŠ” 메타 데이터λ₯Ό κ°€μ§ˆ 수 μžˆμ§€λ§Œ 일반적으둜 λΌμš°νŒ…κ³Ό 같은 메타 λ°μ΄ν„°λŠ” 보톡 μš”μ²­ λ‹Ή ν•˜λ‚˜λ§Œ ν•„μš”ν•˜λ―€λ‘œ, μš”μ²­μ˜ 첫 번째 λ©”μ‹œμ§€μ—λ§Œ ν¬ν•¨μ‹œν‚¨λ‹€. 예λ₯Ό λ“€μ–΄, REQUEST_RESPONSE, REQUEST_STREAM, REQUEST_CHANNEL, REQUEST_FNF.

ν”„λ‘œν† μ½œ ν™•μž₯은 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ μ‚¬μš©ν•˜κΈ° μœ„ν•œ 일반적인 곡톡 메타 데이터 포맷을 μ •μ˜ν•œλ‹€:

  • Composite Metadata - λ‹€μˆ˜μ˜ λ…λ¦½μ μœΌλ‘œ ν¬λ§·νŒ…λœ 메타데이터 μ—”νŠΈλ¦¬
  • Routing - μš”μ²­μ— λŒ€ν•œ λΌμš°νŒ…


5.1.2. μžλ°” κ΅¬ν˜„(Java Implementation)

RSocket μžλ°” κ΅¬ν˜„μ²΄ λŠ”Project Reactorλ₯Ό 기반으둜 ν•œλ‹€. TCP와 μ›Ήμ†ŒμΌ“ 전솑은 Reactor Nettyλ₯Ό 기반으둜 ν•œλ‹€. λ¦¬μ•‘ν‹°λΈŒ 슀트림 λΌμ΄λΈŒλŸ¬λ¦¬λ‘œμ„œ, λ¦¬μ•‘ν„°λŠ” ν”„λ‘œν† μ½œ κ΅¬ν˜„ κ΅¬ν˜„μ„ λ‹¨μˆœν•˜κ²Œ ν•œλ‹€. μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œλŠ” 선언적인(declarative) μ—°μ‚°μžμ™€ 투λͺ…ν•œ λ°±ν”„λ ˆμ…” 지원 κΈ°λŠ₯을 κ°–μΆ˜ Flux와 Monoλ₯Ό μ‚¬μš©ν•˜λŠ” 것이 μžμ—°μŠ€λŸ½λ‹€.

RSocket μžλ°” APIλŠ” μ˜λ„μ μœΌλ‘œ μ΅œμ†Œμ μ΄κ³  기본적이닀. APIλŠ” ν”„λ‘œν† μ½œ κΈ°λŠ₯μ—λ§Œ 쀑점을 두고 μ• ν”Œλ¦¬μΌ€μ΄μ…˜ ν”„λ‘œκ·Έλž˜λ° λͺ¨λΈ(예λ₯Ό λ“€μ–΄, RPC codegen, λ‹€λ₯Έ μ½”λ“œ λ“±)은 더 높은 μˆ˜μ€€μ˜ λ…λ¦½λœ κ΄€μ‹¬μ‚¬λ§Œ 보면 λœλ‹€.

κ΅¬ν˜„μ²΄μΈ io.rsocket.RSocket의 μ£Όμš” 역할은 λ„€ κ°€μ§€ μƒν˜Έλ™μž‘ νƒ€μž…μ„ λ§Œλ“œλŠ” 것이닀. 단일 λ©”μ‹œμ§€λŠ” Mono, λ©”μ‹œμ§€ μŠ€νŠΈλ¦Όμ€ Flux, λ°”μ΄νŠΈ λ²„νΌλ‘œ 데이터와 메타 데이터에 μ ‘κ·Όν•˜λŠ” μ‹€μ œ λ©”μ‹œμ§€λŠ” io.rsocket.Payloadκ°€ μžˆλ‹€. RSocket의 역할은 λŒ€μΉ­μ μœΌλ‘œ μ‚¬μš©λœλ‹€. μš”μ²­μ— λŒ€ν•΄μ„œλŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ— μš”μ²­μ„ μœ„ν•œ RSocket이 μ£Όμ–΄μ§€κ³ , 응닡에 λŒ€ν•΄μ„œλŠ” RSocket을 κ΅¬ν˜„ν•˜μ—¬ μš”μ²­μ„ ν•Έλ“€λ§ν•œλ‹€.

이것듀은 μ™„μ „ν•œ μ†Œκ°œκ°€ μ•„λ‹ˆλ‹€. λŒ€λΆ€λΆ„ μŠ€ν”„λ§ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ APIλ₯Ό 직접 μ‚¬μš©ν•  ν•„μš”κ°€ μ—†λ‹€. κ·ΈλŸ¬λ‚˜ μŠ€ν”„λ§κ³Ό λ…λ¦½μ μœΌλ‘œ RSocket을 λ³΄κ±°λ‚˜ ν…ŒμŠ€νŠΈν•˜λŠ” 것이 μ€‘μš”ν•  수 μžˆλ‹€. RSocket μžλ°” μ €μž₯μ†Œμ—λŠ” API와 ν”„λ‘œν† μ½œ κΈ°λŠ₯을 λ³΄μ—¬μ£ΌλŠ” λ§Žμ€ μƒ˜ν”Œ 앱이 ν¬ν•¨λ˜μ–΄ μžˆλ‹€.


5.1.3. μŠ€ν”„λ§ 지원(Spring Support)

spring-messaging λͺ¨λ“ˆμ€ λ‹€μŒμ„ ν¬ν•¨ν•œλ‹€:

  • RSocketRequester - io.rsocket.RSocketκ³Ό 데이터, 메타 데이터와 인코딩/디코딩을 톡해 μš”μ²­μ„ μƒμ„±ν•˜λŠ” μœ μ—°ν•œ API
  • Annotated Responders - 응닡을 μœ„ν•œ @RequestMapping μ–΄λ…Έν…Œμ΄μ…˜μ΄ 적용된 ν•Έλ“€λŸ¬ λ©”μ„œλ“œ

spring-web λͺ¨λ“ˆμ—λŠ” RSocket μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ ν•„μš”ν•  μˆ˜λ„ μžˆλŠ” Jackson, CBOR/JSON, Protobuf와 같은 Encoder와 Decoder κ΅¬ν˜„μ²΄κ°€ ν¬ν•¨λ˜μ–΄ μžˆλ‹€. λ˜ν•œ 효과적으둜 λΌμš°νŒ… 맀칭을 ν•˜κΈ° μœ„ν•œ PathPatternParser도 ν¬ν•¨λ˜μ–΄ μžˆλ‹€.

μŠ€ν”„λ§λΆ€νŠΈ 2.2λŠ” TCPλ‚˜ μ›Ήμ†ŒμΌ“μ„ μ‚¬μš©ν•˜μ—¬ RSocket μ„œλ²„λ₯Ό μ§€μ›ν•˜κ³ , μ›Ήν”ŒλŸ­μŠ€ μ„œλ²„μ—μ„œ μ›Ήμ†ŒμΌ“μ„ ν†΅ν•œ RSocket을 λ…ΈμΆœν•˜λŠ” μ˜΅μ…˜μ„ ν¬ν•¨ν•œλ‹€. λ˜ν•œ RSocketRequester.Builder와 RSocketStrategies에 λŒ€ν•œ ν΄λΌμ΄μ–ΈνŠΈ 지원 및 μžλ™ 섀정도 μžˆλ‹€. μžμ„Έν•œ λ‚΄μš©μ€ μŠ€ν”„λ§ λΆ€νŠΈ 레퍼런슀의 RSocket μ„Ήμ…˜μ„ μ°Έμ‘°ν•˜λΌ.

μŠ€ν”„λ§ μ‹œνλ¦¬ν‹°(Spring Security) 5.2λŠ” RSocket을 μ§€μ›ν•œλ‹€.

μŠ€ν”„λ§ Integration 5.2λŠ” μΈλ°”μš΄λ“œμ™€ μ•„μ›ƒλ°”μš΄λ“œ 게이트 웨이λ₯Ό μ œκ³΅ν•˜μ—¬ RSocket ν΄λΌμ΄μ–ΈνŠΈμ™€ μ„œλ²„μ™€ μƒν˜Έμž‘μš©ν•œλ‹€. μžμ„Έν•œ λ‚΄μš©μ€ Spring Integration Reference Manual을 μ°Έμ‘°ν•˜λΌ.

μŠ€ν”„λ§ ν΄λΌμš°λ“œ κ²Œμ΄νŠΈμ›¨μ΄λŠ”(Spring Cloud Gateway)λŠ” RSocket 컀λ„₯μ…˜μ„ μ§€μ›ν•œλ‹€.


λͺ©μ°¨ κ°€μ΄λ“œ