Синхронизация службы отдыха с использованием JAVA Spring - PullRequest
0 голосов
/ 10 сентября 2018

У меня есть запрос POST, который я хотел бы синхронизировать на основе тела входящего запроса POJO. В теле запроса есть переменная, по которой я могу определить, является ли входящий запрос дубликатом или нет.

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

@PostMapping(value = "testingSync", headers = {"Content-type=application/json"})
public void testingSync(@RequestBody SampleRequestBody sampleRequestBody) {
    synchronized(sampleRequestBody) {
        //Do some process with the sample request body
    }       
}

Пример тела запроса выглядит примерно так

public class SampleRequestBody {

private String identifier;

public String getIdentifier(){
return this.identifier;
}
public void setIdentifier(String identifier){
this.identifier = identifier;
}
}

Ответы [ 2 ]

0 голосов
/ 25 ноября 2018

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

Все, что вам нужно, это добавить компонент XSync в вашу конфигурацию:

@Configuration
public class Config{
    @Bean
    public XSync<String> xSync(){
        return new XSync<>();
    }
}

и теперь вы можете использовать его в вашем контроллере:

@Autowired
private XSync<String> xSync;

@PostMapping(value = "testingSync", headers = {"Content-type=application/json"})
public void testingSync(@RequestBody SampleRequestBody sampleRequestBody) {

    xSync.execute(sampleRequestBody.getIdentifier(), () -> {  
        //Do some process with the sample request 
    });       
}

Реализация этой библиотеки на основе WeakReference вместо String.intern.

Использование String.intern плохая идея, вы можете получить тупик и утечки памяти.

0 голосов
/ 10 сентября 2018

Блок synchronized синхронизирует вызовы, которые используют тот же экземпляр . Поскольку каждый вызов вашей службы создает новый экземпляр SampleRequestBody, синхронизация практически отсутствует.

Вы можете выполнить синхронизацию по свойству identifier объекта запроса, храня строки в каком-то локальном кэше, чтобы снова получить тот же экземпляр строки для того же идентификатора:

// you should not actually use String.intern() here but some local cache
synchronized(sampleRequestBody.getIdentifier().intern()) {
    //Do some process with the sample request body
}

Приведенный выше пример использует String.intern() только для простоты. В реальном живом приложении следует избегать использования String.intern(), поскольку оно создает объекты в памяти, которые не охватываются Java GC. То есть вместо этого используйте локальный кеш.

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

И еще одна мысль: вам действительно следует переосмыслить необходимость синхронизации здесь. Используйте его, только если нет другой возможности решить ваши требования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...