2016-06-29 6 views
2

С нескольких недель мы используем Storm в нашем проекте. Сегодня мы обнаружили очень странное поведение. Давайте предположим, что мы имеем следующую топологию:Apache Storm: Mutable Объект, испускаемый для разных болтов.


SpoutA ---> BoltB 
     ---> BoltC 

Итак, мы имеем SpoutA, испускающий пользовательский объект Java (давайте назовем это сообщение) для двух различных болтов. BoltB и BoltC. В принципе, мы выполняем раскол.

До сегодняшнего дня мы предположили, что если SpoutA испускает объект сообщения, он сериализуется на SpoutA и десериализуется на BoltB, а также на BoltC. Однако это предположение кажется неправильным. Сегодня мы обнаружили, что десериализованный объект в BoltB идентичен (Same System.identitfyHashCode) объекту в BoltC. Другими словами, если я манипулирую объектом в BoltB, я также манипулирую объектом Object в BoltC, что приводит к множеству непредвиденных побочных эффектов.

Кроме того, это поведение кажется мне очень странным, поскольку оно применяется только в том случае, если SpoutA и соответствующие болты B и C работают у одного и того же работника. Если я явно принудительно использую три произведения, тогда объект (как и ожидалось) представляет собой другой объект для BoltB и для BoltC, поскольку он используется в разных JVM. Следовательно, если мы предположим, что у нас есть более крупная топология (50 различных болтов), работающая на трех рабочих, тогда мы никогда не сможем быть уверены, что объекты в настоящее время разделены между болтами или нет.

Итак, мы действительно НЕ хотим, чтобы объект был разделен между болтами. Обычно мы ожидаем, что во время десериализации новые новые объекты создаются для каждого из болтов.

Итак, вот мой вопрос: Какие здесь основные недостатки? Является ли наш главный недостаток испусканием «изменчивых» объектов? Неправильно ли мы используем сериализацию/десериализацию? Или это может быть дизайнерский недостаток шторма?

Очевидно, что мы могли бы заставить создавать новые объекты, просто испуская байт-массивы, но, на мой взгляд, это противоречит Шторму.

С наилучшими пожеланиями, Андре

+1

В настоящее время мы выполняем 40-штурмовой штормовой процесс на нашей продукции, и у нас была более тонкая проблема, поэтому, когда мы разбираем объект с одного болта на другой, мы используем сериализацию xml и он будет передаваться как строка xml. он решает нашу проблему –

+1

Да, мы также подумали о реализации нашей собственной сериализации/десериализации (но затем на уровне байта). Другое решение будет явно определять передаваемые объекты как непреложные по соглашению. Тем не менее, я надеялся, что может быть лучшее решение (например, просто настройка, чтобы заставить шторм десериализовать объекты отдельно ...) – Vion

+0

да агрегированы, вы можете пойти с ними в опции –

ответ

1

Storm использует два разных подхода к очередности при перемещении кортежей из одного компонента в другой, где два компонента находятся внутри одной JVM и один, где кортеж должен перемещаться по JVM.Я думаю, что вы попадаете в одно и то же JVM-случае, когда объекты в кортежах фактически не сериализованы, поскольку сериализация требуется только для очередей с несколькими JVM.

Я всегда сортировал и дешифровал данные между кортежем и Java-компонентом, чтобы обеспечить строго типизированный интерфейс для моей бизнес-логики в каждом болте/носике. При этом я полагаю, что я случайно избегаю проблемы, с которой вы сталкиваетесь. Это может быть одним из способов обойти вашу проблему.

+0

Да, спасибо за подробное объяснение. Я также прочитал кое-что об этом полчаса назад в следующей презентации (http://de.slideshare.net/miguno/apache-storm-09-basic-training-verisign). Однако я не понимаю, почему это не задокументировано на веб-сайте Storm. Маршаллинг и Demarshalling определенно решает проблему, но может также снизить производительность. – Vion

0

Почему вы ожидаете, что хэш-код будет отличаться? Точно так же, как нет требования о том, что пользовательские значения hashcode должны отличаться для каждого экземпляра нового объекта (с одинаковыми полями и значениями полей!), Нет ничего, что требовало бы, чтобы встроенная реализация hashcode возвращала разные значения при одновременном создании одного и того же объекта.

Итак, чтобы ответить на ваш вопрос: В чем наши основные недостатки?

Главный недостаток - это ваше понимание того, как работает hashcode. Как отметил Махеш Мадушанка в комментарии, вы можете обойти эту функцию.

Также, когда вы сериализуете объект, он сериализует все, включая частные поля. И многие объекты Java кэшируют хэш-значение в частном поле. Например. Строка. Таким образом, вполне нормально, что их hashcode вернет одно и то же значение (я знаю, что вы используете System.identitfyHashCode, а String возвращает переопределенное значение, но это важно помнить).

+0

Не о хэш-коде. Я действительно не забочусь о HashCode. Меня волнует, что объекты, десериализованные двумя разными болтами, по-прежнему идентичны (не только с точки зрения хэш-кода). Если я изменяю объект в BoltB, он также изменяется в BoltC. Это приводит к неопределяемому поведению, так как нельзя быть уверенным, что Болт выполняется в том же или в другой виртуальной машине. Следовательно, нельзя быть уверенным, что вы получаете два разных объекта, которые одинаковы или равны. Поэтому, на мой взгляд, это не особенность, а ошибка в Apache Storm. – Vion

+0

@Vion Итак, я не понимаю, вы предположили, что hashcode был тем же, потому что объекты были идентичны. Но это предположение неверно. Итак, как вы проверили, что эти объекты идентичны? Вы сделали сравнение «==» по их ссылке? Потому что * это * то, что делает два объекта одинаковыми. –

+0

Мы проверили, что объекты идентичны, управляя свойством (например, счетчиком) объекта, полученного в BoltB, и считывая свойство (счетчик) в BoltC. Значение, которому мы изменили свойство в BoltB, было тогда доступно в BoltC => Объект, полученный BoltB, является тем же самым объектом, полученным BoltC ... каждая модификация, применяемая в BoltB на объекте, также выполняется для BoltC ... (как в простом потоковом сценарии ...) – Vion