Были проблемы с серверной частью, написанной на Php, при отправке более 50 тысяч Push уведомлений. Использовал
ApnsPhp и он очень долго отправлял. Там, как я понял, особенности реализации. Так как немного изучал Go, решил на другой виртуалке поднять простенький сервис на Go, который отправляет Push-уведомления, получая токены по запросу на мой старый сервер. Для отправки использую вот
это.
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)
}
}
}
Функция prepareSendingPush(c) делает HTTP запрос на мой сервер и, если получает токены, то происходит отправка.
Все работает отлично, сервис стучится каждые 30 сек и если надо отправляет уведомления, кстати, отправка происходит за 5 секунд, вместо 150 и более у ApnsPHP. Запускаю так start-stop-daemon -Sbvx /root/go/src/myapp/myapp.
В итоге смотрю через htop сколько ресурсов ест мое приложение. И во-первых наблюдаю, что мое приложение отображается как 6 запущенных процессов. Что это? И во-вторых, что потихоньку количество потребления оперативки начинает расти и расти. Что я делаю не так? На виртуалке стоит Ubuntu 14.04.
Вот код, в комменте нельзя вставить нормально.
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)
}