Nginx部署Go项目 | 青训营笔记

1,179 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 15 天

如何在 Ubuntu 云服务器上使用Nginx部署 Go 语言程序?

Nginx 是一个免费的、开源的、高性能的 HTTP 和反向代理服务,主要负责负载一些访问量比较大的站点。Nginx 可以作为一个独立的 Web 服务,也可以用来给 Apache 或是其他的 Web 服务做反向代理。相比于 Apache,Nginx 可以处理更多的并发连接,而且每个连接的内存占用的非常小。

Nginx的安装

没有安装的可以看我的这篇文章,这里就不再水字数了,哈哈

Nginx常用命令

在这里补充几个 Nginx 常用命令。

nginx -s stop    # 停止 Nginx 服务
nginx -s reload  # 重新加载配置文件
nginx -s quit    # 平滑停止 Nginx 服务
nginx -t         # 测试配置文件是否正确

Nginx反向代理部署

推荐使用 nginx 作为反向代理来部署我们的程序,按下面的内容修改 nginx 的配置文件

worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;

    server {
        listen       80;
        server_name  localhost;

        access_log   /var/log/bluebell-access.log;
        error_log    /var/log/bluebell-error.log;

        location / {
            proxy_pass                 http://127.0.0.1:8084;
            proxy_redirect             off;
            proxy_set_header           Host             $host;
            proxy_set_header           X-Real-IP        $remote_addr;
            proxy_set_header           X-Forwarded-For  $proxy_add_x_forwarded_for;
        }
    }
}

执行下面的命令检查配置文件语法:

nginx -t

执行下面的命令重新加载配置文件:

nginx -s reload

接下来就是打开浏览器查看网站是否正常了。

当然我们还可以使用 nginxupstream 配置来添加多个服务器地址实现负载均衡。

worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;

    upstream backend {
      server 127.0.0.1:8084;
      # 这里需要填真实可用的地址,默认轮询
      #server backend1.example.com;
      #server backend2.example.com;
    }

    server {
        listen       80;
        server_name  localhost;

        access_log   /var/log/bluebell-access.log;
        error_log    /var/log/bluebell-error.log;

        location / {
            proxy_pass                 http://backend/;
            proxy_redirect             off;
            proxy_set_header           Host             $host;
            proxy_set_header           X-Real-IP        $remote_addr;
            proxy_set_header           X-Forwarded-For  $proxy_add_x_forwarded_for;
        }
    }
}

Nginx分离静态文件请求

上面的配置是简单的使用 nginx 作为反向代理处理所有的请求并转发给我们的 Go 程序处理,其实我们还可以有选择的将静态文件部分的请求直接使用 nginx 处理,而将 API 接口类的动态处理请求转发给后端的 Go 程序来处理

分离静态文件请求图示

下面继续修改我们的 nginx 的配置文件来实现上述功能。

worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;

    server {
        listen       80;
        server_name  bluebell;

        access_log   /var/log/bluebell-access.log;
        error_log    /var/log/bluebell-error.log;

		# 静态文件请求
        location ~ .*\.(gif|jpg|jpeg|png|js|css|eot|ttf|woff|svg|otf)$ {
            access_log off;
            expires    1d;
            root       /data/app/bluebell;
        }

        # index.html页面请求
        # 因为是单页面应用这里使用 try_files 处理一下,避免刷新页面时出现404的问题
        location / {
            root /data/app/bluebell/templates;
            index index.html;
            try_files $uri $uri/ /index.html;
        }

		# API请求
        location /api {
            proxy_pass                 http://127.0.0.1:8084;
            proxy_redirect             off;
            proxy_set_header           Host             $host;
            proxy_set_header           X-Real-IP        $remote_addr;
            proxy_set_header           X-Forwarded-For  $proxy_add_x_forwarded_for;
        }
    }
}

前后端分开部署

前后端的代码没必要都部署到相同的服务器上,也可以分开部署到不同的服务器上,下图是前端服务将 API 请求转发至后端服务的方案。

前后端分开部署方案1

上面的部署方案中,所有浏览器的请求都是直接访问前端服务,而如果是浏览器直接访问后端API服务的部署模式下,如下图。

此时前端和后端通常不在同一个域下,我们还需要在后端代码中添加跨域支持。

前后端分开部署方案2

这里使用github.com/gin-contrib…库来支持跨域请求。

最简单的允许跨域的配置是使用cors.Default(),它默认允许所有跨域请求。

func main() {
	router := gin.Default()
	// same as
	// config := cors.DefaultConfig()
	// config.AllowAllOrigins = true
	// router.Use(cors.New(config))
	router.Use(cors.Default())
	router.Run()
}

此外,还可以使用cors.Config自定义具体的跨域请求相关配置项:

package main

import (
	"time"

	"github.com/gin-contrib/cors"
	"github.com/gin-gonic/gin"
)

func main() {
	router := gin.Default()
	// CORS for https://foo.com and https://github.com origins, allowing:
	// - PUT and PATCH methods
	// - Origin header
	// - Credentials share
	// - Preflight requests cached for 12 hours
	router.Use(cors.New(cors.Config{
		AllowOrigins:     []string{"https://foo.com"},
		AllowMethods:     []string{"PUT", "PATCH"},
		AllowHeaders:     []string{"Origin"},
		ExposeHeaders:    []string{"Content-Length"},
		AllowCredentials: true,
		AllowOriginFunc: func(origin string) bool {
			return origin == "https://github.com"
		},
		MaxAge: 12 * time.Hour,
	}))
	router.Run()
}

参考资料

部署Go语言项目的 N 种方法