From 47b0b70866a57f57e7966fc322350a19407bff39 Mon Sep 17 00:00:00 2001 From: hongruiqi Date: Tue, 29 Jan 2013 08:36:43 +0800 Subject: [PATCH 1/4] 12.1.md --- 12.1.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/12.1.md b/12.1.md index 570664f4..8f039b3e 100755 --- a/12.1.md +++ b/12.1.md @@ -1,5 +1,5 @@ # 12.1 应用日志 -我们期望开发的Web应用程序能够把整个程序运行过程中出现的各种事件一一记录下来,Go语言中提供了一个简易的log包,我们使用该包可以方便的实现日志记录的功能,这些日志都是基本的给予fmt包的打印再结合panic之类的一些函数来处理我们一般的打印抛出错误之类的。如果我们想把我们的应用日志保存到文件,然后又能够结合日志实现很多复杂的功能,编写过Java或者C++的读者应该都使用过log4j和log4cpp之类的日志工具,Go目前标准包就如前面介绍的只是包含了一个简单的包,但是目前第三方开发的一个日志系统实现了很强大的日志功能,`https://github.com/cihub/seelog`,接下来我们介绍如何通过该日志系统来实现我们应用的日志功能。 +我们期望开发的Web应用程序能够把整个程序运行过程中出现的各种事件一一记录下来,Go语言中提供了一个简易的log包,我们使用该包可以方便的实现日志记录的功能,这些日志都是基于fmt包的打印再结合panic之类的函数来进行一般的打印、抛出错误处理。Go目前标准包只是包含了简单的功能,如果我们想把我们的应用日志保存到文件,然后又能够结合日志实现很多复杂的功能(编写过Java或者C++的读者应该都使用过log4j和log4cpp之类的日志工具),可以使用第三方开发的一个日志系统,`https://github.com/cihub/seelog`,它实现了很强大的日志功能。接下来我们介绍如何通过该日志系统来实现我们应用的日志功能。 ## seelog介绍 seelog是用Go语言实现的一个日志系统,它提供了一些简单的函数来实现复杂的日志分配、过滤和格式化。主要有如下特性: @@ -158,9 +158,9 @@ seelog支持自定义日志处理,下面是我基于它自定义的日志处 通过这种方式我们就可以很方便的查找相应的信息,这样有利于我们针对应用日志做一些统计和分析。另外我们还需要考虑日志的大小,对于一个高流量的Web应用来说,日志的增长是相当可怕的,所以我们在seelog的配置文件里面设置了logrotate,这样就能保证日志文件不会因为不断变大而导致我们的磁盘空间不够引起问题。 ## 小结 -通过上面对seelog系统及如何基于它进行自定义日志系统的学习,现在我们可以很轻松的随需构建一个合适的功能强大的日志处理系统了。日志处理系统为数据分析提供了可靠的数据源,比如通过对日志的分析,我们可以进一步优化系统,或者应用出现问题时方便查找定位问题,另外seelog也提供了日志分级功能,通过对minlevel的配置,我们可以很方便的测试或发布版本的输出消息。 +通过上面对seelog系统及如何基于它进行自定义日志系统的学习,现在我们可以很轻松的随需构建一个合适的功能强大的日志处理系统了。日志处理系统为数据分析提供了可靠的数据源,比如通过对日志的分析,我们可以进一步优化系统,或者应用出现问题时方便查找定位问题,另外seelog也提供了日志分级功能,通过对minlevel的配置,我们可以很方便的设置测试或发布版本的输出消息级别。 ## links * [目录]() * 上一章: [部署与维护](<12.0.md>) - * 下一节: [网站错误处理](<12.2.md>) \ No newline at end of file + * 下一节: [网站错误处理](<12.2.md>) From ebbed629aecb5bac97df076995e14ae33fa93e09 Mon Sep 17 00:00:00 2001 From: hongruiqi Date: Mon, 28 Jan 2013 18:35:56 +0800 Subject: [PATCH 2/4] 12.2.md --- 12.2.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/12.2.md b/12.2.md index ce024582..57da1d42 100755 --- a/12.2.md +++ b/12.2.md @@ -11,15 +11,15 @@ - 文件系统和权限:应用读取不存在的文件,或者读取没有权限的文件、或者写入一个不允许写入的文件,这些都会导致一个错误。应用读取的文件如果格式不正确也会报错,例如配置文件应该是ini的配置格式,而设置成了json格式就会报错。 - 第三方应用:如果我们的应用程序耦合了其他第三方接口程序,例如应用程序发表文章之后自动调用接发微博的接口,所以这个接口必须正常运行才能完成我们发表一篇文章的功能。 -- HTTP错误:这些错误是根据用户的请求出现的错误,最常见的就是404请求,虽然可能会出现很多不同的错误,但其中比较常见的错误还有401未授权错误(需要认证才能访问的资源)、403禁止错误(不允许用户访问的资源)和503错误(程序内部出错)。 +- HTTP错误:这些错误是根据用户的请求出现的错误,最常见的就是404错误。虽然可能会出现很多不同的错误,但其中比较常见的错误还有401未授权错误(需要认证才能访问的资源)、403禁止错误(不允许用户访问的资源)和503错误(程序内部出错)。 - 操作系统出错:这类错误都是由于应用程序上的操作系统出现错误引起的,主要有操作系统的资源被分配完了,导致死机,还有操作系统的磁盘满了,导致无法写入,这样就会引起很多错误。 - 网络出错:指两方面的错误,一方面是用户请求应用程序的时候出现网络断开,这样就导致连接中断,这种错误不会造成应用程序的崩溃,但是会影响用户访问的效果;另一方面是应用程序读取其他网络上的数据,其他网络断开会导致读取失败,这种需要对应用程序做有效的测试,能够避免这类问题出现的情况下程序崩溃。 ## 错误处理的目标 在实现错误处理之前,我们必须明确错误处理想要达到的目标是什么,错误处理系统应该完成以下工作: -- 通知访问用户出现错误了:不论出现的是一个系统错误还是用户错误,用户都应当知道Web应用出了问题,用户的这次请求无法正确的完成了。例如用户的错误请求我们显示一个统一的错误页面(404.html),出现系统错误我们通过自定义的错误页面显示系统暂时不可用之类的错误页面(error.html) -- 记录错误:系统出错错误时,一般就是我们调用函数的时候返回err不为nil的情况下,使用前面小节介绍的日志系统记录到日志文件,如果是一些致命错误通过邮件通知系统管理员,例如一般404之类的错误不需要发送邮件,只需要记录到日志系统。 +- 通知访问用户出现错误了:不论出现的是一个系统错误还是用户错误,用户都应当知道Web应用出了问题,用户的这次请求无法正确的完成了。例如,对于用户的错误请求,我们显示一个统一的错误页面(404.html)。出现系统错误时,我们通过自定义的错误页面显示系统暂时不可用之类的错误页面(error.html)。 +- 记录错误:系统出现错误,一般就是我们调用函数的时候返回err不为nil的情况,可以使用前面小节介绍的日志系统记录到日志文件。如果是一些致命错误,则通过邮件通知系统管理员。一般404之类的错误不需要发送邮件,只需要记录到日志系统。 - 回滚当前的请求操作:如果一个用户请求过程中出现了一个服务器错误,那么已完成的操作需要回滚。下面来看一个例子:一个系统将用户递交的表单保存到数据库,并将这个数据递交到一个第三方服务器,但是第三方服务器挂了,这就导致一个错误,那么先前存储到数据库的表单数据应该删除(应告知无效),而且应该通知用户系统出现错误了。 - 保证现有程序可运行可服务:我们知道没有人能保证程序一定能够一直正常的运行着,万一哪一天程序崩溃了,那么我们就需要记录错误,然后立刻让程序重新运行起来,让程序继续提供服务,然后再通知系统管理员,通过日志等找出问题。 @@ -114,11 +114,11 @@ return } -上面介绍了错误和异常的区别,那么我们在开发程序的时候如何来设计呢?规则很简单:如果你定义的函数无论如何有无可能失败,它就应该返回一个错误。当我调用其他package的函数时,如果这个函数实现的很好,我不需要担心它会panic,除非有真正的异常情况发生,即使那样也不应该是我去处理它。而panic和recover是针对自己开发package里面实现的逻辑,针对一些特殊情况来设计。 +上面介绍了错误和异常的区别,那么我们在开发程序的时候如何来设计呢?规则很简单:如果你定义的函数有可能失败,它就应该返回一个错误。当我调用其他package的函数时,如果这个函数实现的很好,我不需要担心它会panic,除非有真正的异常情况发生,即使那样也不应该是我去处理它。而panic和recover是针对自己开发package里面实现的逻辑,针对一些特殊情况来设计。 ## 小结 本小节总结了当我们的Web应用部署之后如何处理各种错误:网络错误、数据库错误、操作系统错误等,当错误发生时,我们的程序如何来正确处理:显示友好的出错界面、回滚操作、记录日志、通知管理员等操作,最后介绍了如何来正确处理错误和异常。一般的程序中错误和异常很容易混淆的,但是在Go中错误和异常是有明显的区分,所以告诉我们在程序设计中处理错误和异常应该遵循怎么样的原则。 ## links * [目录]() * 上一章: [应用日志](<12.1.md>) - * 下一节: [应用部署](<12.3.md>) \ No newline at end of file + * 下一节: [应用部署](<12.3.md>) From 6ad7ed726335f00f030879ca5af6ad092a6eeda6 Mon Sep 17 00:00:00 2001 From: hongruiqi Date: Tue, 29 Jan 2013 09:13:05 +0800 Subject: [PATCH 3/4] 12.3 --- 12.3.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/12.3.md b/12.3.md index 105d01e8..44de4504 100755 --- a/12.3.md +++ b/12.3.md @@ -1,7 +1,7 @@ # 12.3 应用部署 程序开发完毕之后,我们现在要部署Web应用程序了,但是我们如何来部署这些应用程序呢?因为Go程序编译之后是一个可执行文件,编写过C程序的读者一定知道采用daemon就可以完美的实现程序后台持续运行,但是目前Go还无法完美的实现daemon,因此,针对Go的应用程序部署,我们可以利用第三方工具来管理,第三方的工具有很多,例如Supervisord、upstart、daemontools等,这小节我介绍目前自己系统中采用的工具Supervisord。 ## daemon -目前Go程序如果要实现daemon还不行,详细的见这个Go语言的bug:<`http://code.google.com/p/go/issues/detail?id=227`>,大概的意思说很难从现有的使用的线程中fork一个出来,因为没有一种简单的方法来确保所有已经使用的线程的状态一致性问题。 +目前Go程序还不能实现daemon,详细的见这个Go语言的bug:<`http://code.google.com/p/go/issues/detail?id=227`>,大概的意思说很难从现有的使用的线程中fork一个出来,因为没有一种简单的方法来确保所有已经使用的线程的状态一致性问题。 但是我们可以看到很多网上的一些实现daemon的方法,例如下面两种方式: @@ -178,4 +178,4 @@ Supervisord安装完成后有两个可用的命令行supervisor和supervisorctl ## links * [目录]() * 上一章: [网站错误处理](<12.2.md>) - * 下一节: [备份和恢复](<12.4.md>) \ No newline at end of file + * 下一节: [备份和恢复](<12.4.md>) From 0bba6b7a77c581f3b7008f4844eaa46aa41c28f2 Mon Sep 17 00:00:00 2001 From: hongruiqi Date: Tue, 29 Jan 2013 09:13:11 +0800 Subject: [PATCH 4/4] 12.4 --- 12.4.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/12.4.md b/12.4.md index 37929448..0ea36ccd 100755 --- a/12.4.md +++ b/12.4.md @@ -59,7 +59,7 @@ rsync主要有以下三个配置文件rsyncd.conf(主配置文件)、rsyncd.secr ## MySQL备份 -应用数据库目前还是MySQL为主流,目前MySQL的备份有两种方式:热备份和冷备份,热备份目前主要是采用master/slave方式,关于如何配置这方面的资料,大家可以找到很多。master/slave方式的同步目前主要用于数据库读写分离,其实也可以用于热备份数据。冷备份的话就是数据有一定的延迟,但是可以保证该时间段之前的数据完整,例如有些时候可能我们的误操作引起了数据的丢失,那么master/slave模式是无法找回丢失数据的,但是通过冷备份可以部分恢复数据。 +应用数据库目前还是MySQL为主流,目前MySQL的备份有两种方式:热备份和冷备份,热备份目前主要是采用master/slave方式(master/slave方式的同步目前主要用于数据库读写分离,也可以用于热备份数据),关于如何配置这方面的资料,大家可以找到很多。冷备份的话就是数据有一定的延迟,但是可以保证该时间段之前的数据完整,例如有些时候可能我们的误操作引起了数据的丢失,那么master/slave模式是无法找回丢失数据的,但是通过冷备份可以部分恢复数据。 冷备份一般使用shell脚本来实现定时备份数据库,然后通过上面介绍rsync同步非本地机房的一台服务器。 @@ -135,7 +135,7 @@ rsync主要有以下三个配置文件rsyncd.conf(主配置文件)、rsyncd.secr `find $backup_location/ -type d -mtime +$expire_days | xargs rm -rf` echo "Expired backup data delete complete!" fi - echo "All database backup success! Think you!" + echo "All database backup success! Thank you!" exit fi @@ -146,7 +146,7 @@ rsync主要有以下三个配置文件rsyncd.conf(主配置文件)、rsyncd.secr 设置好属性之后,把命令加入crontab,我们设置了每天00:00定时自动备份,然后把备份的脚本目录/var/www/mysql设置为rsync同步目录。 - 00 00 * * * /root/mysql_backup.sh + 00 00 * * * /root/mysql_backup.sh ## MySQL恢复 前面介绍MySQL备份分为热备份和冷备份,热备份主要的目的是为了能够实时的恢复,例如应用服务器出现了硬盘故障,那么我们可以通过修改配置文件把数据库的读取和写入改成slave,这样就可以尽量少时间的中断服务。 @@ -171,4 +171,4 @@ redis的恢复分为热备份恢复和冷备份恢复,热备份恢复的目的 ## links * [目录]() * 上一章: [应用部署](<12.3.md>) - * 下一节: [小结](<12.5.md>) \ No newline at end of file + * 下一节: [小结](<12.5.md>)