Golang 프로덕션 웹 애플리케이션 구성


120

프로덕션에서 Go 백엔드를 실행하는 경우 :

Go 웹 애플리케이션을 실행하기위한 스택 / 구성은 무엇입니까?

서버를 계속 실행하기 위해 표준 라이브러리 net / http 패키지를 사용하는 사람 외에는이 주제에 대해 많이 보지 못했습니다. Nginx를 사용하여 Go 서버에 요청을 전달하는 방법을 읽었습니다.-Nginx with Go

이것은 나에게 약간 깨지기 쉬운 것 같습니다. 예를 들어, 컴퓨터가 다시 시작되면 서버가 자동으로 다시 시작되지 않습니다 (추가 구성 스크립트없이).

더 견고한 프로덕션 설정이 있습니까?

내 의도에 대한 제쳐두고-다음 프로젝트를 위해 Go로 구동되는 REST 백엔드 서버를 계획하고 있으며 너무 많은 투자를하기 전에 Go가 프로젝트를 라이브로 시작할 수 있는지 확인하고 싶습니다.


3
"컴퓨터가 다시 시작되면 서버가 자동으로 다시 시작되지 않습니다 (추가 구성 스크립트없이)." 나는 이것이 할 수 있다고 생각하지 않는다. 이상적으로는 서비스에 대한 init / systemd / upstart 스크립트를 작성했습니다. 이것은 unix 데몬을 제어하는 ​​데 권장되는 방법입니다.
Intermernet

맞아요. 설치시 자동으로 이러한 기능을 설정하는 apache와 같은 서버와는 대조적으로 그것을 의미한다고 생각합니다.
Chaseph 2013

답변:


134

Go 프로그램은 포트 80에서 수신 대기하고 HTTP 요청을 직접 처리 할 수 ​​있습니다. 대신 Go 프로그램 앞에 역방향 프록시를 사용하여 포트 80에서 수신하고 4000과 같은 포트에서 프로그램에 연결할 수 있습니다. 후자를 수행하는 데는 여러 가지 이유가 있습니다. Go 프로그램을 루트로, 동일한 호스트에서 다른 웹 사이트 / 서비스 제공, SSL 종료, 부하 분산, 로깅 등

나는 앞에서 HAProxy 를 사용 합니다. 모든 역방향 프록시가 작동 할 수 있습니다. Nginx는 또한 훌륭한 옵션입니다 (HAProxy보다 훨씬 인기 있고 더 많은 작업을 수행 할 수 있음).

HAProxy는 문서 ( HTML 버전 ) 를 읽으면 구성하기가 매우 쉽습니다 . haproxy.cfg시작 지점이 필요한 경우 내 Go 프로젝트 중 하나에 대한 전체 파일이 다음과 같습니다.

global
        log     127.0.0.1       local0
        maxconn 10000
        user    haproxy
        group   haproxy
        daemon

defaults
        log     global
        mode    http
        option  httplog
        option  dontlognull
        retries 3
        timeout connect 5000
        timeout client  50000
        timeout server  50000

frontend http
        bind :80
        acl  is_stats  hdr(host)       -i      hastats.myapp.com
        use_backend    stats   if      is_stats
        default_backend        myapp
        capture        request header Host     len     20
        capture        request header Referer  len     50

backend myapp
        server  main    127.0.0.1:4000

backend stats
       mode     http
       stats    enable
       stats    scope   http
       stats    scope   myapp
       stats    realm   Haproxy\ Statistics
       stats    uri     /
       stats    auth    username:password

Nginx는 훨씬 더 쉽습니다.

서비스 제어와 관련하여 Go 프로그램을 시스템 서비스로 실행합니다. 모두가 그렇게한다고 생각합니다. 내 서버는 Ubuntu를 실행하므로 Upstart를 사용합니다. /etc/init/myapp.confUpstart가 내 프로그램을 제어하기 위해 이것을 넣었습니다 .

start on runlevel [2345]
stop on runlevel [!2345]

chdir /home/myapp/myapp
setgid myapp
setuid myapp
exec ./myapp start 1>>_logs/stdout.log 2>>_logs/stderr.log

또 다른 측면은 배포입니다. 한 가지 옵션은 프로그램의 바이너리 파일과 필요한 자산을 전송하여 배포하는 것입니다. 이것은 꽤 훌륭한 솔루션 IMO입니다. 다른 옵션 인 서버에서 컴파일을 사용합니다. (소위 "지속적인 통합 / 배포"시스템을 설정할 때 바이너리 파일을 사용한 배포로 전환하겠습니다.)

