Решение DynamoDB для добавления и удаления атрибутов таблицы в производственном Java SDK - PullRequest
0 голосов
/ 27 августа 2018

Проблема: у нас есть несколько таблиц lambdas и dynamicodb, которые мы используем в рабочей среде, при выпуске новой версии нашего кода мы иногда удаляем атрибут или добавляем атрибуты в наши классы таблиц (код Java с использованием com.amazonaws.services.dynamodbv2 .datamodeling) API высокого уровня. Когда мы внедряем новую версию кода и запрашиваем таблицу, если новый атрибут не существует для существующего элемента или мы удаляем атрибут из кода. Это нарушает код, потому что наш объект Item не соответствует производственным данным.

Мы хотели бы избежать обработки данных в prod, добавляя дополнительные атрибуты со значением по умолчанию или удаляя атрибуты для существующих элементов. Прежде чем мы развернем новую версию по ряду причин, касающихся условий гонки и ее согласованности. Что было бы предпочтительнее, если бы мы обрабатывали его на уровне кода, если атрибут не существует, автоматически добавьте его со значением по умолчанию. Или же код игнорирует атрибуты, которые не определены в классе item / table. Возможно ли это с помощью высокоуровневого Java SDK API?

Другим решением, которое мы придумали, было создание службы, которая питается дельтой (изменение между объектом элемента кода и данными в prod), которая выполняется предтрафик-лямбда, которая обрабатывает данные при развертывании новой версии лямбда Однако мы бы хотели этого избежать.

package com.ourcompany.module.dynamodb.items;

import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBVersionAttribute;
import lombok.Data;

@Data
@DynamoDBTable(tableName = "Boxes")
public class BoxItem {

@DynamoDBHashKey(attributeName = "boxID")
private String channelID;

#This is the field we added, the previous version did not have this field, in prod we have many items without this attribute
@DynamoDBAttribute(attributeName = "lastTimeAccess")
private String lastTimeAccess;

@DynamoDBAttribute(attributeName = "initTime")
private String initTime;

@DynamoDBAttribute(attributeName = "boxIDhash")
private String streamBoxIDHash;

@DynamoDBAttribute(attributeName = "CFD")
private String cfd;

@DynamoDBAttribute(attributeName = "originDomain")
private String originDomain;

@DynamoDBAttribute(attributeName = "lIP")
private String lIP;

@DynamoDBAttribute(attributeName = "pDomain")
private String pDomain;

Выше был изменен наш элемент с добавленным атрибутом.

package com.ourcompany.shared.module.repository.dynamob;

import ...

public class DynamoDbRepository<Item, Key> {

private final DynamoDBMapper mapper;
private static final Logger logger = LogManager.getLogger(DynamoDbRepository.class);

@Inject
public DynamoDbRepository() {
    val client = AmazonDynamoDBClientBuilder
            .standard()
            .withRegion(Regions.US_EAST_1) // TODO: hardcoded now
            .withRequestHandlers(new TracingHandler(AWSXRay.getGlobalRecorder()))
            .build();


    DynamoDBMapperConfig dynamoDBMapperConfig = new DynamoDBMapperConfig.Builder()
                                                   .withSaveBehavior(DynamoDBMapperConfig.SaveBehavior.UPDATE_SKIP_NULL_ATTRIBUTES)
                                                   .withTableNameResolver(new DynamoDBTableNameResolver())
                                                   .build();

    mapper = new DynamoDBMapper(client, dynamoDBMapperConfig);

}
/*
* Many accessor methods are listed here below is the one where we have issue,
*/
public List<Item> findBy(Map<String, Condition> filter, final Class<Item> clazz) throws Exception {
    try {
        logger.trace("DynamoDbRepository findBy(filter, class)");
        val scanExpression = new DynamoDBScanExpression().withScanFilter(filter).withConsistentRead(true);
        PaginatedScanList<Item> ls = mapper.scan(clazz, scanExpression);
        ls.loadAllResults();
        return ls;
    } catch (Exception ex) {
        logger.trace(ex.getMessage());
        throw handleException(ex);
    }
}

Выше представлен наш класс картографа Dynamob DB, но только с указанным методом. Мы смогли проследить, войдя в систему до строки logger.trace («DynamoDbRepository findBy (filter, class)»); и мы знаем, что проблема возникает в маппере. Однако это не приводит к появлению исключения, поэтому мы не можем увидеть фактическую ошибку. Нам пришлось решить эту проблему, удалив все данные из таблиц в prod, после чего новая версия кода повторно заполнила записи атрибутом, и код сработал.

Ответы [ 2 ]

0 голосов
/ 04 сентября 2018

Просто обновление по этому вопросу. Получив совет @zapl о попытке печати трассировки стека, я обнаружил, что в работе AWS DynamoDB Mapper или SDK нет абсолютно ничего плохого. Я ожидал получить некоторую стековую трассировку из SDK и не стал, после более тщательного отслеживания, обнаружил, что разработчики Java неправильно диагностировали проблему, и реальная проблема в том, что у них была логика для фильтрации потока, который зависел от новых полей. Итак, урок истории, разработайте код обратной совместимости, по крайней мере, за одной версией!

0 голосов
/ 27 августа 2018

У вас будет эта проблема для небольшого окна или если вы запустите долгоживущие сплит-тесты.

Мы решили следующими способами:

  1. Какой бы лямбда не использовал атрибуты, убедитесь, что они проверяют, существует ли свойство, и работают с ним. Если обязательное свойство не существует, выдать ошибку и предположить, что оно не удалось. Это может быть проблемой, если вы используете его в транзакционном пути, но сообщит вам, что не удалось и как это исправить. Это для сплит-тестов.
  2. Разработайте свой код для обеспечения обратной совместимости, по крайней мере, с одной версией позади. Обязательно удалите код, как только нужная версия будет установлена.
  3. Если окно маленькое и не сильно загружено, вы можете позволить сервису не перехватить более новую версию.

Надеюсь, это поможет.

...