История о чертовых дублях

от автора

Данная статья подготовлена Дмитрием Овчаренко, архитектором Департамента прикладных финансовых систем компании «Инфосистемы Джет»

Да будет унификация! Такое решение было принято при проектировании интеграционной архитектуры, связывающей CRM с другими внешними системами посредством шины на Oracle Service Bus. Помимо онлайн-интеграции на основе веб-сервисов, она принимает файлы, поступающие в систему, и вызывает веб-сервисы на стороне CRM, специально разработанные для каждого типа входящих данных.

Файл содержит множество записей, и по каждой требуется выполнить отдельный вызов сервиса на стороне CRM. Обработка файла производится в цикле по записям. На каждый вызов сервиса уходит по 5 секунд – это довольно много, но для выполнения поставленных требований вполне хватало. Процесс обработки вызова веб-сервиса в CRM предварительно проверяет запись на дубль, затем выполняет требуемую бизнес-логику и создает запись в БД.

Но «внезапности» могут возникнуть в непредвиденных моментах «шиномонтажа». На промышленных объемах данных в базе CRM стали появляться дубли. Мы выяснили, что источник может почему-то отправить большой файл повторно (сразу после того, как он будет подхвачен файловым proxy-сервисом и помещен в Stage-папку). Причем отставание между вызовами веб-сервисов, создающих дубли, настолько мало, что в момент второго вызова данные в первом еще не закоммичены, и проверка на стороне CRM не успевает срабатывать.

К черту унификацию! Решили реализовывать отдельный Statefull-сервис на Java, хранящий в памяти имена обрабатываемых в текущий момент файлов. При получении файла proxy-сервис на OSB вызывает Java-сервис, передает ему имя файла и узнает, обрабатывается ли он сейчас. В конце обработки файла (или в случае исключения) proxy-сервис сообщает Java-сервису о том, что он закончил обрабатывать файл с данным именем. Соответственно, это имя из списка текущих надо удалить. Обработка двух файлов с одинаковым именем недопустима по бизнес-требованиям. Рестарт сервера тоже не страшен, поскольку будет сброшен не только Java-процесс, но и обрабатываемый файл, если таковой окажется во время перезагрузки.

В общем случае в Oracle SOA Suite Service Bus 11g нет возможности установить блокировку на процесс с синхронизацией по какому-либо идентификатору – предлагается использовать подобный подход не только для ограничения запуска при повторном получении файла, но в принципе в любых случаях, передавая в Statefull-сервис нужный идентификатор.

При этом важно, чтобы в файловом обработчике на OSB был блок Catch верхнего уровня, для того чтобы удалить имя обрабатываемого файла из списка, даже если произошло исключение.

Код сервиса:

@WebService(serviceName = "TaskManager") public class TaskManager {          private static HashMap<String,String> map;     public TaskManager() {         super();         map = new HashMap<String,String>();     }      @WebMethod     @WebResult(name = "Result")     public String addTask(@WebParam(name = "ProcessName") String name){                 String result;                try{             result = map.get(name); // Try to get name from map         }catch (Exception e){       // if there is no such name             result = null;          // we receive exception         }                 if (result == null){        // if there is no such name             map.put(name, "Is running"); // we add name             result = "Task added";                     }         else{             result = "Task is running"; // else - inform caller         }         return result;     }       @WebMethod     @WebResult(name = "Result")     public String removeTask(@WebParam(name = "ProcessName") String name){         String result;             try{             result = map.get(name);         }catch (Exception e){             result = null;         }         if (result == null){             result = "There is no task";                     }         else{             map.remove(name);             result = "Task removed";         }         return result;     } } 

Данный метод очень простой, но, к сожалению, не будет действовать в кластерном варианте развертывания. Также желательно разворачивать его на OSB Managed-сервере WebLogic, чтобы при перезагрузке сбросились одновременно и процессы обработки OSB, и список текущих процессов. Если OSB серверы находятся в кластере, сервис должен быть развернут на отдельном Managed-сервере, и при перезагрузке об этом факте придется помнить.

В заключение. С такой защитой от повторных обработок решение работало больше года, однако ему на смену пришел новый механизм загрузки. Он реализован на Oracle SOA Suite, а обработка записей в нем выполняется параллельно. Но эту тему раскроет уже другая статья.

Мы будем рады вашим конструктивным комментариям.

ссылка на оригинал статьи http://habrahabr.ru/post/267067/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *