goweb-部署与维护

部署与维护

到目前为止,咱们前面已经介绍了如何开发程序、调试程序以及测试程序,正如人们常说的:开发最后的10%须要花费90%的时间,因此这咱们将强调这最后的10%部分,要真正成为让人信任并使用的优秀应用,须要考虑到一些细节,以上所说的10%就是指这些小细节。html

应用日志

咱们指望开发的Web应用程序可以把整个程序运行过程当中出现的各类事件一一记录下来,Go语言中提供了一个简易的log包,咱们使用该包能够方便的实现日志记录的功能,这些日志都是基于fmt包的打印再结合panic之类的函数来进行通常的打印、抛出错误处理。Go目前标准包只是包含了简单的功能,若是咱们想把咱们的应用日志保存到文件,而后又可以结合日志实现不少复杂的功能(编写过Java或者C++的读者应该都使用过log4j和log4cpp之类的日志工具),可使用第三方开发的日志系统:logrus和seelog,它们实现了很强大的日志功能,能够结合本身项目选择。mysql

logrus介绍

logrus是用Go语言实现的一个日志系统,与标准库log彻底兼容而且核心API很稳定,是Go语言目前最活跃的日志库linux

seelog介绍

seelog是用Go语言实现的一个日志系统,它提供了一些简单的函数来实现复杂的日志分配、过滤和格式化。主要有以下特性:git

  • XML的动态配置,能够不用从新编译程序而动态的加载配置信息github

  • 支持热更新,可以动态改变配置而不须要重启应用golang

  • 支持多输出流,可以同时把日志输出到多种流中、例如文件流、网络流等web

  • 支持不一样的日志输出redis

    • 命令行输出
    • 文件输出
    • 缓存输出
    • 支持log rotate
    • SMTP邮件
      上面只列举了部分特性,seelog是一个特别强大的日志处理系统,详细的内容请参看官方wiki。

使用应用日志

对于应用日志,每一个人的应用场景可能会各不相同,有些人利用应用日志来作数据分析,有些人利用应用日志来作性能分析,有些人来作用户行为分析,还有些就是纯粹的记录,以方便应用出现问题的时候辅助查找问题。sql

举一个例子,咱们须要跟踪用户尝试登录系统的操做。这里会把成功与不成功的尝试都记录下来。记录成功的使用"Info"日志级别,而不成功的使用"warn"级别。若是想查找全部不成功的登录,咱们能够利用linux的grep之类的命令工具,以下:shell

# cat /data/logs/roll.log | grep "failed login"
2012-12-11 11:12:00 WARN : failed login attempt from 11.22.33.44 username password

经过这种方式咱们就能够很方便的查找相应的信息,这样有利于咱们针对应用日志作一些统计和分析。另外咱们还须要考虑日志的大小,对于一个高流量的Web应用来讲,日志的增加是至关可怕的,因此咱们在seelog的配置文件里面设置了logrotate,这样就能保证日志文件不会由于不断变大而致使咱们的磁盘空间不够引发问题。

经过上面对seelog系统及如何基于它进行自定义日志系统的学习,如今咱们能够很轻松的随需构建一个合适的功能强大的日志处理系统了。日志处理系统为数据分析提供了可靠的数据源,好比经过对日志的分析,咱们能够进一步优化系统,或者应用出现问题时方便查找定位问题,另外seelog也提供了日志分级功能,经过对minlevel的配置,咱们能够很方便的设置测试或发布版本的输出消息级别。

网站错误处理

