"Go language implements the server to receive HTTP requests and the solution when a leak occurs"

Source: Internet
Author: User
Tags prepare

I. Implementation of the basic procedures

At first, the program was implemented like this:

//hellopackage Mainimport ("Database/sql" "FMT" "Io/ioutil" "Log" "Net/http" "Strings" "Time"    _ "Github.com/go-sql-driver/mysql") Func main () {FMT. Println (time. Now (). Format ("2006-01-02 15:04:05") ) Openhttplisten ()//Savetodb ()}func Openhttplisten () {http. Handlefunc ("/monkeytest", Receiveclientrequest) fmt. Println ("Go server start running ...") Err:= http. Listenandserve ("1.2.3.4:5555", nil)//The address you are listening to is your own IP and port, for example, you see your IP through the ifconfig is 15.34.67.23, then this will be replaced by this IP, not the other IP, or will be errorifErr! =Nil {log. Fatal ("Listenandserve:", Err)}} Func receiveclientrequest (w http. Responsewriter, R*http. Request) {r.parseform () fmt. Println ("Received client request:", R.form) fmt. Println ("Method:", R.method) fmt. Println ("Path:", R.url. Path) fmt. Println ("Scheme:", R.url. Scheme) fmt. Println ("url", R.url) for K, V:=range R.form {fmt. Printf ("----------\ n") fmt. Println ("Key:", K) fmt. Println ("Value:", strings. Join (V, ",") } var className string var pkgname string var pkgver string var leakroot string var Leakdetail st Ring var pkgbuildtime stringifLen (r.form["ClassName"]) > 0{className= r.form["ClassName"][0]    }    ifLen (r.form["Pkgname"]) > 0{pkgname= r.form["Pkgname"][0]    }    ifLen (r.form["Pkgver"]) > 0{pkgver= r.form["Pkgver"][0]    }    ifLen (r.form["Leakroot"]) > 0{leakroot= r.form["Leakroot"][0]    }    ifLen (r.form["Leakdetail"]) > 0{Leakdetail= r.form["Leakdetail"][0]    }    ifLen (r.form["Buildtime"]) > 0{pkgbuildtime= r.form["Buildtime"][0]} body, _:=Ioutil. ReadAll (r.body)//r.body.close () Body_str:=string (body) fmt. Println ("Body_str:", Body_str) fmt. Println ("Header", R.header)Fmt. Println ("Customerid", R.header.get ("Customerid") ) W.header (). Set ("Access-control-allow-origin", "Origin") var result stringifLen (leakdetail)! = 0{result=Savetodb (ClassName, Pkgname, Pkgver, Leakroot, Leakdetail, Pkgbuildtime)} else {result= "Error"} fmt. fprintf (w, result)}func Savetodb (ClassName string, pkgname string, pkgver string, leakroot string, leakdetail string, PKGB Uildtime string) string {db, err:= SQL. Open ("MySQL", "Username:[email Protected] (2.3.4.5:3306)/myku?charset=utf8")//The database to be replaced by its own user name: password @ Database address: Port/Database name Checkerr (ERR)ifErr! =Nil {return"Error"    }    //Insert Data stmt, err:= db. Prepare ("Insert MyTable SET classname=?,pkgname=?,pkgver=?,leakroot=?,leakdetail=?,leakdate=?,pkgbuildtime=?"))//The mytable here replace their table namestmt, err: = db. Prepare ("INSERT INTO mytable (classname,pkgname,pkgver,leakroot,leakdetail,leakdate,pkg) VALUES (?,?,?,?,?,?)")    Rows, err: = db. Query ("SELECT * FROM MyTable") Checkerr (err)ifErr! =Nil {return"Error"    }    /*FMT. Println ("Res.", rows) for rows. Next () {var className string rows. Columns () Err = rows. Scan (&classname) checkerr (err) fmt. Println (className)}*///Checkerr (Err) res, err:= stmt. Exec (ClassName, Pkgname, Pkgver, Leakroot, Leakdetail, time. Now (). Format ("2006-01-02 15:04:05"), Pkgbuildtime) fmt. Println ("Res.", Res)ifErr! =Nil {return"Error"} else {return"Success"}}func Checkerr (err error) {ifErr! =Nil {fmt. Println ("Error.")        //Panic (Err)}}

