#sockets #go #goroutine
#сокеты #Вперед #goroutine
Вопрос:
полный код можно загрузить по адресу https://groups.google.com/forum /#!topic/golang-nuts/e1Ir__Dq_gE
Может ли кто-нибудь помочь мне улучшить этот пример кода до нулевой ошибки? Я думаю, это поможет нам разработать клиент / серверный код без ошибок.
мои шаги по разработке:
- Создайте сервер, который мог бы обрабатывать несколько подключений с помощью goroutine.
- Создайте клиент, который отлично работает с простым протоколом.
- Разверните клиент для имитации нескольких клиентов (с параметром -n = 1000 клиентов по умолчанию)
- ЗАДАЧА: попытаться уменьшить блокировку сервера
- ЗАДАЧА: попробуйте использовать bufioдля увеличения пропускной способности
Я обнаружил, что этот код очень нестабилен и содержит три проблемы:
- запустите 1000 клиентов, у одного из них возникает ошибка EOF при чтении с сервера.
- запускаю 1050 клиентов, слишком много открытых файлов в ближайшее время (ни один клиент не открылся).
-
запуск 1020 клиентов, ошибка во время выполнения с длинными стеками трассировки.
Start pollServer: pipe: too many open files panic: runtime error: invalid memory address or nil pointer dereference [signal 0xb code=0x1 addr=0x28 pc=0x4650d0]
Здесь я вставляю свой более упрощенный код.
const ClientCount = 1000
func main() {
srvAddr := "127.0.0.1:10000"
var wg sync.WaitGroup
wg.Add(ClientCount)
for i := 0; i < ClientCount; i {
go func(i int) {
client(i, srvAddr)
wg.Done()
}(i)
}
wg.Wait()
}
func client(i int, srvAddr string) {
conn, e := net.Dial("tcp", srvAddr)
if e != nil {
log.Fatalln("Err:Dial():", e)
}
defer conn.Close()
conn.SetTimeout(proto.LINK_TIMEOUT_NS)
defer func() {
conn.Close()
}()
l1 := proto.L1{uint32(i), uint16(rand.Uint32() % 10000)}
log.Println(conn.LocalAddr(), "WL1", l1)
e = binary.Write(conn, binary.BigEndian, amp;l1)
if e == os.EOF {
return
}
if e != nil {
return
}
// ...
}
Комментарии:
1. Этот сайт может быть полезен. В нем дается подробный обзор с примерами сетевого кода в Go: jan.newmarch.name/go
2. На какой операционной системе вы запускаете клиент / сервер?
3. Проблема № 2, вероятно, вызвана ограничением на 1024 файловых дескриптора в вашей операционной системе. Также вы откладываете соединение. Дважды закрыть (), что может быть проблемой.
4. @RCE, спасибо, я уверен, что проблема № 2 вызвана ulimit -n 1024. Я удалил соединение defer. Ошибка Close () дважды, но она не может получить никакой помощи в этой проблеме.
5. Каким будет протокол? Действительно ли необходимо, чтобы одновременно было открыто так много сокетов? У вас будут системные ресурсы, используемые для каждого из этих открытых сокетов.
Ответ №1:
Этот ответ на serverfault [1] предполагает, что для серверов, которые могут обрабатывать большое количество подключений, необходимо установить более высокий ulimit. Также проверьте приложения на утечки памяти или файловых дескрипторов с помощью lsof.
ulimit -n 99999