javaapache-sparkdocker-swarmpredictionio

pio train fails with IOException: Connection reset by peer


I've done a setup of predictionIO v0.13 on my linux machine in docker (running in swarm mode). This setup includes:

The template I am using is the ecomm-recommender-java, modified for my data. I don't know if I made an error with the template or with the docker setup, but there is something really wrong:

  1. pio build succeeds
  2. pio train fails - with Exception in thread "main" java.io.IOException: Connection reset by peer

Because of this, I put a lot of logging into my template for various points, and this is what I found:

[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)

I couldn't find any more relevant in any of the logs, but that's a possibility that I overlooked something.

I tried to play with the train parameters like so: pio-docker train -- --master local[3] --driver-memory 4g --executor-memory 10g --verbose --num-executors 3

As most of the google search results are suggested these. My main problem here is that I don't know from where this exception is coming and how to discover it.

Here is the save and method, which could be relevant:

    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;
    }

The hardcoded /templates/ is the docker-mounted volume for pio and for spark also.

Expected result is: train completes without error. I am happy to share more details if necessary, please ask for them, as I am not sure what could be helpful here.

EDIT1: Including 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:

Solution

  • I found out what the issue is: somehow the connection to elasticsearch is lost during the long-running train. This is a docker issue, not a predictionIO issue. For now, I "solved" this by not using elasticsearch at all.

    Another thing I was not aware of: it does matter where you put your --verbose in the command. Providing it in the way I did originally (like pio train -- --driver-memory 4g --verbose) has no/little effect on the verbosity of the logging. The right way to do so is pio train --verbose -- --driver-memory 4g, so before the --. This way I got much more log, from which the origin of the issue became clear.