обработка истечения срока действия cookie в многопоточном клиенте Rest - PullRequest
0 голосов
/ 28 августа 2018

У меня есть служба, которую я пишу, которая находится между клиентами, которые будут принимать массовые запросы и отправлять их индивидуально в приложение поставщика, которое необходимо разбить на отдельные запросы.

Это приложение-поставщик имеет API покоя, срок действия токена которого истекает каждые 4 часа. Это также истекает при перезагрузке, и для множества других ситуаций. Я хотел бы справиться с этим изящно.

По соображениям производительности я указал, что могу отправить 15 одновременных запросов в приложение поставщика, чтобы мне не пришлось ждать полного обхода.

Проблема, которую я сейчас пытаюсь решить, заключается в том, как обрабатывать случай истечения срока действия токена / файла cookie, когда я выполняю массовую операцию.

Мой код выглядит примерно так, Executor и многие другие вещи исключены для краткости:

@RestController("/upload")
public BulkController {

    @Autowired RestClient restClient;

    @PostMapping
    public bulkUpload(@RequestBody BulkType bulk){
        restClient.bulkupload(bulk);
    }
}

public RestClient {
    /* Credentials and other initializations */
    @Autowired AsnycClient asyncClient;
    @Async
    private 
    public bulkupload(BulkType bulk){
        for( Single single: bulk.getEntries()){
            asyncClient.upload(single);
        }
    }

}
public AsnycClient {

    /* Credentials and other initializations */
    private static String token = null;
    @Async
    public uploadSingle(Single single){

        Result result = vendorClient.upload(single, token);
        if( result.needsAuthentication()){
            token = vendorClient.authenticate(credentials);
            result = vendorClient.upload(single, token);
        }
    }

}

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

То, что происходит сейчас, это то, что первые 10 или около того запросов отправляются со старым токеном, и все они возвращаются с needsAuthentication(true). Таким образом, я получаю 10 звонков на authenticate() и еще 10 звонков в приложение поставщика, всего 30 звонков.

То, что я хотел бы попытаться найти, - это правильный способ заставить authenticate() произойти должным образом, чтобы первый из тех, у кого есть needsAuthentication(true), выполнял authenticate(), а другие могли обнаружить что-то, и использовать новое значение токена.

Наивный способ, который привел меня к моему вопросу, заключается в следующем:

public AsnycClient {

    /* Credentials and other initializations */
    private static String token = null;
    @Async
    public uploadSingle(Single single){
        Result result = vendorClient.upload(single, token);
        if( result.needsAuthentication()){
            synchronized (token){
                token = vendorClient.authenticate(credentials);
            }
            result = vendorClient.upload(single, token);
        }
    }

}

Хотя это и гарантирует, что все потоки взаимодействуют, регистрируясь по одному, это на самом деле не помогает мне пропустить дорогой authenticate() шаг.

Еще одна попытка, которую я предпринял и которая удовлетворяет потребности, состоит в следующем:

public AsnycClient {

    private static HashMap<String, String> refreshedTokenMap = new HashMap<String, String>();
    /* Credentials and other initializations */
    private static String token = null;
    @Async
    public uploadSingle(Single single){
        String currentToken = token;
        Result result = vendorClient.upload(single, currentToken);
        if( result.needsAuthentication()){
            synchronized (token){
                if( refreshedTokenMap.containsKey(currentToken)){
                    // the current token is one that has been renewed, and so 'token' will contain renewed value
                }else{
                    token = vendorClient.authenticate(credentials);
                    refreshedTokenMap.put(currentToken, token);
                }

            }
            result = vendorClient.upload(single, token);
        }
    }

}

Используя это refreshedTokenMap, я могу сказать, был ли токен, с которого я запустил функцию, обновлен во время моего текущего потока. То, что не имеет никакого способа, - это удалить записи в этом Map, как только все потоки, использующие оригинальный токен, завершат выполнение.

Есть ли у кого-нибудь хорошие ресурсы, которые решили эту проблему, или другое руководство?

спасибо.

...