golang http Services achieve a smooth restart

package main

import (
	"context"
	"encoding/json"
	"fmt"
	"math/rand"
	"net/http"
	"os"
	"os/signal"
	"time"
)

var logChan  = make(chan map[string]interface{})

var requestStatusMap = map[int]bool{}


var done = make(chan bool, 1)
var quit = make(chan os.Signal, 1)


// Why can smooth restart?
// Under normal circumstances server.ListenAndServe () This location hang around the entire process
// this program can be seen as two parts, one is the listening part of web services, part of a deal, if the web server does not open, then you can not handle the request for a new incoming (can be understood as a leading the way)
// really make this request because the primary process is broken (main) is kill
// so graceful restart the principle is, first kill off the web server, not new requests come in, and so all existing requests over, and then end the current process
func main() {
	server := newServer()
	signal.Notify(quit, os.Interrupt)
	go monitorKill(server, quit)
	server.ListenAndServe()
	<-done
}


func newServer() *http.Server {
	router := http.NewServeMux()
	router.HandleFunc("/hello", sayHello)
	return &http.Server{
		Addr:         ":8262",
		Handler:      router,
	}
}

func monitorKill(server *http.Server, quit <-chan os.Signal)  {
	<-quit
	go shutDown(server)
	for {
		if len(requestStatusMap) != 0 {
			fmt.Println ( "request there are still in progress, please wait")
			time.Sleep(time.Second * 1)
			continue
		} else {
			close(done)
			break
		}
	}
}

func shutDown(server *http.Server) {
	if err := server.Shutdown(context.Background()); err != nil {
		fmt.Println(err)
	}
}

func sayHello(w http.ResponseWriter, r *http.Request) {
	go WriteInfo () // request to write the log
	var uniqueId = GenerateRangeNum(1, 1000)
	requestStatusMap[uniqueId] = false
	url := r.URL.Path
	query  := r.URL.RawQuery
	method := r.Method
	a := map[string] interface{}{
		"url" : url,
		"method" : method,
		"query" : query,
		"response": "hello world!",
	}
	logChan <-a
	w.Write([]byte("hello world!"))
	time.Sleep(time.Second * 10)
	delete(requestStatusMap, uniqueId)
}

func WriteInfo() {
	Info: = <-logChan
	fileName := "/tmp/weekhomework.log"
	_-Er: os.stat = (filename)
	if err != nil || os.IsNotExist(err) {
		_, _ = os.Create(fileName)
	}
	f,err := os.OpenFile(fileName, os.O_WRONLY, 0644)
	defer f.Close()
	if err !=nil {
		fmt.Println(err.Error())
	} else {
		// append mode can not be written O_APPEND Why write? todo
		n, _ := f.Seek(0, 2)
		infostr, _ := json.Marshal(info)
		_,err=f.WriteAt([]byte(string(infostr) +"\n"), n)
	}
}

GenerateRangeNum func (who you are, with you) you {
	if min == max {
		Return min
	}
	rand.Seed(time.Now().Unix())
	randNum: rand.Intn = (max-min) + min
	return randNum
}

  

The main idea: For every request to take notes, do deletion after processing is completed. With a coroutine to monitor the interrupt signal, an interrupt signal first http service turned off.

If this time there is no request has been processed, then wait in rotation, and all processed then given a termination signal the end of the main process execution

Guess you like

Origin www.cnblogs.com/tobemaster/p/11986814.html