поезд pio завершается с ошибкой IOException: сброс соединения узлом

Я выполнил настройку PredictionIO v0.13 на своей Linux-машине в докере (работает в режиме роя). Эта установка включает в себя:

  • один контейнер для pio v0.13
  • один контейнер для elasticsearch v5.6.4
  • один контейнер для mysql v8.0.16
  • один контейнер для spark-master v2.3.2
  • один контейнер для spark-worker v2.3.2

Я использую шаблон ecomm-recommender-java, модифицированный для моих данных. Я не знаю, ошибся ли я с шаблоном или с настройкой докера, но что-то действительно не так:

  1. сборка пио прошла успешно
  2. pio train не работает - с исключением в потоке "main" java.io.IOException: сброс соединения одноранговым узлом

Из-за этого я вложил в свой шаблон много логирования по разным точкам, и вот что нашел:

  • Поезд выходит из строя после расчета модели. Я использую собственный класс Model для хранения модели логистической регрессии и различных индексов пользователей и продуктов.
  • Модель PersistentModel. В методе сохранения я ставлю логирование после каждого шага. Они регистрируются, и я могу найти сохраненные результаты в смонтированном томе докера, поэтому кажется, что сохранение также завершается успешно, но после этого я получаю следующее исключение:
[INFO] [Model] saving user index
[INFO] [Model] saving product index
[INFO] [Model] save done
[INFO] [AbstractConnector] Stopped Spark@20229b7d{HTTP/1.1,[http/1.1]}{0.0.0.0:4040}
Exception in thread "main" java.io.IOException: Connection reset by peer
    at sun.nio.ch.FileDispatcherImpl.read0(Native Method)
    at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:39)
    at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)
    at sun.nio.ch.IOUtil.read(IOUtil.java:197)
    at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:380)
    at org.apache.predictionio.shaded.org.apache.http.impl.nio.reactor.SessionInputBufferImpl.fill(SessionInputBufferImpl.java:204)
    at org.apache.predictionio.shaded.org.apache.http.impl.nio.codecs.AbstractMessageParser.fillBuffer(AbstractMessageParser.java:136)
    at org.apache.predictionio.shaded.org.apache.http.impl.nio.DefaultNHttpClientConnection.consumeInput(DefaultNHttpClientConnection.java:241)
    at org.apache.predictionio.shaded.org.apache.http.impl.nio.client.InternalIODispatch.onInputReady(InternalIODispatch.java:81)
    at org.apache.predictionio.shaded.org.apache.http.impl.nio.client.InternalIODispatch.onInputReady(InternalIODispatch.java:39)
    at org.apache.predictionio.shaded.org.apache.http.impl.nio.reactor.AbstractIODispatch.inputReady(AbstractIODispatch.java:114)
    at org.apache.predictionio.shaded.org.apache.http.impl.nio.reactor.BaseIOReactor.readable(BaseIOReactor.java:162)
    at org.apache.predictionio.shaded.org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:337)
    at org.apache.predictionio.shaded.org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:315)
    at org.apache.predictionio.shaded.org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:276)
    at org.apache.predictionio.shaded.org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:104)
    at org.apache.predictionio.shaded.org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:588)
    at java.lang.Thread.run(Thread.java:748)

Я не смог найти ничего более подходящего ни в одном из журналов, но есть вероятность, что я что-то упустил из виду.

Я пробовал играть с параметрами поезда так: pio-docker train -- --master local[3] --driver-memory 4g --executor-memory 10g --verbose --num-executors 3

  • игра с режимами искры (т. е.: --master local[1-3] и не предоставление этого для использования экземпляров в контейнерах докеров)
  • играл с --driver-memory (от 4g до 10g)
  • играл с --executor-memory (также с 4g до 10g)
  • играл с номером --num-executors (от 1 до 3)

Так как большинство результатов поиска Google предлагают это. Моя главная проблема здесь в том, что я не знаю, откуда это исключение и как его обнаружить.

