用 Go 开发终端接口服务--把项目部署到服务器
Go 编译代码生成二进制包的时候,只处理 go 类型文件,静态文件、配置文件、 HTML 等那些非 go 类型文件都原样保留。进入项目根目录下,执行打包指令如:
go build -ldflags "-w -s"
Go 在不同的操作系统上编译出来的二进制包是不一样的,比如在 Windows 下编译出 chapter01.exe,在 Linux 下编译出 chapter01,也可以通过指令进行交叉编译,不过交叉编译不在本教程的范围内,一般我们服务器都是 Linux,我们最好在本地相同的系统下编译,再上传到服务器部署,或在服务器上完成编译,这样可以避免不必要的麻烦。值得注意的是,如果本地系统配置 Go 环境,编译成二进制包,那么服务器不需要安装任何 Go 相关的东西,因为打出来的二进制包,已经把所有依赖都打进去了。这就是 Go 特别赞的地方。
上次说明了项目架构,根目录是 chapter01 文件夹,打完二进制包后,项目结构不变,所有 go 相关的代码,都会编译成 一个二进制文件,存放在根目录下,我们只需要把二进制包、静态文件、配置文件、 HTML 等那些非 go 类型文件原样放在 chapter01 文件夹上,上传到服务器即可。
比如我们部署在 /var/www/go 路径下,新建 一个 chapter01 文件夹:
cd /var/www/go/ mkdir chapter01
nohup ./chapter01 &如果没有错误,服务就算启动成功了。如果有错误,退出 nohup 守护进程,在 chapter01/nohup.out 查看错误日志,排除问题。
# ctrl+c 退出 nohup 守护进程,查看 chapter01 服务启动日志 cat /var/www/go/chapter01/nohup.out
使用 nohup 守护服务进程,是非常简陋的做法,如果服务器意外关机重启,服务就无法自动重启,我们的服务因此会发生中断,恰恰我们又没有发现,那就很不好了。建议起码通过 supervisord 来守护服务进程,再配置一些日志路径,重启次数等参数,更稳妥一些。supervisord 安装方法不再累赘说明,读者可以查阅本章小结外部资料。以下是 supervisord 守护 chapter01 服务进程的配置:
[program:chapter01] command=/var/www/go/chapter01/chapter01 directory=/var/www/go/chapter01 priority=1 autostart=true autorestart=true startsecs=10 startretries=3 stdout_logfile=/var/www/go/chapter01/chapter01_access.log stdout_logfile_maxbytes=1MB stdout_logfile_backups=10 stdout_capture_maxbytes=1MB stderr_logfile=/var/www/go/chapter01/chapter01_error.log stderr_logfile_maxbytes=1MB stderr_logfile_backups=10 stderr_capture_maxbytes=1MB
下面讲解一下 supervisord 重要的配置属性:
- command:启动指令
- directory:启动目录
- priority:启动优先级 1...n,越小越优先
- autostart :开机自动启动
- autorestart :意外中断自动重启
- startretries :尝试启动次数
- stdout_logfile: 请求日志路径
- stderr_logfile: 出错日志路径
通过 supervisord 的协助,保证了 chapter01 服务进程运行稳妥后,下一步是启动两个 chapter01 服务进程,分别运行在 3001、3002 两个端口下,我们使用 nginx 代理它们,并绑定域名,比如域名是 api.mydomain.com,新建一个 nginx 配置文件 /etc/nginx/sites-enabled/api.mydomain.com.conf
# 新建 api.mydomain.com 的 nginx 配置文件 nano /etc/nginx/sites-enabled/api.mydomain.com.conf
通过以下配置来完成代理和绑定操作:
*代码清单 - nginx 代理接口服务,绑定域名配置*
upstream api_mydomain_com { server localhost:3001 max_fails=3 fail_timeout=45s; server localhost:3002 max_fails=3 fail_timeout=45s; keepalive 30; } server { listen 80; server_name api.mydomain.com; location / { proxy_pass http://api_mydomain_com; proxy_redirect off; proxy_pass_header Server; proxy_set_header Host $http_host; proxy_set_header Remote_addr $remote_addr; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Scheme $scheme; proxy_http_version 1.1; index index.html; root /var/www/go/chapter01/; } location /static { root /var/www/go/chapter01/; expires 30d; add_header Cache-Control public; access_log off; } location /media { root /var/www/go/chapter01/; expires 1d; add_header Cache-Control public; access_log off; } }
保存配置,重启 nginx 服务器
service nginx restart重启 nginx 后,通过 http://api.mydomain.com 域名访问我们的 chapter01 服务。以上配置只是提供普通的 http 模式服务。
如果想让我们的服务运行在 http2 模式下,发挥更大的效能,Go 服务不做任何改变,只需对现有的 nginx 做一下升级,升级到 1.9.6 版本或以上,搭配一个 SSL 证书,nginx 启用 http2 模式,重启即可;
如果 nginx 版本比较陈旧,可以先卸载,再安装最新的版本:
## 卸载老版本 nginx : sudo apt-get --purge remove nginx sudo apt-get --purge remove nginx-common sudo apt-get --purge remove nginx-core ## 重新安装最新版本 nginx: sudo apt-get install software-properties-common sudo add-apt-repository ppa:nginx/stable sudo apt-get update sudo apt-get install nginx
nginx 升级工作完成后,先彻底杀死老 nginx 的进程,再查看当前版本,是不是成功升级了
# 查看老 nginx 进程 pid ps -ef|grep nginx # 查出 pid 后,直接强制杀死 kill -9 pid # 重启新 nginx 服务 service nginx restart # 查看新 nginx 的版本号是否正确? nginx -V
升级一切都完毕,SSL 证书也准备就绪,它们有两个文件,一个是证书,一个是证书密钥,路径我们自行存放:
# 证书文件路径 /var/www/conf/chapter01/1_api.mydomain.com_bundle.crt # 证书密钥路径 /var/www/conf/chapter01/2_api.mydomain.com.key
*代码清单 - nginx 启用 http2 模式配置如下:*
upstream api_mydomain_com { server localhost:3001 max_fails=3 fail_timeout=45s; server localhost:3002 max_fails=3 fail_timeout=45s; keepalive 30; } server { # 关键点 通过 443 端口启用 http2 模式 listen 443 ssl http2; server_name api.mydomain.com; # 关键点 证书的一系列配置 ssl_certificate /var/www/conf/chapter01/1_api.mydomain.com_bundle.crt; ssl_certificate_key /var/www/conf/chapter01/2_api.mydomain.com.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; ssl_ciphers EECDH+AES128:HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; location / { proxy_pass http://api_mydomain_com; proxy_redirect off; proxy_pass_header Server; proxy_set_header Host $http_host; proxy_set_header Remote_addr $remote_addr; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Scheme $scheme; proxy_set_header X-Forwarded-Proto https; index index.html; root /var/www/go/chapter01/; } location /static { root /var/www/go/chapter01/; expires 30d; add_header Cache-Control public; access_log off; } location /media { root /var/www/go/chapter01/; expires 1d; add_header Cache-Control public; access_log off; } }
再重启 nginx 后,通过 https://api.mydomain.com 域名访问 http2 模式下的 chapter01 服务了。
小结
supervisor 安装和配置,请参考:
- https://www.cnblogs.com/lege/p/4228984.html
- https://www.cnblogs.com/jasonkoo/articles/3750638.html
- https://www.cnblogs.com/shengulong/p/7641069.html
《用 Go 开发终端接口服务》 目录
- 小册介绍
- 前言
- 环境搭建与开发工具选择
- Go 语言基本语法
- Go 语言编码规范
- 快速编写一个 Web 服务器
- 项目整体结构介绍
- 准备项目所需的 Go 类包
- 公共类关键函数
- 定义 model 实体层结构体
- 灵活写 dao 数据层函数
- 按需写 service 服务层逻辑
- 暴露 controller 控制层接口
- 测试已写好的接口
- 把项目部署到服务器
- 保证高性能项目的法宝
- 写在后面
哇~~~ 竟然还没有评论!