Server-side Go program for the processing of long and long links and the preservation of running parameters _golang

Source: Internet
Author: User
Tags key string readfile set time socket server port

Processing strategy for long and short connections (analog heartbeat)
as a server that may interact with many of the client's, the first thing to ensure is the stability of the entire server's running state, so it is important to ensure a timely disconnect when connecting to the client, Otherwise, once you have a long connection with multiple clients that does not shut down, it is scary to take up server resources. Therefore, we need to set different restriction policies for short and long connections that may occur.
For short connections, we can use the timeout function with Golang in the net package, a total of three, respectively:

Copy Code code as follows:

Func (*ipconn) setdeadline
Func (c *ipconn) Setdeadline (t time. Time) Error

Func (*ipconn) setreaddeadline
Func (c *ipconn) Setreaddeadline (t time. Time) Error

Func (*ipconn) setwritedeadline
Func (c *ipconn) Setwritedeadline (t time. Time) Error

If you want to set a short connection to the server timeout, we can write this:

Copy Code code as follows:

Netlisten, err: = Net. Listen ("TCP", Port)
Log ("Waiting for Clients")
for {
Conn, err: = Netlisten.accept ()
If Err!= nil {
Continue
}


Conn. Setreaddeadline (time. Now (). ADD (time. Duration * time. Second))
The three functions here are used to set the maximum length of time each socket connection can be maintained, and the connection is automatically disconnected at the server end once the set timeout is exceeded. where Setreadline, Setwriteline sets the maximum duration of read and write, while Setdeadline contains Setreadline, setwriteline two functions.
By this setting, each client connection with the server will not be longer than 10s.

After the short connection, the next is for the long connection processing strategy ~ ~
As a long connection, because it is often difficult to determine when the connection will be interrupted, so it is not as simple as dealing with a short connection to set a timeout can be done, and in the Golang net package, there is no function for long connections, Therefore, we need to design and implement the processing strategy for long connection.
For Socke long connections, it is common practice to design a communication mechanism between the server and the socket, and when there is no information interaction between the two, a packet (heartbeat) is sent periodically to maintain the connection state.

This approach is currently using a relatively large number of practices, but relatively expensive, especially when the server and multiple client maintain long connection, concurrency is relatively high, taking into account the business needs of the company, I finally chose a relatively simple logic, relatively low cost strategy:
Every time the server receives the information that the client sends, it starts the heartbeat and disconnects the client if it does not receive the client's message again before the heartbeat is finished. Once you receive the message from the client again within the set time, the server resets the timer and restarts the heartbeat again until the timeout is disconnected.
The following is the code that implements the timing:

Copy Code code as follows:

Long connection Entrance
Func handleconnection (Conn net. Conn,timeout int) {

Buffer: = Make ([]byte, 2048)
for {
N, err: = conn. Read (buffer)

If Err!= nil {
LOGERR (Conn. Remoteaddr (). String (), "Connection error:", err)
Return
}
Data: = (Buffer[:n])
Messnager: = Make (chan byte)
POSTDA: =make (chan byte)
Heartbeat timing
Go heartbeating (conn,messnager,timeout)
To detect whether any data is coming from the client.
Go Gravelchannel (Data,messnager)
Log ("Receive Data length:", N)
LOG (Conn. Remoteaddr (). String (), "Receive data string:", String (data

}
}

Heartbeat timing, according to Gravelchannel to determine whether the client in the set time to send information
Func heartbeating (Conn net. Conn, Readerchannel chan byte,timeout int) {
Select {
Case FK: = <-readerchannel:
LOG (Conn. Remoteaddr (). String (), "Receive data string:", String (FK))
Conn. Setdeadline (time. Now (). ADD (time. Duration (Timeout) * time. Second))
Conn. Setreaddeadline (time. Now (). ADD (time. Duration (5) * time. Second))
Break
Case <-time. After (time). SECOND*5):
Log ("It ' s really weird to get nothing!!!")
Conn. Close ()
}

}

Func Gravelchannel (n []byte,mess Chan byte) {
For _, V: = Range n{
Mess <-V
}
Close (Mess)
}


Func Log (v... interface{}) {
Log. Println (v ...)
}

In this way, we can successfully implement the processing of long connections ~ ~, we can do this test:

Func Sender (Conn net. Conn) {
For I: = 0; I <5; i++ {
Words:= StrConv. Itoa (i) + "This are a test for long conn"
Conn. Write ([]byte (words))
Time. Sleep (2*time. Second)

}
Fmt. PRINTLN ("Send Over")

}


can be found, When the Time.sleep blocking time in the sender function is shorter than the timeout in the server, the client-side information can be freely sent to the end of the loop, and when we set the sender function to block for a long time, we can only emit the first loop of information.


put the run parameters into the configuration file (Xml/yaml)
in order to publish our written server to the server, we need to build our code into a package, so that if you want to modify some of the code later, it is necessary to compile the code to package and upload to the server.

Obviously, this is too cumbersome ... Therefore, it is common practice to write variables and numeric values to the configuration file that may change frequently in the running of the server, so that the program can read the parameters from the configuration file directly to avoid frequent operation of the code.

About the format of the configuration file, here recommend Yaml and xml~ XML is the traditional configuration file, but I recommend Yaml, he is more humane than XML, also better write, about Yaml details can refer to: YAML official website

For example, we can use the server listening to the port as a variable, write the configuration file Config.yaml and Config.xml, into the root of the code, so that when we want to replace the server port, as long as the configuration file to modify the value of the port can be pulled. Config.xml contents are as follows:

<?xml version= "1.0" encoding= "UTF-8"?> 
<Config1>GetConfig</Config1> 
<config2>the </Config2> 
<Config3>Information</Config3> 
<feature1>hereistest1</feature1 > 
<Feature2>1024</Feature2> 
<Feature3>Feature23333</Feature3> 

Config.yaml contents are as follows:

address:172.168.0.1 
config1:easy 
Config2: 
 feature1:2 
 Feature2: [3, 4] 
Port:: 6060 
Config4:is 
Config5:atest 


The next step is to parse them, the current Golang official has not yet resolved the YAML library, so I recommend the use of Third-party Go-yaml package,
The address is as follows: Go-yaml, after we install the package, we can parse the file through him:

Copy Code code as follows:

Parse file, remove all parameters
Func getyamlconfig () map[interface{}]interface{}{

Data, err: = Ioutil. ReadFile ("Config.yaml")
Convert the parsed parameters to map
M: = Make (map[interface{}]interface{})
If Err!= nil {
LogErr ("Error:%v", err)
}
Err = Yaml. Unmarshal ([]byte (data), &m)

return m
}
Take out the corresponding value according to the requirement
Func getelement (Key String,themap map[interface{}]interface{}) string {
If Value,ok:=themap[key];ok {
return value. (string)
}

LogErr ("Can ' t find the *.yaml")
Return ""
}


This also gives the code to parse the XML configuration file:

Copy Code code as follows:

Func getxmlconfig () map[string]string {

var t xml. Token
var err error

Keylst: = make ([]string,6)
Valuelst:=make ([]string,6)
Fills the parsed elements into a map for easy lookup
Map1:=make (map[string]string)
Content, Err: = Ioutil. ReadFile ("Config.xml")
CheckError (ERR)
Decoder: = XML. Newdecoder (bytes. Newbuffer (content))

I:=0
J:=0
For T, err = decoder. Token (); Err = = Nil; T, Err = decoder. Token () {

Switch token: = T. (type) {
Processing elements
Case XML. Startelement:

Name: = token. Name.local
Keylst[i]=string (name)
I=i+1

Case XML. Chardata:
Content1: = String ([]byte (token))
Valuelst=append (VALUELST,CONTENT1)
Valuelst[j]=content1
J=j+1

}
}
For Count:=0;count<len (KEYLST); count++{
Map1[keylst[count]]=valuelst[count]
}

Return MAP1
}
The function to take out the map is similar to that in Yaml, skip here


The operation effect is as follows:

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.