Вот сохранение и метод, который может иметь значение:

    public boolean save(String id, AlgorithmParams algorithmParams, SparkContext sparkContext) {
        try {
            logger.info("saving logistic regression model");
            logisticRegressionModel.save("/templates/" + id + "/lrm");
            logger.info("creating java spark context");
            JavaSparkContext jsc = JavaSparkContext.fromSparkContext(sparkContext);
            logger.info("saving user index");
            userIdIndex.saveAsObjectFile("/templates/" + id + "/indices/user");
            logger.info("saving product index");
            productIdIndex.saveAsObjectFile("/templates/" + id + "/indices/product");
            logger.info("save done");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return true;
    }

Жестко закодированный /templates/ — это смонтированный в докере том для pio, а также для spark.

Ожидаемый результат: поезд завершается без ошибок. Я рад поделиться более подробной информацией, если это необходимо, пожалуйста, запросите их, так как я не уверен, что здесь может быть полезно.

EDIT1: включая docker-compose.yml

version: '3'

networks:
    mynet:
        driver: overlay

services:

    elasticsearch:
        image: docker.elastic.co/elasticsearch/elasticsearch:5.6.4
        environment:
          - xpack.graph.enabled=false
          - xpack.ml.enabled=false
          - xpack.monitoring.enabled=false
          - xpack.security.enabled=false
          - xpack.watcher.enabled=false
          - cluster.name=predictionio
          - bootstrap.memory_lock=false
          - "ES_JAVA_OPTS=-Xms1g -Xmx1g"
        volumes:
          - pio-elasticsearch-data:/usr/share/elasticsearch/data
        deploy:
            replicas: 1
        networks:
            - mynet

    mysql:
        image: mysql:8
        command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
        environment:
          MYSQL_ROOT_PASSWORD: somepass
          MYSQL_USER: someuser
          MYSQL_PASSWORD: someotherpass
          MYSQL_DATABASE: pio
        volumes:
          - pio-mysql-data:/var/lib/mysql
        deploy:
            replicas: 1
        networks:
            - mynet

    spark-master:
        image: bde2020/spark-master:2.3.2-hadoop2.7
        ports:
          - "8080:8080"
          - "7077:7077"
        volumes:
            - ./templates:/templates
        environment:
          - INIT_DAEMON_STEP=setup_spark
        deploy:
            replicas: 1
        networks:
            - mynet

    spark-worker:
        image: bde2020/spark-worker:2.3.2-hadoop2.7
        depends_on:
          - spark-master
        ports:
          - "8081:8081"
        volumes:
            - ./templates:/templates
        environment:
          - "SPARK_MASTER=spark://spark-master:7077"
        deploy:
            replicas: 1
        networks:
            - mynet

    pio:
        image: tamassoltesz/pio0.13-spark.230:1
        ports:
            - 7070:7070
            - 8000:8000
        volumes:
            - ./templates:/templates
        dns: 8.8.8.8
        depends_on:
          - mysql
          - elasticsearch
          - spark-master
        environment:
          PIO_STORAGE_SOURCES_MYSQL_TYPE: jdbc
          PIO_STORAGE_SOURCES_MYSQL_URL: "jdbc:mysql://mysql/pio"
          PIO_STORAGE_SOURCES_MYSQL_USERNAME: someuser
          PIO_STORAGE_SOURCES_MYSQL_PASSWORD: someuser
          PIO_STORAGE_REPOSITORIES_EVENTDATA_NAME: pio_event
          PIO_STORAGE_REPOSITORIES_EVENTDATA_SOURCE: MYSQL
          PIO_STORAGE_REPOSITORIES_MODELDATA_NAME: pio_model
          PIO_STORAGE_REPOSITORIES_MODELDATA_SOURCE: MYSQL
          PIO_STORAGE_SOURCES_ELASTICSEARCH_TYPE: elasticsearch
          PIO_STORAGE_SOURCES_ELASTICSEARCH_HOSTS: predictionio_elasticsearch
          PIO_STORAGE_SOURCES_ELASTICSEARCH_PORTS: 9200
          PIO_STORAGE_SOURCES_ELASTICSEARCH_SCHEMES: http
          PIO_STORAGE_REPOSITORIES_METADATA_NAME: pio_meta
          PIO_STORAGE_REPOSITORIES_METADATA_SOURCE: ELASTICSEARCH
          MASTER: spark://spark-master:7077 #spark master
        deploy:
            replicas: 1
        networks:
            - mynet

volumes:
    pio-elasticsearch-data:
    pio-mysql-data:

person tamassoltesz    schedule 03.05.2019    source источник
comment
Добро пожаловать в StackOverflow! ИМХО - это скорее проблема с сетью, чем с кодом. Конечно, ваша сеть находится в сценариях Docker, так что это код! Не могли бы вы включить свой файл docker-compose.yml или аналогичный пример? Это должно помочь выявить сетевые проблемы между контейнерами.   -  person rbrtl    schedule 03.05.2019
comment
Благодарю вас! Я отредактировал вопрос, вы можете найти там файл docker-compose   -  person tamassoltesz    schedule 03.05.2019
comment
Я ни в коем случае не эксперт в Docker, но мне нужно его изучить, поэтому любая отговорка хороша. Глядя на файл docker-compose, меня смущают имена хостов: откуда каждый из ваших контейнеров знает, как называются другие? - "SPARK_MASTER=spark://spark-master:7077" как эта строка указывает на главный контейнер искры?   -  person rbrtl    schedule 03.05.2019
comment
В режиме роя докер выполняет балансировку нагрузки для служб, а также обнаружение. Короче говоря, они могут найти друг друга, потому что все они являются частью одной и той же сети (mynet в примере), а имя службы spark-master — spark-master.   -  person tamassoltesz    schedule 03.05.2019
comment
Только что нашел документы для сетевых ссылок ???? быстрая проверка работоспособности: нужны ли вам кавычки вокруг переменной среды MASTER в контейнере pio?   -  person rbrtl    schedule 03.05.2019
comment
Я не уверена. Попробую без этого.   -  person tamassoltesz    schedule 03.05.2019
comment
Нет, цитаты не нужны.   -  person tamassoltesz    schedule 03.05.2019
comment
Привет, Томас, я не вижу строку журнала для SparkContext. Это было успешно создано? Я знаю меньше о Spark, чем о Docker (я действительно надеялся, что кто-то уже придет на помощь), но эта переменная jsc, похоже, не используется. В этих документах упоминаются новые контексты, создающие сервер веб-интерфейса — это единственное отношение Я добрался до порта :4040 в вашем списке журналов   -  person rbrtl    schedule 03.05.2019
comment
@rbrtl, вы правы, это jsc нигде не используется. Это просто остатки попытки решить эту же проблему. Во всяком случае, да, этот sparkContext создается, все из моего save регистрируется. Более того, теперь я уверен, что упомянутое исключение не происходит из e.printStackTrace() предложения catch, так как я добавляю больше логов в предложение catch, и я не вижу этих строк журнала, но я все еще вижу исключение.   -  person tamassoltesz    schedule 03.05.2019


Ответы (1)


Я выяснил, в чем проблема: каким-то образом теряется соединение с elasticsearch во время долгого поезда. Это проблема докера, а не проблема прогнозирования. На данный момент я «решил» это, вообще не используя elasticsearch.

Еще одна вещь, о которой я не знал: не имеет значения, где вы поместите --verbose в команде. Предоставление его так, как я сделал изначально (например, pio train -- --driver-memory 4g --verbose), не влияет/незначительно влияет на подробность ведения журнала. Правильный способ сделать это pio train --verbose -- --driver-memory 4g, поэтому перед --. Таким образом, я получил гораздо больше логов, из которых стало ясно происхождение проблемы.

person tamassoltesz    schedule 07.05.2019