Pull to refresh
251.48
Инфосистемы Джет
российская ИТ-компания

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

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

Да будет унификация! Такое решение было принято при проектировании интеграционной архитектуры, связывающей 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, а обработка записей в нем выполняется параллельно. Но эту тему раскроет уже другая статья.

Мы будем рады вашим конструктивным комментариям.
Tags:
Hubs:
+4
Comments0

Articles

Information

Website
jet.su
Registered
Founded
1991
Employees
1,001–5,000 employees
Location
Россия