Запуск и развертывание с помощью Go

Go
Запуск и развертывание с помощью Go

Введение

В конце концов, тесты и документация готовы, осталось только развертывание.

Может использоваться непосредственно во время обычного тестированияgo runработает, но когда дело доходит до развертывания для скомпилированных языков, определенно хочу использоватьgo buildГенерировать бинарные файлы.

построить в докере

Поскольку вся система основана на docker-compose, вам нужно написать Dockerfile, Соберите весь проект в виде образа в докере.

Таким образом, его можно запустить прямо в докере.Процесс генерации бинарных файлов для каждой локальной сборки, Это превращается в пересборку образа докера.

Dockerfile выглядит следующим образом:

FROM golang:1.13 as build

ENV GOPROXY="https://goproxy.io"
# https://stackoverflow.com/questions/36279253/go-compiled-binary-wont-run-in-an-alpine-docker-container-on-ubuntu-host
# build for static link
ENV CGO_ENABLED=0
WORKDIR /app
COPY . /app
RUN make build

# production stage
FROM alpine as production

WORKDIR /app
COPY ./conf/ /app/conf
COPY --from=build /app/web /app
EXPOSE 8081
ENTRYPOINT ["/app/web"]
CMD [ "-c", "./conf/config_docker.yaml" ]

При построении используется двухэтапная сборка: сначала бинарный файл собирается в обычном образе golang. Затем скопируйте его в образ alpine, чтобы уменьшить размер образа после завершения сборки.

Переменные среды должны быть установлены при построенииCGO_ENABLED=0, чтобы отключить использование динамической компоновки CGO, Пожалуйста, обратитесь кstackoverflow.

Интегрирован в docker-compose

Когда Dockerfile написан, вы можете напрямую собрать образ и запустить тест, чтобы увидеть, работает ли он.

docker build -t go_web .
docker run -p 8081:8081 go_web

Когда все хорошо, его можно интегрировать вdocker-compose.yaml, названный службой.

app:
  build:
    context: .
  depends_on:
    - mysql

Есть зависимость, ведь mysql должен быть запущен первым.Что касается того, почему порт не выставлен, это потому, что используется обратный прокси nginx.

Использовать обратный прокси nginx

docker-compose может вручную масштабировать СЛУЖБУ до нескольких экземпляров.

Usage: up [options] [--scale SERVICE=NUM...] [SERVICE...]

Хотя масштабирование docker-compose больше не популярно после выхода kubernetes, давайте его реализуем. Здесь мы фокусируемся только на расширении приложения, то есть текущего проекта, независимо от других зависимостей, таких как базы данных.

Изменить API

Сначала внесите изменения/check/healthAPI возвращает имя хоста, чтобы можно было наблюдать эффект.

var hostname string

func init() {
	name, err := os.Hostname()
	if err != nil {
		name = "unknow"
	}
	hostname = name
}

// HealthCheck 返回心跳响应
func HealthCheck(ctx *gin.Context) {
	message := fmt.Sprintf("OK from %s", hostname)
	ctx.String(http.StatusOK, message)
}

После завершения модификации обратите внимание на перестроение образа, чтобы модификация вступила в силу.

создать службу nginx

Настройте nginx в docker-compose.

nginx:
  image: nginx:stable-alpine
  ports:
    - 80:80
  depends_on:
    - app
  volumes:
    - ./conf/nginx_web.conf:/etc/nginx/conf.d/default.conf
  command: nginx -g 'daemon off;'

Затем напишите файл конфигурации nginx:

upstream web {
  server app:8081;
}

server {
  listen 80;
  server_name localhost;

  location / {
    # https://stackoverflow.com/questions/42720618/docker-nginx-stopped-emerg-11-host-not-found-in-upstream
    resolver 127.0.0.1;

    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded-Host $http_host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Real-IP $remote_addr;

    client_max_body_size 5m;

    proxy_pass http://web;
  }

}

Здесь настроен обратный прокси для перенаправления всех запросовapp:8081, это порт, предоставляемый сервером приложений,

Обратите внимание, что наборresolver 127.0.0.1;, иначе nginx не сможет подключиться в началеapp:8081разбился сразу.

Так почему бы не запустить NGINX, когда будете готовы?depends_onГарантируется только то, что порядок запуска гарантирован, а не подтверждается, что он готов.

обновление базы данных

То же самое верно и для базы данных, нам нужно установить определенный механизм повторных попыток, чтобы убедиться, что база данных была запущена.

func openDB(username, password, addr, name string) *gorm.DB {
	config := fmt.Sprintf(
		"%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=%t&loc=%s&timeout=10s",
		username,
		password,
		addr,
		name,
		true,
		// "Asia%2FShanghai",  // 必须是 url.QueryEscape 的
		"Local",
	)
	var db *gorm.DB
	var err error
	for i := 0; i < 10; i++ {
		db, err = gorm.Open("mysql", config)
		if err == nil {
			break
		}
		time.Sleep(time.Second * 3)
	}
	if db == nil {
		logrus.Fatalf("数据库连接失败. 数据库名字: %s. 错误信息: %s", name, err)
	}
	logrus.Infof("数据库连接成功, 数据库名字: %s", name)

	setupDB(db)
	return db
}

Кроме того, при запуске базы данных задайте сценарий инициализации, чтобы вам не приходилось вручную создавать базу данных.

mysql:
  image: mysql:8
  command: --default-authentication-plugin=mysql_native_password --init-file /data/application/init.sql
  environment:
    MYSQL_ROOT_PASSWORD: "1234"
  ports:
    - 3306:3306
  volumes:
    - ./script/db.sql:/data/application/init.sql

Сценарий инициализации базы данных очень прост, достаточно проверить, существует ли определенная база данных, и создать ее, если она не существует.

CREATE DATABASE IF NOT EXISTS `db_apiserver`;

запускать

Когда все изменения сделаны, пора начинать и пробовать.

docker-compose up --scale app=3 nginx

Это запускает три экземпляра приложения.

если вы продолжите посещатьhttp://127.0.0.1:80/v1/check/health, должно получиться три результата, Аналогично следующему:

OK from 5f8a835b6797
OK from b6dbb50cecd5
OK from 87e98121950d

Первые несколько посещений могут возвращать ошибку 502, поскольку приложение все еще подключается к базе данных и не запущено.

Затем вы можете изменить конфигурацию nginx, чтобы использовать различные механизмы балансировки нагрузки, встроенные в nginx. Рекомендуется использовать предыдущий使用 Go 添加 Nginx 代理использовать вместе.

Суммировать

Есть много способов развертывания GO, просто выберите правильный. Если вам это нужно, вы также можете пересекать двоичные файлы для каждой платформы.

Текущий раздел кода

как версияv0.17.0