Answer the question
In order to leave comments, you need to log in
Why is a Go application gradually consuming more and more RAM?
There were problems with the backend written in Php when sending more than 50,000 push notifications. Used ApnsPhp and it took a very long time to send. There, as I understand it, the features of the implementation. Since I studied Go a little, I decided to raise a simple service on Go on another virtual machine, which sends Push notifications, receiving tokens on request to my old server. I use this to send .
func main() {
c, err := apns.NewClientWithFiles(apns.ProductionGateway, "/root/go/src/myapp/resources/pushcert.pem", "/root/go/src/myapp/resources/apnskey.pem")
if err != nil {
addStringToLog(fmt.Sprintf("%s", err))
log.Fatal("Could not create client", err.Error())
}
go func() {
for f := range c.FailedNotifs {
addStringToLog(fmt.Sprintf("Notif", f.Notif.ID, "failed with", f.Err.Error()))
fmt.Println("Notif", f.Notif.ID, "failed with", f.Err.Error())
}
}()
prepareSendingPush(c)
tickChan := time.NewTicker(time.Second * 30).C
for {
select {
case <-tickChan:
prepareSendingPush(c)
}
}
}
func prepareSendingPush(client apns.Client) {
addStringToLog("Start get tokens")
fmt.Printf("Start get tokens")
response, err := http.Get("https://domain.com/gettokens.php")
if err != nil {
addStringToLog(fmt.Sprintf("%s", err))
fmt.Printf("%s", err)
} else {
defer response.Body.Close()
contents, err := ioutil.ReadAll(response.Body)
if err != nil {
addStringToLog(fmt.Sprintf("%s", err))
fmt.Printf("%s", err)
}
type JsonObj struct {
Status string `json:"status"`
Text string `json:"text"`
Tokens []string `json:"tokens"`
}
js := new(JsonObj)
err = json.Unmarshal(contents, &js)
if err != nil {
addStringToLog(fmt.Sprintf("%s", err))
fmt.Println("error:", err)
}
if len(js.Tokens) > 0 {
addStringToLog("Start sending")
fmt.Printf("Start sending")
for i := 0; i < len(js.Tokens); i++ {
tok := js.Tokens[i]
if tok != "" {
sendPush(client, tok, js.Text, 1, i)
}
}
addStringToLog("End sending")
fmt.Printf("End sending")
}
addStringToLog("End get tokens")
fmt.Printf("End get tokens")
}
}
func sendPush(client apns.Client, token string, body string, badge uint, identifier int) {
p := apns.NewPayload()
p.APS.Alert.Body = body
p.APS.Sound = "default"
p.APS.Badge.Set(badge)
//p.APS.ContentAvailable = 1
m := apns.NewNotification()
m.Payload = p
m.DeviceToken = token
m.Priority = apns.PriorityImmediate
m.Identifier = uint32(identifier)
client.Send(m)
}
Answer the question
In order to leave comments, you need to log in
Keep track of the number of goroutines. Perhaps somewhere they are implicitly created and hang on reading from a channel, for example, to which you forgot to write or which you forgot to close.
This can be done using the runtime module, getting the value runtime.NumGoroutine
The number of processes is usually taken from the number of cores, so you have 6 of them running. To put it simply, the go runtime scatters goroutines between these processes to execute.
sendPush(), preparesendPush()
You pass
functions apns.Client
as a parameter. Go always passes 'copy_by_value' parameters, which means it creates and passes a copy of the client on every call.
apns.Client // contains filtered or unexported fields
, that is, it is not known what is copied and how much it lends itself to the scavenger. Try passing the same client as a referencefunc prepareSendingPush(client *apns.Client), func sendPush(client *apns.Client...
causingprepareSendingPush(&c)
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question