[nats] Request-Reply

[์›๋ณธ ๋งํฌ]

Request-Reply ํŒจํ„ด์€ ๊ธฐ์กด์˜ ๋ฉ”๋ชจ๋ฆฌ ํ ์‹œ์Šคํ…œ๊ณผ ์ฐจ๋ณ„ํ™”๋˜๋Š” nats์˜ pub/sub ํ™•์žฅ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜๋‹ค.

์ด๋ฅผ ์ด์šฉํ•˜๋ฉด ์›น์„œ๋ฒ„์ฒ˜๋Ÿผ ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ  ์‘๋‹ต์„ ๋ฐ›์•„์˜ค๋Š” ์‹์˜ ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.
๋™๊ธฐ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜๋„, ๋น„๋™๊ธฐ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

๋จผ์ € CLI๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์‘๋‹ต ํ˜•ํƒœ๋ฅผ ๋งŒ๋“ค์–ด๋ณด๊ฒ ๋‹ค.
์•„๋ž˜๋Š” help.please๋ผ๋Š” ์š”์ฒญ์ด ๋‚ ๋ผ์˜ฌ ๊ฒฝ์šฐ 'OK, I CAN HELP!!!'๋ฅผ ์‘๋‹ต์œผ๋กœ ๋ฐ˜ํ™˜ํ•ด์ฃผ๋Š” ์‘๋‹ต์ด๋‹ค.

nats reply --server nats://localhost:4222 help.please 'OK, I CAN HELP!'

์ด๋Ÿฌ๋ฉด ์ผ๋‹จ ๋Œ€๊ธฐ์ค‘์ด ๋  ๊ฒƒ์ด๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์š”์ฒญ์„ ๋‚ ๋ฆฐ๋‹ค.

nats request --server nats://localhost:4222 help.please 'I need help!'

๊ทธ๋Ÿฌ๋ฉด reply์—์„œ ๋ณด๋‚ด์ค€ ๋ฉ”์„ธ์ง€๊ฐ€ request ์ธก์—์„œ ๋ณด์ผ ๊ฒƒ์ด๊ณ 


request์—์„œ ๋ณด๋‚ด์ค€ ๋ฉ”์„ธ์ง€๋„ reply ์ธก์—์„œ ๋ณด์ผ ๊ฒƒ์ด๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์ด๊ฑด pub/sub๊ณผ ๋‹ค๋ฅด๊ฒŒ, reply๊ฐ€ ์—ฌ๋Ÿฌ๊ฐœ๋ผ๋„ ํ•˜๋‚˜๋งŒ ์„ ์ •๋ผ์„œ ์ฒ˜๋ฆฌ๋œ๋‹ค.
์•„๋ž˜๋Š” ํ•œ ์ฃผ์ œ์— ๋Œ€ํ•ด 2๊ฐ€์ง€ "reply"๋ฅผ ์ •์˜ํ•˜๊ณ  request๋ฅผ ๋‚ ๋ ธ์„ ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ๋™์ž‘์ด๋‹ค.

๊ทธ๋ƒฅ ๋žœ๋ค์œผ๋กœ ํ•˜๋‚˜์”ฉ ํ˜ธ์ถœํ•ด์„œ ๋ฐ›์•„์˜จ๋‹ค.

์ด๊ฑธ ์ด์šฉํ•˜๋ฉด HTTP ์„œ๋ฒ„์™€ ๋น„์Šค๋ฌด๋ฆฌํ•œ ๊ธฐ๋Šฅ๋“ค์„ ๊ตฌํ˜„ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

์•„๋ž˜๋Š” ๋ง์…ˆ์„ ์ˆ˜ํ–‰ํ•ด์ฃผ๋Š” "add"๋ผ๋Š” ์ฃผ์ œ๋ฅผ ๋งŒ๋“ค๊ณ  ์‚ฌ์šฉํ•˜๋Š” ๊ฐ„๋‹จํ•œ ์˜ˆ์ œ๋‹ค.
์–ธ์–ด๋Š” Go๋‹ค. ํŠน๋ณ„ํ•œ ์ด์œ ๋Š” ์—†๋‹ค.

reply ํ”„๋กœ์„ธ์Šค๋Š” ์š”์ฒญ์ด ์™”์„ ๊ฒฝ์šฐ์˜ ์‘๋‹ต์„ ์ฒ˜๋ฆฌํ•œ๋‹ค.
๋ฉ”์„ธ์ง€์—์„œ ์ธ์ž ๋ชฉ๋ก์„ ์‰ผํ‘œ ๊ตฌ๋ถ„์œผ๋กœ ๋ฐ›๊ณ , ๋”ํ•ด์„œ ๊ฒฐ๊ณผ๋ฅผ ์•Œ๋ ค์ค€๋‹ค.

package main

import (
	"fmt"
	"strconv"
	"strings"

	"github.com/nats-io/nats.go"
)

func main() {
	client, _ := nats.Connect(nats.DefaultURL)

	// Reply
	client.Subscribe("add", func(m *nats.Msg) {
		input := string(m.Data)
		operands := strings.Split(input, ",")
		lhs, lhsErr := strconv.ParseInt(operands[0], 10, 64)
		rhs, rhsErr := strconv.ParseInt(operands[1], 10, 64)

		if lhsErr != nil || rhsErr != nil {
			client.Publish(m.Reply, []byte("I can't help!"))
			return
		}

		sum := lhs + rhs
		pubMessage := fmt.Sprintf("Sum is %d", sum)
		pubError := client.Publish(m.Reply, []byte(pubMessage))

		if pubError != nil {
			fmt.Println(pubError)
		}
	})

	fmt.Println("replier is running")

	for {
	}
}

request ํ”„๋กœ์„ธ์Šค๋Š” ์ด์— ๋น„ํ•ด ๊ฐ„๋‹จํ•˜๋‹ค.
์ฃผ์ œ๋ช…๊ณผ ๋ฉ”์„ธ์ง€, ํƒ€์ž„์•„์›ƒ์„ ์ „๋‹ฌํ•œ๋‹ค.
ํƒ€์ž„์•„์›ƒ ์‹œ๊ฐ„๋™์•ˆ์€ reply๊ฐ€ ๊ตฌ์„ฑ๋˜์–ด์žˆ์ง€ ์•Š๊ฑฐ๋‚˜ ๋‹ต์ด ์˜ค์ง€ ์•Š๋”๋ผ๋„ ๊ธฐ๋‹ค๋ฆฐ๋‹ค.

package main

import (
	"fmt"
	"time"

	"github.com/nats-io/nats.go"
)

func main() {
	client, _ := nats.Connect(nats.DefaultURL)

	message, err := client.Request("add", []byte("10,20"), 100*time.Millisecond)

	fmt.Println("replier received a reply")
	fmt.Println(string(message.Data))

	if err != nil {
		fmt.Println(err)
		panic(err)
	}
}

reply๋ฅผ ์‹คํ–‰ํ•ด๋‘๊ณ 

๋ฉ”์„ธ์ง€๊ฐ€ ์ด๋ ‡๊ฒŒ ๋‚ ๋ผ์˜ค๋ฉด ์ž˜ ๋œ ๊ฒƒ์ด๋‹ค.



์ฐธ์กฐ
์š”์ฒญ-ํšŒ์‹  - NATS ๋ฌธ์„œ