Later because the hint exists too many open files problem, did a revision, changed to:

//hellopackage Mainimport ("Database/sql" "FMT" "Io/ioutil" "Log" "Net/http" "Strings" "Time"    _ "Github.com/go-sql-driver/mysql") Func main () {FMT. Println (time. Now (). Format ("2006-01-02 15:04:05") ) Openhttplisten ()//Savetodb ()}func Openhttplisten () {srv:= &http. server{Addr:"1.2.3.4:5555", ReadTimeout:5 *Time . Second, WriteTimeout:10 *Time . Second,} http. Handlefunc ("/monkeytest", Receiveclientrequest) fmt. Println ("Go server start running ...") Err:=srv. Listenandserve ()ifErr! =Nil {log. Fatal ("Listenandserve:", Err)}} Func receiveclientrequest (w http. Responsewriter, R*http. Request) {r.parseform () fmt. Println ("Received client request:", R.form) fmt. Println ("Method:", R.method) fmt. Println ("Path:", R.url. Path) fmt. Println ("Scheme:", R.url. Scheme) fmt. Println ("url", R.url) for K, V:=range R.form {fmt. Printf ("----------\ n") fmt. Println ("Key:", K) fmt. Println ("Value:", strings. Join (V, ",") } var className string var pkgname string var pkgver string var leakroot string var Leakdetail st Ring var pkgbuildtime stringifLen (r.form["ClassName"]) > 0{className= r.form["ClassName"][0]    }    ifLen (r.form["Pkgname"]) > 0{pkgname= r.form["Pkgname"][0]    }    ifLen (r.form["Pkgver"]) > 0{pkgver= r.form["Pkgver"][0]    }    ifLen (r.form["Leakroot"]) > 0{leakroot= r.form["Leakroot"][0]    }    ifLen (r.form["Leakdetail"]) > 0{Leakdetail= r.form["Leakdetail"][0]    }    ifLen (r.form["Buildtime"]) > 0{pkgbuildtime= r.form["Buildtime"][0]} defer r.body.close () Body, _:=Ioutil. ReadAll (r.body)//r.body.close () Body_str:=string (body) fmt. Println ("Body_str:", Body_str) fmt. Println ("Header", R.header)Fmt. Println ("Customerid", R.header.get ("Customerid") ) W.header (). Set ("Access-control-allow-origin", "Origin") var result stringifLen (leakdetail)! = 0{result=Savetodb (ClassName, Pkgname, Pkgver, Leakroot, Leakdetail, Pkgbuildtime)} else {result= "Error"} fmt. fprintf (w, result)}func Savetodb (ClassName string, pkgname string, pkgver string, leakroot string, leakdetail string, PKGB Uildtime string) string {db, err:= SQL. Open ("MySQL", "Username:[email Protected] (2.3.4.5:3306)/myku?charset=utf8") defer db. Close () Checkerr (err)ifErr! =Nil {return"Error"    }    //Insert Data stmt, err:= db. Prepare ("Insert MyTable SET classname=?,pkgname=?,pkgver=?,leakroot=?,leakdetail=?,leakdate=?,pkgbuildtime=?"))    stmt, err: = db. Prepare ("INSERT INTO mytable (classname,pkgname,pkgver,leakroot,leakdetail,leakdate,pkg) VALUES (?,?,?,?,?,?)")    Rows, err: = db. Query ("SELECT * FROM MyTable") Checkerr (err)ifErr! =Nil {return"Error"    }    /*FMT. Println ("Res.", rows) for rows. Next () {var className string rows. Columns () Err = rows. Scan (&classname) checkerr (err) fmt. Println (className)}*///Checkerr (Err) res, err:= stmt. Exec (ClassName, Pkgname, Pkgver, Leakroot, Leakdetail, time. Now (). Format ("2006-01-02 15:04:05"), Pkgbuildtime) fmt. Println ("Res.", Res)ifErr! =Nil {return"Error"} else {return"Success"}}func Checkerr (err error) {ifErr! =Nil {fmt. Println ("Error.")        //Panic (Err)}}

