WedX - журнал о программировании и компьютерных науках

Google App Engine — разница между локальным сервером разработки и развернутым сервером

Я пишу приложение на Google App Engine, и мне удалось написать код, который выполняется локально и помещает данные в локальное хранилище данных. Однако, когда я развертываю код на сервере Google, данные не помещаются в хранилище данных. Мои основные индикаторы того, что в хранилище данных ничего не помещается: во-первых, когда я иду в консоль разработчика, мне говорят, что записей нет, и во-вторых, когда я запускаю страницу, которая получает данные, ничего не возвращается.

Нужно ли определять новые виды в app.yaml или консоли разработчика, прежде чем они будут работать в производственном хранилище данных?

Вот мои методы put и get из хранилища данных. Опять же, работает в тестовой среде и не работает в продакшене, все отлично компилируется.

package tweetdata

import (
    "net/url"
    "time"

    "golang.org/x/net/context"
    "google.golang.org/appengine/datastore"
    "google.golang.org/appengine/log"

    "github.com/ChimeraCoder/anaconda"
)

const linkTweetKind string = "LinkTweet"
const tweetKey string = "Tweets"
const tweetKeyID string = "default_tweetstore"

//LinkTweet contains the address extracted from a tweet and the original tweet
type LinkTweet struct {
    Address *url.URL
    Tweet   anaconda.Tweet
}

//StoreTweet is a struct used for storing a tweet in the datastore
type StoreTweet struct {
    Address     string
    Text        string
    TweetID     int64
    CreatedTime time.Time
    Retweets    int
    Favorites   int
}

//TweetScore is a struct that shows the relative score of an address based on
// it's populatrity
type TweetScore struct {
    Address    *url.URL
    score      int
    lastActive time.Time
}

//WriteLinkTweet writes a given Tweet to the datastore
func WriteLinkTweet(tweet LinkTweet, c context.Context) error {
    log.Infof(c, "Putting Tweet into datastore: %v", tweet.Tweet.Id)
    key := datastore.NewIncompleteKey(c, linkTweetKind, getTweetKey(c))
    created, _ := tweet.Tweet.CreatedAtTime()
    store := &StoreTweet{Address: tweet.Address.String(),
        Text:        tweet.Tweet.Text,
        TweetID:     tweet.Tweet.Id,
        CreatedTime: created,
        Retweets:    tweet.Tweet.RetweetCount,
        Favorites:   tweet.Tweet.FavoriteCount,
    }

    err := datastore.RunInTransaction(c, func(c context.Context) error {
        _, err := datastore.Put(c, key, store)
        log.Errorf(c, "Failed to write LinkTweet to datastore. %v", err.Error())
        return err
    }, nil)
    return err
}

//GetAllNewTweets queries the datastore and gets all tweets created since the last
// time given
func GetAllNewTweets(since time.Time, c context.Context) []StoreTweet {
    q := datastore.NewQuery(linkTweetKind).Ancestor(getTweetKey(c)).Filter("CreatedTime >=", since)
    out := make([]StoreTweet, 0, 15)
    q.GetAll(c, &out)
    return out
}

