Go Web编程(十二——部署与维护)
原文作者:Go 技术论坛文档:《Go Web 编程()》
转自链接:https://learnku.com/docs/build-web-application-with-golang/4-form/3173
应用日志
GO语言中提供了一个简易的log包,我们使用该包可以方便的实现日志记录的功能。
这些日志都是基于fmt包的打印再结合panic之类的函数来进行一般的打印、抛出错误处理。
第三方开发的日志系统:logrus和seelog。
- logrus
logrus是用Go语言实现的一个日志系统,与标准库log完全兼容并且核心API很稳定,是Go语言目前最活跃的日志库
安装logrus:
go get -u github.com/sirupsen/logrus
例:
package main
import (
log "github.com/Sirupsen/logrus"
)
func main(){
log.WithFields(logFields{
"animal" : "walrus",
}).Info("A walrus appears")
}
自定义日志处理:
package main
import (
"os"
log "github.com/Sirupsen/logrus"
)
func init() {
// 日志格式化为 JSON 而不是默认的 ASCII
log.SetFormatter(&log.JSONFormatter{})
// 输出 stdout 而不是默认的 stderr,也可以是一个文件
log.SetOutput(os.Stdout)
// 只记录严重或以上警告
log.SetLevel(log.WarnLevel)
}
func main() {
log.WithFields(log.Fields{
"animal": "walrus",
"size": 10,
}).Info("A group of walrus emerges from the ocean")
log.WithFields(log.Fields{
"omg": true,
"number": 122,
}).Warn("The group's number increased tremendously!")
log.WithFields(log.Fields{
"omg": true,
"number": 100,
}).Fatal("The ice breaks!")
// 通过日志语句重用字段
// logrus.Entry 返回自 WithFields()
contextLogger := log.WithFields(log.Fields{
"common": "this is a common field",
"other": "I also should be logged always",
})
contextLogger.Info("I'll be logged with common and other field")
contextLogger.Info("Me too")
}
- seelog介绍
seelog 是用 Go 语言实现的一个日志系统,它提供了一些简单的函数来实现复杂的日志分配、过滤和格式化。
安装seelog
go get -u github.com/cihub/seelog
例:
package main
import log "github.com/cihub/seelog"
func main(){
defer log.Flush()
log.Info("Hello from Seelog!")
}
编译后如果出现了hello from seelog,说明seelog日志系统以及成功安装并且可以正常运行了。
自定义日志处理:
package logs
import (
// "errors"
"fmt"
// "io"
seelog "github.com/cihub/seelog"
)
var Logger seelog.LoggerInterface
func loadAppConfig() {
appConfig := `
<seelog minlevel="warn">
<outputs formatid="common">
<rollingfile type="size" filename="/data/logs/roll.log" maxsize="100000" maxrolls="5"/>
<filter levels="critical">
<file path="/data/logs/critical.log" formatid="critical"/>
<smtp formatid="criticalemail" senderaddress="astaxie@gmail.com" sendername="ShortUrl API" hostname="smtp.gmail.com" hostport="587" username="mailusername" password="mailpassword">
<recipient address="xiemengjun@gmail.com"/>
</smtp>
</filter>
</outputs>
<formats>
<format id="common" format="%Date/%Time [%LEV] %Msg%n" />
<format id="critical" format="%File %FullPath %Func %Msg%n" />
<format id="criticalemail" format="Critical error on our server!\n %Time %Date %RelFile %Func %Msg \nSent by Seelog"/>
</formats>
</seelog>
`
logger, err := seelog.LoggerFromConfigAsBytes([]byte(appConfig))
if err != nil {
fmt.Println(err)
return
}
UseLogger(logger)
}
func init() {
DisableLog()
loadAppConfig()
}
// DisableLog disables all library log output
func DisableLog() {
Logger = seelog.Disabled
}
// UseLogger uses a specified seelog.LoggerInterface to output library log.
// Use this func if you are using Seelog logging system in your app.
func UseLogger(newLogger seelog.LoggerInterface) {
Logger = newLogger
}
网站错误处理
数据库错误:
连接错误:可能是与数据库服务器网络断开、用户名密码不正确
查询错误:SQL非法导致的错误
数据错误:数据库中的约束冲突,如一个唯一字段中插入一条重复主键的值就会报错
应用运行时错误:
文件系统和权限:应用读取不存在的文件或者没有权限的文件。应用读取的文件格式不正确。
第三方应用:调用的第三方接口程序必须正常巡行
HTTP错误:这些错误是根据用户的请求出现的错,最常见的是404错误。
操作系统出错:操作系统的资源被分配完了,导致死机,磁盘满了导致无法写入
网络出错:网络连接断开
- 错误处理的目标
通知访问用户出现错误、记录错误、回滚当前的请求操作、保证现有程序可运行可服务。
- 如何处理错误
通知用户在访问页面时候我们可以有两种错误:404.html和error.html
func (p *MyMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/" {
sayhelloName(w, r)
return
}
NotFound404(w, r)
return
}
func NotFound404(w http.ResponseWriter, r *http.Request) {
log.Error("页面找不到") // 记录错误日志
t, _ = t.ParseFiles("tmpl/404.html", nil) // 解析模板文件
ErrorInfo := "文件找不到" // 获取当前用户信息
t.Execute(w, ErrorInfo) // 执行模板的 merger 操作
}
func SystemError(w http.ResponseWriter, r *http.Request) {
log.Critical("系统错误") // 系统错误触发了 Critical,那么不仅会记录日志还会发送邮件
t, _ = t.ParseFiles("tmpl/error.html", nil) // 解析模板文件
ErrorInfo := "系统暂时不可用" // 获取当前用户信息
t.Execute(w, ErrorInfo) // 执行模板的 merger 操作
}
- 异常
程序的健壮性,在一些地方需要建立recover机制:
func GetUser(uid id)(username string){
defer func(){
if x:=recover();x!=nil {
username=""
}
}()
username = User[uid]
return
}
如果你定义的函数有可能失败,它就应该返回一个错误。当我调用其他 package 的函数时,如果这个函数实现的很好,我不需要担心它会 panic,除非有真正的异常情况发生,即使那样也不应该是我去处理它。而 panic 和 recover 是针对自己开发 package 里面实现的逻辑,针对一些特殊情况来设计。
应用部署
针对Go的应用程序部署,我们可以利用第三方工具来管理,第三方的工具有很多,例如Supervisord、upstart、daemontools等。
- Supervisord
安装:sudo easy_install supervisor安装。
Supervisord默认的配置文件路径为/etc/supervisord.conf
管理:supervisord,初始启动Supervisord
supervisorctl stop 停止某一个进程
supervisorctl start 启动某一个进程
supervisorctl stop all 停止全部进程
supervisorctl reload 载入最新的配置文件,并按新的配置启动、管理所有的进程。
备份和恢复
- rsync
$ yum insall rsync
配置文就:rsyncd.conf(主配置文件)、rsyncd.secrets(密码文件)、rsyncd.motd(rsync服务器信息)。
服务端开启:
#/usr/bin/rsync --daemon --config=/etc/rsyncd.conf
- Mysql备份
主从复制:https://www.cnblogs.com/Gumi-o/p/14469529.html
mysql恢复(冷备):
mysql -u username -p databse < backup.sql
- redis备份
分为两种:热备份和了备份,也支持master/slave模式。
冷备:定时把缓存数据保存到数据库文件里面。
- redis恢复
redis的恢复分为热备份恢复和冷备份恢复,热备份只需要修改应用的相应的数据库连接即可。
冷备份只需要把保存的数据copy到redis的工作目录就可以了。

浙公网安备 33010602011771号