하나의 프로세스에서 여러 서비스를 우아하게 관리
배경
API gateway
와 RPC service
를 같은 프로세스에 넣을 수 있는지, 어떻게 하면 되는지 자주 질문을 받았습니다. 외부 서비스와 메시지 큐를 같은 프로세스에 넣는 개발자도 있습니다. 이러한 문제를 보다 우아하게 해결하는 방법을 살펴보겠습니다.문제
두 가지 모의 서비스를 예로 들어 보겠습니다. 하나의 프로세스에서 두 개의 서로 다른 포트에서 시작해야 하는 두 개의 서비스가 있습니다. 코드는 다음과 같습니다.
package main
import (
"fmt"
"net/http"
)
func morning(w http.ResponseWriter, req *http.Request) {
fmt.Fprintln(w, "morning!")
}
func evening(w http.ResponseWriter, req *http.Request) {
fmt.Fprintln(w, "evening!")
}
type Morning struct{}
func (m Morning) Start() {
http.HandleFunc("/morning", morning)
http.ListenAndServe("localhost:8080", nil)
}
func (m Morning) Stop() {
fmt.Println("Stop morning service...")
}
type Evening struct{}
func (e Evening) Start() {
http.HandleFunc("/evening", evening)
http.ListenAndServe("localhost:8081", nil)
}
func (e Evening) Stop() {
fmt.Println("Stop evening service...")
}
func main() {
// todo: start both services here
}
코드는
morning
서비스에 대한 요청이 있고 서비스가 morning!
를 반환하고 evening
서비스에 대한 요청이 있고 서비스가 evening
를 반환할 만큼 간단합니다. 구현해보시죠~첫 시도
main
에서 두 서비스를 모두 시작할 수 있습니까? 해보자.func main() {
var morning Morning
morning.Start()
defer morning.Stop()
var evening Evening
Start()
Stop()
}
시작 후
curl
로 확인합시다.$ curl -i http://localhost:8080/morning
HTTP/1.1 200 OK
Date: Mon, 18 Apr 2022 02:10:34 GMT
Content-Length: 9
Content-Type: text/plain; charset=utf-8
morning!
$ curl -i http://localhost:8081/evening
curl: (7) Failed to connect to localhost port 8081 after 4 ms: Connection refused
morning
만 성공하고 evening
는 요청할 수 없는 이유는 무엇입니까?main
에 인쇄 문을 추가하고 시도해 봅시다.func main() {
fmt.Println("Start morning service...")
var morning Morning
morning.Start()
defer morning.Stop()
fmt.Println("Start evening service...")
var evening Evening
Start()
Stop() defer evening.
}
다시 실행하고 확인하십시오.
$ go run main.go
Start morning service...
Start morning service...
만 인쇄하므로 evening
서비스가 전혀 시작되지 않습니다. 그 이유는 morning.Start()
가 현재의 goroutine
를 차단하여 후속 코드가 실행되지 않기 때문입니다.두 번째 시도
이것은
WaitGroup
가 유용한 곳입니다. 이름에서 알 수 있듯이 WaitGroup
는 작업 그룹을 wait
수행하는 데 사용되며 대기 중인 고루틴이 계속될 수 있도록 작업이 완료될 때까지 기다립니다. 시도해 봅시다.func main() {
var wg sync.WaitGroup
wg.Add(2)
go func() {
defer wg.Done()
fmt.Println("Start morning service...")
var morning Morning
defer morning.Stop()
morning.Start()
Start() }()
go func() {
defer wg.Done()
fmt.Println("Start evening service...")
var evening Evening
defer evening.Stop()
evening.Start()
Start() }()
wg.Wait()
}
시도 해봐.
$ go run main.go
Start evening service...
Start morning service...
좋아요, 두 서비스가 모두 작동 중이므로
curl
로 확인하겠습니다.$ curl -i http://localhost:8080/morning
HTTP/1.1 200 OK
Date: Mon, 18 Apr 2022 02:28:33 GMT
Content-Length: 9
Content-Type: text/plain; charset=utf-8
morning!
$ curl -i http://localhost:8081/evening
HTTP/1.1 200 OK
Date: Mon, 18 Apr 2022 02:28:36 GMT
Content-Length: 9
Content-Type: text/plain; charset=utf-8
evening!
작동하며
WaitGroup
를 사용한 프로세스가wait
.go-zero
어떻게 처리하는지 보자~세 번째 시도
go-zero
에서는 여러 서비스의 시작과 중지를 쉽게 관리할 수 있도록 ServiceGroup
를 제공합니다. 시나리오에서 사용하여 어떻게 수행되는지 봅시다.import "github.com/zeromicro/go-zero/core/service"
// more code here
func main() {
group := service.NewServiceGroup()
defer group.Stop()
group.Add(Morning{})
group.Add(Evening{})
group.Start()
}
보시다시피 코드는 훨씬 더 읽기 쉽고
WaitGroup
에 추가할 수를 실수로 잘못 계산할 수 없습니다. 그리고 ServiceGroup
는 Start
가 나중에 Stop
먼저 defer
와 동일한 서비스를 확인하고 리소스를 더 쉽게 정리할 수 있도록 합니다.ServiceGroup
는 각 서비스의 Start/Stop
를 관리할 뿐만 아니라 graceful shutdown
신호를 수신하면 각 서비스의 Stop
메소드를 능동적으로 호출하는 SIGTERM
를 제공하고 HTTP
서비스에 대해서는 server.Shutdown
서비스의 경우 HTTP
로, server.GracefulStop()
서비스의 경우 gRPC
로 정상적으로 종료할 수 있습니다.요약
ServiceGroup
의 구현은 82줄의 코드로 충분히 간단합니다.$ cloc core/service/servicegroup.go
------------------------------------------------------------------
Language files blank comment code
------------------------------------------------------------------
Go 1 22 14 82
------------------------------------------------------------------
코드는 짧고 간결하며 모든 서비스(Restful, RPC, MQ)는 기본적으로
ServiceGroup
의 go-zero
에 의해 관리되므로 매우 편리하고 읽을 가치가 있습니다.프로젝트 주소
https://github.com/zeromicro/go-zero
go-zero
를 사용하고 별표를 표시하여 지원해 주셔서 감사합니다!
Reference
이 문제에 관하여(하나의 프로세스에서 여러 서비스를 우아하게 관리), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/kevwan/elegantly-manage-multiple-services-in-one-process-bc2텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)