Длительная программа в Google App Engine

Я написал код сервлета на Java для чтения строки из файла, который хранится в Google Cloud Storage. Как только я читаю каждую строку, я передаю ее API прогнозирования. Как только я получу предсказание переданного текста. Я добавляю его к исходной строке и сохраняю в другом файле в облачном хранилище Google.

Этот исходный файл имеет формат csv и содержит более 10 000 записей. Поскольку я анализирую его индивидуально, передаю его в API прогнозирования, а затем сохраняю обратно в облачное хранилище. На это уходит много времени. Поскольку App Engine имеет ограничение в 30 разделов, а также очереди задач имеют ограничение. Может ли кто-нибудь предложить мне какой-то вариант? Поскольку повторный запуск программы невозможен, поскольку я не смогу инициировать прогноз с того места, где остановился.

Вот мой код:

@SuppressWarnings("serial")
public class PredictionWebAppServlet extends HttpServlet {

    private static final String APPLICATION_NAME = "span-test-app";

    static final String MODEL_ID = "span-senti";
    static final String STORAGE_DATA_LOCATION = "/bigdata/training_set/";
    private static HttpTransport httpTransport;
    private static final JsonFactory JSON_FACTORY = JacksonFactory
            .getDefaultInstance();

    public static final String INPUT_BUCKETNAME = "bigdata";
    public static final String INPUT_FILENAME = "abc.csv";

    public static final String OUTPUT_BUCKETNAME = "bigdata";
    public static final String OUTPUT_FILENAME = "def.csv";

    private static Credential authorize() throws Exception {

        Credential cr = new GoogleCredential.Builder()
                .setTransport(httpTransport)
                .setJsonFactory(JSON_FACTORY)
                .setServiceAccountId(
                        "878482284233-aacp8vd5297aqak7v5r0f507qr63mab4@developer.gserviceaccount.com")
                .setServiceAccountScopes(
                        Collections.singleton(PredictionScopes.PREDICTION))
                .setServiceAccountPrivateKeyFromP12File(
                        new File(
                                "28617ba6faac0a51eb2208edba85d2e20e6081b4-privatekey.p12"))
                .build();
        return cr;
    }



    public void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws IOException {
        try {
            httpTransport = GoogleNetHttpTransport.newTrustedTransport();
            Credential credential = authorize();

            Prediction prediction = new Prediction.Builder(httpTransport,
                    JSON_FACTORY, credential).setApplicationName(APPLICATION_NAME)
                    .build();


            GcsService gcsService = GcsServiceFactory.createGcsService();

            GcsFilename filename = new GcsFilename(INPUT_BUCKETNAME, INPUT_FILENAME);
            GcsFilename filename1 = new GcsFilename(OUTPUT_BUCKETNAME,
                    OUTPUT_FILENAME);
            GcsFileOptions options = new GcsFileOptions.Builder()
                    .mimeType("text/html").acl("public-read")
                    .addUserMetadata("myfield1", "my field value").build();


            GcsOutputChannel writeChannel = gcsService.createOrReplace(filename1, options);

            PrintWriter writer = new PrintWriter(Channels.newWriter(writeChannel,
                    "UTF8"));


            GcsInputChannel readChannel = null;
            BufferedReader reader = null;

            readChannel = gcsService.openReadChannel(filename, 0);
            reader = new BufferedReader(Channels.newReader(readChannel, "UTF8"));
            String line;
            String cvsSplitBy = ",";
            String temp_record = "";
            Input input = new Input();
            InputInput inputInput = new InputInput();


            while ((line = reader.readLine()) != null) {

                String[] post = line.split(cvsSplitBy);

                inputInput.setCsvInstance(Collections
                        .<Object> singletonList(post[1]));
                input.setInput(inputInput);

                Output output = prediction.trainedmodels()
                        .predict("878482284233", MODEL_ID, input).execute();
                for (int i = 0; i < 10; i++) {
                    temp_record = temp_record + post[i] + ",";
                }
                temp_record = temp_record + output.getOutputLabel();


                 writer.println(temp_record);

            }

            writer.flush();
            writer.close();

            //resp.getWriter().println(temp_record);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        finally{

        }
    }
}

person Deepesh Shetty    schedule 14.07.2014    source источник


Ответы (2)


Вы сами на это намекаете.

Если вы считаете, что ваша работа может быть завершена в течение 10 минут, вы можете сделать это только с очередями задач.

Если нет, вам нужно будет использовать комбинацию очередей задач и серверных частей. Вам нужно вставить его в бэкэнд-экземпляр. Взгляните на Push-очереди и серверные части

ОБНОВЛЕНИЕ — с модулями вместо бэкендов

Бэкэнды устарели в пользу модулей. Способ сделать это с помощью модулей:

  1. преобразовать ваше приложение в структуру модулей
  2. определить модуль с ручным масштабированием
  3. обрабатывать URL-адрес "/_ah/start" в этом модуле
  4. выполнить всю свою работу в обработчике "/_ah/start"

Инстансы с ручным масштабированием не имеют ограничений по времени работы. Вы можете запустить «навсегда» в запросе «/_ah/start», если у экземпляра есть ручное масштабирование. Эй, вы даже можете создавать темы, если хотите. Но это не должно быть необходимо для этой работы. Просто беги, пока не закончишь.

person polesen    schedule 14.07.2014
comment
Бэкэнд устарел !! - person Deepesh Shetty; 15.07.2014

Именно для таких вещей и предназначена фреймворк MapReduce.

person Daniel Roseman    schedule 14.07.2014