咱们的Web应用一旦上线以后,那么各类错误出现的几率都有,Web应用平常运行中可能出现多种错误,具体以下所示:

  • 数据库错误:指与访问数据库服务器或数据相关的错误。例如,如下可能出现的一些数据库错误。

    • 链接错误:这一类错误多是数据库服务器网络断开、用户名密码不正确、或者数据库不存在。
    • 查询错误:使用的SQL非法致使错误,这样子SQL错误若是程序通过严格的测试应该能够避免。
    • 数据错误:数据库中的约束冲突,例如一个惟一字段中插入一条重复主键的值就会报错,可是若是你的应用程序在上线以前通过了严格的测试也是能够避免这类问题。
    • 应用运行时错误:这类错误范围很广,涵盖了代码中出现的几乎全部错误。可能的应用错误的状况以下:

    • 文件系统和权限:应用读取不存在的文件,或者读取没有权限的文件、或者写入一个不容许写入的文件,这些都会致使一个错误。应用读取的文件若是格式不正确也会报错,例如配置文件应该是ini 的配置格式,而设置成了json格式就会报错。
    • 第三方应用:若是咱们的应用程序耦合了其余第三方接口程序,例如应用程序发表文章以后自动调用接发微博的接口,因此这个接口必须正常运行才能完成咱们发表一篇文章的功能。
  • HTTP错误:这些错误是根据用户的请求出现的错误,最多见的就是404错误。虽然可能会出现不少不一样的错误,但其中比较常见的错误还有401未受权错误(须要认证才能访问的资源)、403禁止错误(不容许用户访问的资源)和503错误(程序内部出错)。

  • 操做系统出错:这类错误都是因为应用程序上的操做系统出现错误引发的,主要有操做系统的资源被分配完了,致使死机,还有操做系统的磁盘满了,致使没法写入,这样就会引发不少错误。

  • 网络出错:指两方面的错误,一方面是用户请求应用程序的时候出现网络断开,这样就致使链接中断,这种错误不会形成应用程序的崩溃,可是会影响用户访问的效果;另外一方面是应用程序读取其余网络上的数据,其余网络断开会致使读取失败,这种须要对应用程序作有效的测试,可以避免这类问题出现的状况下程序崩溃。

错误处理的目标

在实现错误处理以前,咱们必须明确错误处理想要达到的目标是什么,错误处理系统应该完成如下工做:

  • 通知访问用户出现错误了:不论出现的是一个系统错误仍是用户错误,用户都应当知道Web应用出了问题,用户的此次请求没法正确的完成了。例如,对于用户的错误请求,咱们显示一个统一的错误页面(404.html)。出现系统错误时,咱们经过自定义的错误页面显示系统暂时不可用之类的错误页面(error.html)。
  • 记录错误:系统出现错误,通常就是咱们调用函数的时候返回err不为nil的状况,可使用前面小节介绍的日志系统记录到日志文件。若是是一些致命错误,则经过邮件通知系统管理员。通常404之类的错误不须要发送邮件,只须要记录到日志系统。
  • 回滚当前的请求操做:若是一个用户请求过程当中出现了一个服务器错误,那么已完成的操做须要回滚。下面来看一个例子:一个系统将用户递交的表单保存到数据库,并将这个数据递交到一个第三方服务器,可是第三方服务器挂了,这就致使一个错误,那么先前存储到数据库的表单数据应该删除(应告知无效),并且应该通知用户系统出现错误了。
  • 保证现有程序可运行可服务:咱们知道没有人能保证程序必定可以一直正常的运行着,万一哪一天程序崩溃了,那么咱们就须要记录错误,而后马上让程序从新运行起来,让程序继续提供服务,而后再通知系统管理员,经过日志等找出问题。

如何处理异常

咱们知道在不少其余语言中有try...catch关键词,用来捕获异常状况,可是其实不少错误都是能够预期发生的,而不须要异常处理,应该当作错误来处理,这也是为何Go语言采用了函数返回错误的设计,这些函数不会panic,例如若是一个文件找不到,os.Open返回一个错误,它不会panic;若是你向一个中断的网络链接写数据,net.Conn系列类型的Write函数返回一个错误,它们不会panic。这些状态在这样的程序里都是能够预期的。你知道这些操做可能会失败,由于设计者已经用返回错误清楚地代表了这一点。这就是上面所讲的能够预期发生的错误。

可是还有一种状况,有一些操做几乎不可能失败,并且在一些特定的状况下也没有办法返回错误,也没法继续执行,这样状况就应该panic。举个例子:若是一个程序计算x[j],可是j越界了,这部分代码就会致使panic,像这样的一个不可预期严重错误就会引发panic,在默认状况下它会杀掉进程,它容许一个正在运行这部分代码的goroutine从发生错误的panic中恢复运行,发生panic以后,这部分代码后面的函数和代码都不会继续执行,这是Go特地这样设计的,由于要区别于错误和异常,panic其实就是异常处理。

规则很简单:若是你定义的函数有可能失败,它就应该返回一个错误。当我调用其余package的函数时,若是这个函数实现的很好,我不须要担忧它会panic,除非有真正的异常状况发生,即便那样也不该该是我去处理它。而panic和recover是针对本身开发package里面实现的逻辑,针对一些特殊状况来设计。

应用部署

程序开发完毕以后,咱们如今要部署Web应用程序了,可是咱们如何来部署这些应用程序呢?由于Go程序编译以后是一个可执行文件,编写过C程序的读者必定知道采用daemon就能够完美的实现程序后台持续运行,可是目前Go还没法完美的实现daemon,所以,针对Go的应用程序部署,咱们能够利用第三方工具来管理,第三方的工具备不少,例如Supervisord、upstart、daemontools等,