Then under Linux through Nohup go run Hello.go &, the program officially ran up, (note: The server IP must be local IP address only) can be entered in the browser:

Http://1.2.3.4:5555/monkeytest, then you can submit the request to the server side of Go

Ii. solutions to problems that arise in go (including the discovery of problems, the process of problem solving)

Once the program is running under Linux, after running through Nohup go run Hello.go &, all the real-time information will be printed to Nohup.out to view this file, this prompt will appear:

2017/07/28 01:51:35 http:accept error:accept tcp 10.252.149.243:9090:accept4:too many open files; Retrying in 5ms

2017/07/28 01:51:35 http:accept error:accept tcp 10.252.149.243:9090:accept4:too many open files; Retrying in 10ms

2017/07/28 01:51:35 http:accept error:accept tcp 10.252.149.243:9090:accept4:too many open files; Retrying in 20ms

2017/07/28 01:51:35 http:accept error:accept tcp 10.252.149.243:9090:accept4:too many open files; Retrying in 40ms

2017/07/28 01:51:35 http:accept error:accept tcp 10.252.149.243:9090:accept4:too many open files; Retrying in 80ms

2017/07/28 01:51:35 http:accept error:accept tcp 10.252.149.243:9090:accept4:too many open files; Retrying in 160ms

2017/07/28 01:51:35 http:accept error:accept tcp 10.252.149.243:9090:accept4:too many open files; Retrying in 320ms

2017/07/28 01:51:35 http:accept error:accept tcp 10.252.149.243:9090:accept4:too many open files; Retrying in 640ms

2017/07/28 01:51:36 http:accept error:accept tcp 10.252.149.243:9090:accept4:too many open files; retrying in 1s

2017/07/28 01:51:37 http:accept error:accept tcp 10.252.149.243:9090:accept4:too many open files; retrying in 1s

In this case, the content that is written to the database cannot be written to.

Because: Under Linux everything is a file, all whether the nohup.out or socket connection is a file, so here can be found in the current PID of the number of files, you can use the following 2 (2) To view the number of files and the details of a PID

After searching, it is found that this can be mitigated in the following ways, first through:

1, ulimit-n View the maximum number of connections, if it is 1024, you can try to modify it to 4096

2, this can not fundamentally solve the problem, continue to check:

(1) Too many open files, whether the file handle leaks, or: The DB operation has a leak, then whether the program is not closed?

After viewing, it does not close, so increase: defer db.close () and defer f.close () processing

The meaning of the defer here is that the delegate performs a shutdown before return, but has drawbacks, especially when used with named return parameters, specifically: https://tiancaiamao.gitbooks.io/go-internals/content/ This is described in the zh/03.4.html article:

The procedure for returning a function is to assign a value to the return value first, then call the defer expression, and finally return to the calling function.

In fact, the reason is: return xxx is not an atomic directive

However, because the close operation does not increase the return parameter, so the effect is not very likely to use

(2) Then after the modification, restart the program, and constantly create the connection database and open file processing operations:

Use the following command:

First get the PID value of Go: PS aux | grep go, for example, results are: 29927

Then execute: ls-l/proc/29927/fd/| Wc-l, the result is: 6, indicating that the number of sockets has not increased

Then execute: ls-l/proc/29927/fd/, get the result is: the current process open the number of connections information details

Note: The number of sockets increases with HTTP requests and database connections before the defer close () operation is not increased in (1)

Follow up here to see if the issue is completely resolved.

"Go language implements the server to receive HTTP requests and the solution when a leak occurs"

Related Article

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.