원격 Git 저장소에서 내 프로젝트의 코드를 가져 와서 Go로 빌드하고 바이너리 및 기타 자산을에 복사 ~/myapp/하고 서비스를 다시 시작 하는 작은 셸 스크립트가 서버 에 있습니다.

전반적으로 모든 것이 다른 서버 설정과 크게 다르지 않습니다. 코드를 실행하고 HTTP 요청을 처리 할 방법이 있어야합니다. 실제로 Go는 이러한 작업에 대해 매우 안정적인 것으로 입증되었습니다.


9
좋은 대답입니다! 권장되는 기본 설정에 필요한 모든 것의 좋은 예입니다.
Intermernet 2013

로그 회전에 대해 무엇을합니까? 이것이 내가 supervisord를 사용하는 유일한 이유이지만 로깅이 너무 많이 진행되면 어려움을 겪습니다.
fiorix

@fiorix, 로그 회전에 대한 다른 질문을 열 수 있다고 확신하지만 여전히 유닉스를 사용하고 있고 표준 도구를 사용하려면 logrotate : linuxcommand.org/man_pages/logrotate8.html을 확인하십시오 . 이것은 잘 알려진 많은 서비스 (apache, yum 등)에서 사용되며 구성하기가 매우 쉽습니다.
Doody P 2013

Go에서 자신 만의 역방향 프록시를 만드는 것이 얼마나 쉬울까요? 이것이 nginx 또는 haproxy를 사용하는 것보다 훨씬 더 나쁜 생각일까요? Go는 훌륭한 HTTP / HTTPS / HTTP / 2 지원을 제공합니다.
thomasrutter

58

nginx :

  • 내 Go 애플리케이션에 대한 역방향 HTTP 프록시
  • 정적 파일 처리
  • SSL 종료
  • HTTP 헤더 (Cache-Control 등)
  • 액세스 로그 (따라서 시스템 로그 회전 활용)
  • 재 작성 (www로 표시, http : //에서 https : //로 표시 등)

nginx를 사용하면이 작업을 매우 쉽게 수행 할 수 있습니다. 덕분에 Go에서 직접 서비스를 제공 할 수 있지만 net/http"바퀴를 재창조"하는 작업이 많이 있으며 전역 HTTP 헤더와 같은 항목에는 피할 수있는 몇 가지 상용구가 포함됩니다.

내 Go 바이너리 관리 감독 . Ubuntu의 Upstart (Mostafa에서 언급했듯이)도 좋지만 상대적으로 배포에 구애받지 않고 잘 문서화되어 있으므로 supervisord를 좋아합니다.

나를 위해 감독 됨 :

  • 필요에 따라 내 Go 바이너리를 실행합니다.
  • 충돌 후 가져옵니다.
  • 단일 구성의 일부로 내 환경 변수 (세션 인증 키 등)를 보유합니다.
  • 내 DB 실행 (내 Go 바이너리가 그것없이 실행되지 않도록하기 위해)

8

데몬으로 실행되는 간단한 go 앱을 원하는 경우 Upstart 대신 systemd (많은 Linux 배포판에서 지원됨)를 사용하십시오.

다음 위치에서 서비스 파일을 만듭니다.

touch /etc/systemd/system/my-go-daemon.service

시작하다

[Unit]
Description=My Go App

[Service]
Type=simple
WorkingDirectory=/my/go/app/directory
ExecStart=/usr/lib/go run main.go 

[Install]
WantedBy=multi-user.target

그런 다음 서비스를 활성화하고 시작하십시오.

systemctl enable my-go-daemon
systemctl start my-go-daemon
systemctl status my-go-daemon

systemd에는 쉬운 문제 해결을 위해 로그를 추적 할 수있는 별도의 저널링 시스템이 있습니다.


5

바이너리를 소켓에 인터넷 도메인 권한이있는 포트 (1024 미만의 포트 번호)에 바인딩 할 수 있습니다. setcap

setcap 'cap_net_bind_service=+ep' /path/to/binary

  1. 이 명령은 에스컬레이션해야합니다. sudo필요에 따라
  2. 프로그램의 모든 새 버전은 다음에 의해 재 인증되어야하는 새 바이너리를 생성합니다. setcap

setcap 선적 서류 비치

cap_net_bind_service 선적 서류 비치

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.