daemon

目前Go程序还不能实现daemon,详细的见这个Go语言的bug:http://code.google.com/p/go/issues/detail?id=227,大概的意思说很难从现有的使用的线程中fork一个出来,由于没有一种简单的方法来确保全部已经使用的线程的状态一致性问题。

备份和恢复

应用备份

在大多数集群环境下,Web应用程序基本不须要备份,由于这个其实就是一个代码副本,咱们在本地开发环境中,或者版本控制系统中已经保持这些代码。可是不少时候,一些开发的站点须要用户来上传文件,那么咱们须要对这些用户上传的文件进行备份。目前其实有一种合适的作法就是把和网站相关的须要存储的文件存储到云储存,这样即便系统崩溃,只要咱们的文件还在云存储上,至少数据不会丢失。

若是咱们没有采用云储存的状况下,如何作到网站的备份呢?这里咱们介绍一个文件同步工具rsync:rsync可以实现网站的备份,不一样系统的文件的同步,若是是windows的话,须要windows版本cwrsync。

MySQL备份

应用数据库目前仍是MySQL为主流,目前MySQL的备份有两种方式:热备份和冷备份,热备份目前主要是采用master/slave方式(master/slave方式的同步目前主要用于数据库读写分离,也能够用于热备份数据),关于如何配置这方面的资料,你们能够找到不少。冷备份的话就是数据有必定的延迟,可是能够保证该时间段以前的数据完整,例若有些时候可能咱们的误操做引发了数据的丢失,那么master/slave模式是没法找回丢失数据的,可是经过冷备份能够部分恢复数据。

冷备份通常使用shell脚原本实现定时备份数据库,而后经过上面的rsync同步非本地机房的一台服务器。

MySQL恢复

前面介绍MySQL备份分为热备份和冷备份,热备份主要的目的是为了可以实时的恢复,例如应用服务器出现了硬盘故障,那么咱们能够经过修改配置文件把数据库的读取和写入改为slave,这样就能够尽可能少时间的中断服务。

可是有时候咱们须要经过冷备份的SQL来进行数据恢复,既然有了数据库的备份,就能够经过命令导入:

mysql -u username -p databse < backup.sql
能够看到,导出和导入数据库数据都是至关简单,不过若是还须要管理权限,或者其余的一些字符集的设置的话,可能会稍微复杂一些,可是这些都是能够经过一些命令来完成的。

redis备份

redis是目前咱们使用最多的NoSQL,它的备份也分为两种:热备份和冷备份,redis也支持master/slave模式,因此咱们的热备份能够经过这种方式实现,相应的配置你们能够参考官方的文档配置,至关的简单。咱们这里介绍冷备份的方式:redis其实会定时的把内存里面的缓存数据保存到数据库文件里面,咱们备份只要备份相应的文件就能够,就是利用前面介绍的rsync备份到非本地机房就能够实现。

redis恢复

redis的恢复分为热备份恢复和冷备份恢复,热备份恢复的目的和方法同MySQL的恢复同样,只要修改应用的相应的数据库链接便可。

可是有时候咱们须要根据冷备份来恢复数据,redis的冷备份恢复其实就是只要把保存的数据库文件copy到redis的工做目录,而后启动redis就能够了,redis在启动的时候会自动加载数据库文件到内存中,启动的速度根据数据库的文件大小来决定。

看到这我明白了我对数据库了解的仍是太少o(╥﹏╥)o

最后的小结

本章讨论了如何部署和维护咱们开发的Web应用相关的一些话题。这些内容很是重要,要建立一个可以基于最小维护平滑运行的应用,必须考虑这些问题。

具体而言,本章讨论的内容包括:

  • 建立一个强健的日志系统,能够在出现问题时记录错误而且通知系统管理员
  • 处理运行时可能出现的错误,包括记录日志,并如何友好的显示给用户系统出现了问题
  • 处理404错误,告诉用户请求的页面找不到
  • 将应用部署到一个生产环境中(包括如何部署更新)
  • 如何让部署的应用程序具备高可用
  • 备份和恢复文件以及数据库
    读完本章内容后,对于从头开始开发一个Web应用须要考虑那些问题,你应该已经有了全面的了解。本章内容将有助于你在实际环境中管理前面各章介绍开发的代码。

好刺激呀这一块

连接

相关文章
相关标签/搜索