Использование Commonj Work Manager для отправки асинхронных HTTP-вызовов
Я переключился с выполнения последовательных HTTP-вызовов на 4 службы REST и на 4 одновременных вызова с использованием исполнителя задач менеджера работы commonj4. Я использую WebLogic 12c. Этот новый код работает в моей среде разработки, но в нашей тестовой среде в условиях нагрузки, а иногда и без нагрузки карта результатов не заполняется всеми результатами. Ведение журнала предполагает, что каждый рабочий элемент все же получил обратно результаты. Может ли это быть проблемой с ConcurrentHashMap? В этом примере от IBM они используют свою собственную версию Work и есть метод getData(), хотя ему не нравится, что этот метод действительно существует в определении их класса. Я следовал другому примеру, который просто использовал класс Work, но не продемонстрировал, как вывести данные из этих потоков в основной поток. Должен ли я использовать execute() вместо schedule()? API не выглядит хорошо документированным. Тайм-аут залипания достаточно высок. component.processInbound() на самом деле содержит код для HTTP-вызова, но у меня проблемы нет, потому что я могу переключиться обратно к синхронной версии класса ниже и не иметь никаких проблем.
Мой код:
public class WorkManagerAsyncLinkedComponentRouter implements
MessageDispatcher<Object, Object> {
private List<Component<Object, Object>> components;
protected ConcurrentHashMap<String, Object> workItemsResultsMap;
protected ConcurrentHashMap<String, Exception> componentExceptionsInThreads;
...
//components is populated at this point with one component for each REST call to be made.
public Object route(final Object message) throws RouterException {
...
try {
workItemsResultsMap = new ConcurrentHashMap<String, Object>();
componentExceptionsInThreads = new ConcurrentHashMap<String, Exception>();
final String parentThreadID = Thread.currentThread().getName();
List<WorkItem> producerWorkItems = new ArrayList<WorkItem>();
for (final Component<Object, Object> component : this.components) {
producerWorkItems.add(workManagerTaskExecutor.schedule(new Work() {
public void run() {
//ExecuteThread th = (ExecuteThread) Thread.currentThread();
//th.setName(component.getName());
LOG.info("Child thread " + Thread.currentThread().getName() +" Parent thread: " + parentThreadID + " Executing work item for: " + component.getName());
try {
Object returnObj = component.processInbound(message);
if (returnObj == null)
LOG.info("Object returned to work item is null, not adding to producer components results map, for this producer: "
+ component.getName());
else {
LOG.info("Added producer component thread result for: "
+ component.getName());
workItemsResultsMap.put(component.getName(), returnObj);
}
LOG.info("Finished executing work item for: " + component.getName());
} catch (Exception e) {
componentExceptionsInThreads.put(component.getName(), e);
}
}
...
}));
} // end loop over producer components
// Block until all items are done
workManagerTaskExecutor.waitForAll(producerWorkItems, stuckThreadTimeout);
LOG.info("Finished waiting for all producer component threads.");
if (componentExceptionsInThreads != null
&& componentExceptionsInThreads.size() > 0) {
...
}
List<Object> resultsList = new ArrayList<Object>(workItemsResultsMap.values());
if (resultsList.size() == 0)
throw new RouterException(
"The producer thread results are all empty. The threads were likely not created. In testing this was observed when either 1)the system was almost out of memory (Perhaps the there is not enough memory to create a new thread for each producer, for this REST request), or 2)Timeouts were reached for all producers.");
//** The problem is identified here. The results in the ConcurrentHashMap aren't the number expected .
if (workItemsResultsMap.size() != this.components.size()) {
StringBuilder sb = new StringBuilder();
for (String str : workItemsResultsMap.keySet()) {
sb.append(str + " ");
}
throw new RouterException(
"Did not receive results from all threads within the thread timeout period. Only retrieved:"
+ sb.toString());
}
LOG.info("Returning " + String.valueOf(resultsList.size()) + " results.");
LOG.debug("List of returned feeds: " + String.valueOf(resultsList));
return resultsList;
}
...
}
}
1 ответ
В итоге я клонировал документ DOM, используемый в качестве параметра. Должен быть какой-то нижестоящий код, который имеет побочные эффекты для параметра.