Files
build-web-application-with-…/en/12.2.md
2014-12-17 12:48:51 -08:00

11 KiB
Raw Blame History

12.2 Errors and crashes

Once our web applications go live, it's likely that there will be some unforeseen errors. A few example of common errors that may occur in the course of your application's daily operations, are listed below:

  • Database Errors: errors related to accessing the database server or stored data. The following are some database errors which you may encounter:

  • Connection Errors: indicates that a connection to the network database server could not be established, a supplied user name or password is incorrect, or that the database does not exist.

  • Query Errors: the illegal or incorrect use of an SQL query can raise an error such as this. These types of errors can be avoided through rigorous testing.

  • Data Errors: database constraint violation such as attempting to insert a field with a duplicate primary key. These types of errors can also be avoided through rigorous testing before deploying your application into a production environment.

  • Application Runtime Errors: These types of errors vary greatly, covering almost all error codes which may appear during runtime. Possible application errors are as follows:

  • File system and permission errors: when the application attempts to read a file which does not exist or does not have permission to read, or when it attempts to write to a file which it is not allowed to write to, errors of this category will occur. A file system error will also occur if an application reads a file with an unexpected format, for instance a configuration file that should be in the INI format but is instead structured as JSON.

  • Third-party application errors: These errors occur in applications which interface with other third-party applications or services. For instance, if an application publishes tweets after making calls to Twitter's API, it's obvious that Twitter's services must be up and running in order for our application to complete its task. We must also ensure that we supply these third-party interfaces with the appropriate parameters in our calls, or else they will also return errors.

  • HTTP errors: These errors vary greatly, and are based on user requests. The most common is the 404 Not Found error, which arises when users attempt to access non-existent resources in your application. Another common HTTP error is the 401 Unauthorized error (authentication is required to access the requested resource), 403 Forbidden error (users are altogether refused access to this resource) and 503 Service Unavailable errors (indicative of an internal program error).

  • Operating system errors: These sorts of errors occur at the operating system layer and can happen when operating system resources are over-allocated, leading to crashes and system instability. Another common occurrence at this level is when the operating system disk gets filled to capacity, making it impossible to write to. This naturally produces in many errors.

  • Network errors: network errors typically come in two flavors: one is when users issue requests to the application and the network disconnects, thus disrupting its processing and response phase. These errors do not cause the application to crash, but can affect user access to the website; the other is when applications attempts to read data from disconnected networks, causing read failures. Judicious testing is particularly important when making network calls to avoid such problems, which can cause your application to crash.

Error handling goals

Before implementing error handling, we must be clear about what goals we are trying to achieve. In general, error handling systems should accomplish the following:

  • User error notifications: when system or user errors occur, causing current user requests to fail to complete, affected users should be notified of the problem. For example, for errors cause by user requests, we show a unified error page (404.html). When a system error occurs, we use a custom error page to provide feedback for users as to what happened -for instance, that the system is temporarily unavailable (error.html).
  • Log errors: when system errors occur (in general, when functions return non-nil error variables), a logging system such as the one described earlier should be used to record the event into a log file file. If it is a fatal error, the system administrator should also be notified via e-mail. In general however, most 404 errors do not warrant the sending of email notifications; recording the event into a log for later scrutiny is often adequate.
  • Roll back the current request operation: If a user request causes a server error, then we need to be able to roll back the current operation. Let's look at an example: a system saves a user-submitted form to its database, then submits this data to a third-party server. However, the third-party server disconnects and we are unable to establish a connection with it, which results in an error. In this case, the previously stored form data should be deleted from the database (void should be informed), and the application should inform the user of the system error.
  • Ensure that the application can recover from errors: we know that it's difficult for any program to guarantee 100% uptime, so we need to make provision for scenarios where our programs fail. For instance if our program crashes, we first need to log the error, notify the relevant parties involved, then immediately get the program up and running again. This way, our application can continue to provide services while a system administrator investigates and fixes the cause of the problem.

