Golang Hot Update Tips

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

Preface

The HTTP section of the Golang standard library provides powerful Web application support, coupled with the support of middleware frameworks such as Negroni, to develop high-performance Web applications, such as providing RESTful API services. Typically these Web applications are deployed on multiple Linux operating system application servers, using Nginx as the reverse proxy for highly available cluster services. When applying version upgrades, how do you implement a more elegant version update of polymorphic servers?

Problem analysis

Web App updates, I think there are a couple of things that might need to be considered:

    1. The compiled application binary files and configuration files are uploaded to the server;
    2. The application server can sense that there is a new version upload;
    3. In the absence of a service stop, the hot update version;
    4. It is best to have all of the update procedures scripted to reduce manual operation errors.

Scheme

In fact, there are some open source projects in the go community that can automatically detect changes in Web applications and automate updates, but these applications are detecting source code, resource file updates, starting the build process, enabling automatic compilation and restart, such as gin and fresh, which are suitable for use in the development and testing phases, may not be suitable for application deployment and updates, but it provides a good idea.

Deployment Environment directory and version of the upload I will publish the application binaries and configuration files, stored in a directory, such as ~/app/release, each version is retained in this directory, such as app.1.0, app.1.1, app.2.0, once found a problem, can be timely rollback. Also, under the ~/app directory, use the soft link file to point to the latest version, such as

ln -s ~/app/release/app.2.0 ~/app/app.bin

Also, use a text file that is saved under ~/app/release to indicate the current version of the app, such as current.conf:

{    "bin.file": "~/app/release/app.2.0",    "cfg.file": "~/app/release/cfg.2.0"}

When you need to update the version of the server, you can invoke the SCP through a script, upload the new version to the release directory, and then update the current.conf file. Monitor the current.conf file, learn that the version update current.conf file is the current version, once this file changes, that is, the version needs to be updated (or rolled back), we only need to monitor the change of this file, once the change, then do the corresponding processing. The monitoring of files can be achieved by fsnotify.

func watch() {    watcher, err := fsnotify.NewWatcher()    if err != nil {        logger.Fatal(err)    }    defer watcher.Close()    go func() {        for {                select {                case event := <-watcher.Events:                    logger.Println("event:", event)                    if event.Op&fsnotify.Write == fsnotify.Write {                        logger.Println("notify runner to do the ln -s and restart server.")                        restartChan <- true                    }                case err := <-watcher.Errors:                    logger.Println("error:", err)            }        }    }()    err = watcher.Add("/path/to/current.conf")    if err != nil {        logger.Fatal(err)    }    <- make(chan bool)}

After restarting the service to monitor changes to the current.conf file, the next step is to restart the service. In order for the service to be uninterrupted and gracefully restarted, endless can be used to replace the listenandserve of the standard library net/http:

 n := negroni.New()    n.Use(middleware.NewRecovery())    n.Use(middleware.NewMaintainMiddleware())    n.Use(middleware.NewLogMiddleware())    n.Use(middleware.NewStatic(http.Dir("static")))    n.UseHandler(router.NewRouter())    log.Fatal(endless.ListenAndServe(":3000", n))

After the current.conf change, first point the soft link file under ~/app to the latest version, and then use

kill -HUP

Notifies the app to restart.

Func run () {for {<-Restartchan c, err: = Ioutil. ReadFile ("/path/to/current.conf") if err! = Nil {logger. PRINTLN ("current.conf read error:", err) return} var j interface{} Err = json. Unmarshal (c, &j) if err! = Nil {logger.        Println ("Current.conf Parse Error:", err) return} parsed, OK: = J. (map[string]interface{}) If!ok {logger. Println ("Current.conf Parse error:mapping errors") return} exec. Command ("rm", "App.bin"). Run () exec. Command ("ln", "-S", parsed["Bin.file"]. ( String), "App.bin"). Run () exec. Command ("rm", "app.conf"). Run () exec. Command ("ln", "-S", parsed["Cfg.file"]. ( String), "App.cfg"). Run () If!started {cmd: = exec. Command ("./app.bin", "-C", "app.cfg") started = true} else {processes, _: = PS.  Processes () for _, V: = Range Processes {              If strings. Contains (V.executable (), parsed["Bin.file"]) {process, _: = OS. Findprocess (V.pid ()) process. Signal (Syscall. SIGHUP)}}}}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.