2013-06-08 2 views
0

У меня есть задача, когда пользователь использует XML от стороннего пользователя. XML-канал обновляется только один раз в день. XML хранится в базе данных и возвращается пользователю по запросу. Если XML отсутствует в базе данных, он извлекается из третьей стороны, сохраняется в базе данных и возвращается пользователю. Все последующие запросы будут просто читать XML из базы данных.Избегание нескольких вызовов при использовании веб-службы

Теперь мой вопрос. Скажем, для запроса третьей стороне требуется 10 секунд. В этот период существует несколько серверных вызовов для одних и тех же данных. Я не хочу, чтобы каждый из них запускал запросы третьей стороне, и я не хочу, чтобы пользователь ничего не получал или не ошибся. Вероятно, они должны дождаться завершения первого запроса, после чего XML будет доступен. Это относительно простая проблема, но я хочу знать, что лучше всего подходит для нее.

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

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

Благодаря

+0

Использование блокировки кажется довольно простым и приятным решением. Вы также можете «синхронизировать» метод, который извлекает данные из стороннего производителя и управляет простым булевым флагом «isLoadingFromThirdParty». – Pragmateek

+0

Возможно ли, что вы получите несколько запросов на одни и те же данные в течение 10-секундного окна обновления ?, и какой вред он будет делать? Будете ли вы значительно замедлить обработку, сделав последующий вызов данных? Я прошу, потому что разработчики склонны переучивать, не уточняя требования. Кто-то платит за это, и они, возможно, предпочтут потратить свои деньги на получение базового рабочего продукта, который они могут поставить перед клиентами, прежде чем стать слишком обеспокоенным проблемами производительности и эффективности. –

+0

@Engineer. Я полностью согласен. Это более сложная задача. Если бы это зависело от меня, я бы даже не ленив, загружая данные в первую очередь. Требование состоит в том, что нет возможности, чтобы конечная точка третьей стороны была забита, если большое количество пользователей сразу попало на сайт - хотя я согласен с тем, что это чрезмерная инженерия. – fatlog

ответ

1

Все, что вам нужно сделать, это создать отдельный компонент, который отвечает, чтобы получить XML от третьих лиц и сохранить его в базу данных.
В вашем коде различные темы попробуйте «извлечь» XML с этого компонента.
Этот компонент возвращает XML из базы данных, если он существует. Если он не существует, вы используете ReentrantLock для синхронизации.
Итак, вы делаете trylock, и только один из ваших тем преуспевает. Остальные будут заблокированы. Когда блокировка освобождается, другие потоки разблокируются, но XML уже был получен от третьей стороны и сохранен в базе данных потоком, который первым удалось получить блокировку. Таким образом, другие потоки просто возвращают XML из БД.

Пример кода (это просто «псевдо-код», чтобы вы начали. Вы должны обрабатывать исключения и т.д., но основной скелет может быть использован. У НЕ забудьте unlock в finally, так что ваш код не блок indefinitelly):

public String getXML() { 
    String xml = getXMLFromDatabase(); 
    if(xml == null) { 
    if(glocalLock.tryLock()) { 
     try{ 
      xml = getXMLFromThirdParty(); 
      storeXMLToDatabase(xml);  
     } 
     finally { 
      globalLock.unlock(); //ok! got XML and stored in DB. Wake-up others! 
     } 
    } 
    else { 
     try{ //Another thread got the lock and will do the query. Just wait on lock!  
      globalLock.lock(); 
     } 
     finally { 
      //woken up but the xml is already fetched 
      xml = getXMLFromDatabase(); 
      globalLock.unlock(); 
     } 
    }  
    return xml; 
} 
Смежные вопросы