// guestbookKey returns the key used for all guestbook entries.
func getTweetKey(c context.Context) *datastore.Key {
    // The string "default_guestbook" here could be varied to have multiple guestbooks.
    return datastore.NewKey(c, tweetKey, tweetKeyID, 0, nil)
}

  • Опубликуйте фрагменты кода, которые вы используете для (попытки) записи сущностей в хранилище данных. Кроме того, что вы видите (или не видите), что заставляет вас верить, что ничего не спасается? 04.08.2015
  • Любая регистрация на ненулевом err? 04.08.2015
  • Я все еще новичок в GAE и не совсем уверен, где посмотреть вывод из log.Printf (или есть ли эквивалент из пакета appengine? 04.08.2015
  • Для ведения журнала вам потребуется использовать функции ведения журнала — Debugf, Infof, Errorf, Warningf, Criticalf — из допустимого контекста запроса (документы находятся в appengine.Context), чтобы войти в App Engine. На вашем сервере разработки вы увидите эти журналы в выводе вашего терминала. В рабочем App Engine эти журналы хранятся в вашей консоли Google Cloud для вашего проекта в разделе Мониторинг › Журналы. 04.08.2015
  • Опубликуйте getTweetKey или просто установите для родителя значение nil и повторите попытку. 04.08.2015
  • Опубликован обновленный код @sridhar. 04.08.2015
  • Поскольку Google App Engine не делает доступным стандартный http.Transport, необходимо указать Anaconda использовать другой клиентский контекст. Я предполагаю, что вы делаете это, иначе это, вероятно, не будет работать и на сервере разработки. 05.08.2015
  • @Sridhar, код для загрузки твитов находится в другом коде, но я использую альтернативный транспорт. 05.08.2015
  • Прошлой ночью я еще немного поработал над этим, и оказалось, что ошибка была где-то в моем коде, и я не добрался до кода хранилища данных, потому что неправильно понял, как GAE обрабатывает подпрограммы Go. Я голосую за все комментарии в благодарность за помощь, но не могу по праву принять ни один из ответов. Спасибо за вашу помощь. 05.08.2015
  • Здорово! Рад слышать. 08.08.2015

Ответы:


1

Вы видите (часто поначалу сбивающий с толку) эффект «конечной согласованности». Сущности, которые записываются вне транзакции, требуют времени, чтобы быть видимыми для запросов.

https://cloud.google.com/datastore/docs/articles/balancing-strong-and-eventual-consistency-with-google-cloud-datastore/ объясняет проблему. https://cloud.google.com/appengine/docs/go/datastore/transactions предназначен для перехода.

04.08.2015
  • Итак, добавить транзакции или подождать, и в конце концов они появятся? 04.08.2015
  • @MrWizard54 - Как долго вы ждете, чтобы увидеть данные? Даже при окончательной согласованности данные обычно видны по запросам в течение одной секунды. 04.08.2015
  • Обычно, но хвост задержки иногда может быть длинным. 04.08.2015
  • На данный момент прошло более двух часов с тех пор, как я запустил Put(), но до сих пор не вижу никаких данных. 04.08.2015
  • Видите ли вы что-нибудь, используя консоль администратора Datastore Viewer? 04.08.2015

  • 2

    Используете ли вы datastore:,noindex в каких-либо полях в структуре StoreTweet? Чтобы выполнить любой запрос к любым полям, хранилище данных должно сначала проиндексировать поля, к которым вы будете запрашивать. Таким образом, отсутствие индексации этих полей приведет к тому, что запрос вернет nil без каких-либо ошибок. Ваш сервер разработки автоматически создает файл index.yaml в вашем проекте после первого запуска ваших запросов? Хранилище рабочих данных использует этот файл, чтобы решить, какие поля должны быть проиндексированы, все поля, которые не проиндексированы, не могут быть запрошены. Из предоставленной вами информации это все, что я могу придумать, что может привести к тому, что ваши запросы будут возвращаться пустыми.

    Для дальнейшей отладки я бы просмотрел ваше производственное хранилище данных и убедился, что ваши данные правильно структурированы, а значения установлены такими, какими вы ожидаете их видеть.

    04.08.2015
  • Сервер разработки создает index.yaml — вид: предок LinkTweet: да свойства: — имя: CreatedTime 04.08.2015
  • Новые материалы

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

    Учебные заметки: создание моего первого пакета Node.js
    Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

    Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
    Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..

    ИИ в аэрокосмической отрасли
    Каждый полет – это шаг вперед к великой мечте. Чтобы это происходило в их собственном темпе, необходима команда астронавтов для погони за космосом и команда технического обслуживания..


    Для любых предложений по сайту: [email protected]