Зачем горутин пауза на несколько минут - PullRequest
0 голосов
/ 26 декабря 2018

У меня есть задача, написанная на GO, для чтения файлов .gz из AWS S3, размер каждого файла .gz будет 20M .

Каждая программа будет загружать файл .gz изs3 на локальный диск, затем прочитайте его содержимое построчно через gzip.NewReader.

Когда число задач (goroutine) превышает 70, 67 goroutine завершит свои операции успешно.Но оставшийся горутин тогда будет приостановлен на несколько минут.

В момент, когда он остановился, я увидел, что ЦП равен 100%, а затем ЦП снизится до 0,2% (4 ЦПУ, 16 ГБ памяти), чтобы остаться на несколько минут.

Вопрос : Я запутался в том, что почему в то время не выполнялось никаких операций с довольно низким ЦП?Чем это может быть вызвано?

Test results:
60 goroutines, it will finish successfully in 27 seconds;
70 goroutines, it will finish successfully in 30s;
80 goroutines, 77 of them will finish successfully in 30s, but the remaining 3 will **pause 4 minutes**, then restart and finish in 10s

Код, указанный ниже:

Основная программа:

    func main() {
      runtime.GOMAXPROCS(runtime.NumCPU()*2)
      chs := make([]chan string, 70)
      for i:=min; i<max; i++ {
          chs[i] = make(chan string, 1)
          go readobj.Reads3obj(i, chs[i])
      }
      for _, ch := range chs {
        fmt.Println(<-ch)
      }
    }

ReadObject:

func Reads3obj(s3KeyName, ch chan string) {
    sess, err := session.NewSession(&aws.Config{
              Region: aws.String("x"),
              Credentials: credentials.NewStaticCredentials("x", "x", "")},)

    downloader := s3manager.NewDownloader(sess)

    //create a zipFile to download from S3 to local
    zipFile, err := os.Create(zipname)

    //download .gz file from S3
    n, err := downloader.Download(zipFile, &s3.GetObjectInput{
        Bucket: aws.String(bucket),
        Key:    aws.String(s3KeyName),
    })
    //create a file reader
    fileReader, err := os.Open(zipFile)

    //create a gzip reader      
    gzipReader, err := gzip.NewReader(fileReader)

    //create a buffered reader
    buf := bufio.NewReader(gzipReader)

    //read zip file line by line
    for line, isPrefix, err := []byte{0}, false, error(nil); len(line) > 0 && err == nil; {
        line, isPrefix, err = buf.ReadLine()
       //insert line to ES
    }
  }

ИЗД.он сделал паузу, количество открытых файлов довольно мало, поэтому я думаю, что количество открытых файлов не превышает большинство, и это не имеет значения.Потому что:

Выход ll /proc/PID/fd равен

zc@ip-xxx:/proc/18059/fd$ ll
total 0
dr-x------ 2 zc zc  0 Dec 26 06:50 ./
dr-xr-xr-x 9 zc zc  0 Dec 26 06:50 ../
lrwx------ 1 zc zc 64 Dec 26 06:50 0 -> /dev/pts/0
lrwx------ 1 zc zc 64 Dec 26 06:50 1 -> /dev/pts/0
lrwx------ 1 zc zc 64 Dec 26 06:50 12 -> 
/home/zc/75.gz
lrwx------ 1 zc zc 64 Dec 26 06:50 2 -> /dev/pts/0
lrwx------ 1 zc zc 64 Dec 26 06:50 21 -> 
/home/zc/78.gz
lrwx------ 1 zc zc 64 Dec 26 06:50 253 -> socket:[76054]
lrwx------ 1 zc zc 64 Dec 26 06:50 280 -> socket:[77064]
lrwx------ 1 zc zc 64 Dec 26 06:50 47 -> 
/home/zc/58.gz
lrwx------ 1 zc zc 64 Dec 26 06:50 65 -> anon_inode:[eventpoll]
lrwx------ 1 zc zc 64 Dec 26 06:50 93 -> socket:[75984]

1 Ответ

0 голосов
/ 26 декабря 2018

Golang GZIP библиотека читает файл в одной процедуре,

Таким образом, большой файл долго занимает процессор на 100%.Используйте взамен pzip .

Используйте вместо gzip, замените

  import "compress/gzip" 

на

 import gzip "github.com/klauspost/pgzip".
...