Anonymous
Он не подходит мне
Alexander
Тогда покажи, что делает ssh.Scan
Anonymous
Да перезагрузка комп, повесил случайно
Alexander
close(jobs) никогда не выполнится
Канал буферизированный - все задачи влезут.
Anonymous
package ssh import ( "fmt" "net" "time" ) func Scan(thread int, jobs <-chan string, results chan<- string) { for j := range jobs { _, err := net.DialTimeout("tcp", j+":22", 5*time.Second) if err != nil { results <- fmt.Sprintf("Thread %d: %v\n", thread, err) return } results <- fmt.Sprintf("Thread %d: %s port is opened.\n", thread, j) } }
Anonymous
Это вот сама функция scan
Alexander
https://play.golang.org/p/GmCueoKFXIj
Alexander
всё работает как надо
Anonymous
То есть этот код можно считать хорошим?
Anonymous
Просто вопрос был в том, что если у меня хостов например будет миллион, то я же не смогу позволить отработать миллион горутин
Alexander
Да, я сначала не понял, как именно работает ssh.Scan. Но так как он читает задачи из канала, то всё в целом правильно.
Alexander
Я бы только не стал делать канал с таким буфером - это бессмысленно
Michael
и беспощадно
Anonymous
Простой небуфиризированный сделать?
Michael
но когда хочется и колится, то можно
Alexander
Да. Только читающую горутину запусти _сначала_
Anonymous
Почему нет?
Ну я пока не силен в го, вот и решил уточнить) По верному пути ли я иду
Alexander
Можно много горутин 👌
Тут, я думаю, будут проблемы с сетью. Незачем сканировать сеть в миллион потоков.
Anonymous
Alexander
Это правильно, да.
Chebyrash
Я думал у вас миллион коннектов
Anonymous
Всем спасибо, очень помогли) А то сижу со вчера и думаю как реализовать)
Michael
хорошо реализовывать надо) и про балансировку нагрузки на сеть не забывай
Anonymous
А так по честному, не очень у меня на го? Да?
Anonymous
Я просто до этого на питоне бацал
Michael
у всех не очень и все живут
Anonymous
)) Да вот только начал недавно) так в основном по вебу мелочевку всякую писал
Michael
у фастхттп были юзкейсы кмк
Michael
подходит для задач - используй
Michael
не подоходит - не используй
Anonymous
Но я хочу сделать не 254 воркера(w := 0; w < len(hosts); w++), а всего 10
А зачем WorkerGroup когда есть семафоры с помощью которых всегда ограничивались количество одновременно живущих потока? http://jmoiron.net/blog/limiting-concurrency-in-go
Anonymous
А wg на самом деле не очень подходит пока что, сейчас буду думать
Anonymous
Почитаю, посмотрим) Если интересно будет потом могу отписать, как решил это
Michael
запускаю нужное кол-во рутин, они слушают канал с тасками, когда канал закрываю, то и рутины завершаются
Michael
воркеры с манагером общаются аля Task & TaskResult сообщениями
Anonymous
и отслеживать одновременное кол-во запущенных, но не помню почему отмел эту идею
Michael
как наваяешь, лучше код покажи
Michael
кто нить да подскажет
Anonymous
Ну да, наверное так и сделаю, но пока проблем нет вроде
Alexander
WaitGroup (да, я ошибся, когда назвал их WorkerGroup) нужен чтобы не отслеживать количество результатов, а просто дождаться пока все горутины отработают. Вот пример - https://golang.org/pkg/sync/#example_WaitGroup
Anonymous
Это классическая задача решается или через семафоры или через thread pool. По крайней мере в оствльных языках
Alexander
Если сделаешь чтение или запись в отдельной горутине, как я рекомендовал выше (чтобы буфер в канале не делать равным количеству данных), то ожидание завершения работы горутин станет актуальным.
Alexander
Вот с записью в отдельной горутине и канал без буфера - https://play.golang.org/p/E725utf5Et_X
Alexander
Можно сделать наоборот - считывать в отдельной горутине, а записывать в основном потоке
Alexander
Главное - чтобы и запись и чтение работали одновременно
Anonymous
Хм
Anonymous
Ща попробую
Anonymous
Погоди, а вот ожидание завершения у меня происходит же по сути по освобождению данных из канала, то есть то что я сделал запись в отдельной горутине, мало что поменяло вроде, единственное, что к ней нужен будет waitgroup
Anonymous
Или я ошибаюсь?
Anonymous
Ну то есть пока я не освобожу канал полностью, горутина не перестанет работать
Anonymous
Так же?
Anonymous
Я может быть не так что - то понимаю
Michael
в мейне создаю несколько воркеров
Alexander
WaitGroup тут пока не нужен, т.к. всё еще есть подсчет задач. А смысл изменения - убрать буфер у канала и сохранить немного памяти (ну или много)
Michael
а... оптимизируете)
Anonymous
А, понял. Просто еще с объемами данных такими не успел столкнуться, надо бы попробовать поигратьсья с огромным кол-вом данных
Michael
для моих задач работает такой вариант создаём два канала - один для таском, другой для done сообщений или результатов поднимается нужно кол-во горутин при завершении канал с тасками закрывает начинаем вычитывать done сообщения (тут есть блокировка осн потока выполнения) как все отчитались, так и завершаем выполнение
Michael
А, понял. Просто еще с объемами данных такими не успел столкнуться, надо бы попробовать поигратьсья с огромным кол-вом данных
объёмные данные тоже интересный вопрос большие задачи можно побить на поменьше и при этом оставить буфер, если он нужен
Alexander
да
Ну так тоже можно, да. Только WaitGroup же сделан именно для этого.
Michael
Ну да, надо эксперементировать, я совсем недавно начал
могу дать такой совет - старайся делать как можно меньше выделений памяти так как можно упереться в фрагментацию озу и сборщик и средства Го не помогут
Anonymous
Я вот как переделал сейчас
Anonymous
package main import ( "flag" "fmt" "log" "sync" "x/ssh" ) func main() { var wg sync.WaitGroup pool := flag.String("p", "", "IP format 192.168.1.0/24") flag.Parse() // 64.254.32.0/24 hosts, err := ssh.GenerateHosts(*pool) if err != nil { log.Fatalf("[ERROR] %v\n", err) } results := make(chan string, 5) for _, host := range hosts { wg.Add(1) go func(host string) { wg.Done() ssh.Scan(host, results) }(host) } wg.Wait() for i := 0; i < len(hosts); i++ { fmt.Print(<-results) } }
Anonymous
jobs убрал за ненадобностью
Michael
а чего результаты аж на 5?
Anonymous
А да это еще не трогал)
Anonymous
я вот кстати не до конца еще буффер понимаю у канадов
Michael
wg.Done() ssh.Scan(host, results) done после Scan?
Anonymous
ой