How to handle errors

In chapter 11, we addressed the process of error handling and design using some examples. Let's go into these examples in a bit more detail, and see some other error handling scenarios:

  • Notify the user of errors:

When an error occurs, we can present the user accessing the page with two kinds of errors pages: 404.html and error.html. Here is an example of what the source code of an error page might look like:

<html lang="en">

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <title>Page Not Found
  </title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>

<body>
  <div class="container">
	<div class="row">
	  <div class="span10">
		<div class="hero-unit">
		  <h1> 404! </h1>
		  <p>{{.ErrorInfo}}</p>
		</div>
	  </div>
	  <!--/span-->
	</div>
  </div>
</body>

</html>

Another example:

<html lang="en">

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <title>system error page
  </title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">

</head>

<body>
  <div class="container">
	<div class="row">
	  <div class="span10">
		<div class="hero-unit">
		  <h1> system is temporarily unavailable ! </h1>
		  <p>{{.ErrorInfo}}</p>
		</div>
	  </div>
	  <!--/span-->
	</div>
  </div>
</body>

</html>

404 error-handling logic, in the occurrence of a system error:

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(" page not found")              //error logging
	t, _ = t.ParseFiles("tmpl/404.html", nil) //parse the template file
	ErrorInfo := " File not found "           //Get the current user information
	t.Execute(w, ErrorInfo)                   //execute the template merger operation
}

func SystemError(w http.ResponseWriter, r *http.Request) {
	log.Critical(" System Error")                      //system error triggered Critical, then logging will not only send a message
	t, _ = t.ParseFiles("tmpl/error.html", nil)        //parse the template file
	ErrorInfo := " system is temporarily unavailable " //Get the current user information
	t.Execute(w, ErrorInfo)                            //execute the template merger operation
}

How to handle exceptions

We know that in many other languages have try... catch keywords used to capture the unusual situation, but in fact, many errors can be expected to occur without the need for exception handling, should be handled as an error, which is why the Go language using the function returns an error of design, these functions do not panic, for example, if a file is not found, os.Open returns an error, it will not panic; if you break the network connection to a write data, net.Conn series Type the Write function returns an error, they do not panic. These states where such procedures are to be expected. You know that these operations might fail, an error is returned because the designer has used a clear indication of this. This is the above stated error can be expected to occur.

But there is a situation, there are some operations almost impossible to fail, and in certain cases there is no way to return an error and can not continue, such a situation should panic. For example: if a program to calculate x [j], but j bounds, and this part of the code will lead to panic, like this one unexpected fatal error will cause panic, by default it will kill the process, it this allows a part of the code that is running from the error occurred panic goroutine recover operation, the occurrence of panic, the function of this part of the code and the code behind not be executed, which is specially designed such that Go, as separate from the errors and abnormal, panic fact exception handling. The following code, we expect to get the User via uid the username information, but if uid crossed the line will throw an exception, this time if we do not recover mechanism, the process will be killed, resulting in non- service program. So in order to process robustness, in some places need to establish recover mechanism.

func GetUser(uid int) (username string) {
	defer func() {
		if x := recover(); x != nil {
			username = ""
		}
	}()

	username = User[uid]
	return
}

The above describes the difference between errors and exceptions, so when we develop programs how to design it? The rules are simple: If you define a function may fail, it should return an error. When I call other package 's function, if this function is implemented well, I do not need to worry that it will panic, unless there is a true exception to happen, nor even that I should go with it. The panic and recover for its own development package which implements the logic to design for some special cases.

Summary

This section summarizes when we deployed Web application how to handle various error: network error, database error, operating system errors, etc., when an error occurs, our program how to correctly handle: Show friendly error interface, rollback, logging, notify the administrator and other operations, and finally explains how to correctly handle errors and exceptions. General program errors and exceptions easily confused, but errors and exceptions in Go is a clear distinction, so tell us in a program designed to handle errors and exceptions should follow the principles of how to.