티스토리 뷰

CDN purge는 CDN의 캐싱을 삭제해주는 기능이다.

 

앞단에서 CDN을 사용하고 있었지만, 기존에는 png, jpeg 등 파일만 관리했고,

azure blob storage에 파일이 올라가면, 파일 경로와 파일명이 무조건 새로 설정되었기 때문에,

cdn에서 요청이 들어올 때 새로 업로드한 파일에 대해선 blob에서 이미지를 캐싱했기 때문에 아무 문제가 없었다. 

그래서 전임자가 azure에 쉽게 업로드할 수 있게 만들어놓은 API를 그대로 썼다.

 

이번 이슈는 XML 파일을 수정하는 것이 새로 추가되었다는 것이다.

blob에서 파일이 수정되는 경우엔 cdn에서 캐시 리로드 주기가 되기 전에는 검사를 따로 안하기 때문에,

즉시 반영이 안되는 문제가 있다.(하지만 즉시 반영이 되어야 했다.)

 

예제코드 등을 찾고, 이런 저런 시도를 해보았으나, 시간도 없고,

새로 나온 api의 예제코드도 살펴보았으나 결국 레거시 코드를 사용하게 되었다. 

 

먼저 PURGE 요청은 아래와 같이 만들어 보낼 수 있다.

 

 

Endpoints - Purge Content - REST API (Azure Azure Front Door Standard/Premium (Preview) and CDN)

Azure Front 도어 Standard/Premium (미리 보기) 및 CDN 서비스에 대해 자세히 알아보세요. CDN에서 콘텐츠를 제거 합니다.

docs.microsoft.com

 

아주 무난하고 쉽다. 그냥 post 요청하나 만들어서 보내면 된다.

근데 하나 빠진게 있다. 본문을 보면 알겠지만 azure ad의 oauth2 인증을 해야 한다.

문제는 azure AD를 활용한 인증이 필요하다는 것이고, 인증방법에 대한 예시가 없다는 것이다.

그걸 하기 위해선 2가지 절차가 있다.

  1. azure AD 계정으로 로그인한 후, azure service principal에서 access token을 만든다.
  2. purge 요청을 만들어 보낸다. (authorization header에 bearer access token을 추가한다.)

 현재 목적은 spring 서버 내에서 파일 업로드 후에 purge까지 진행하는 것이 목적이므로 2번이 목적에 더 적합하다.

 

먼저 azure active directory에 들어가서 app registiration에서 service principal이란걸 등록하자.

등록하고 나면 아래와 같이 정보가 뜬다.

여기서 directory (tenent) ID가 필요하다. 나중에 코드에서 tenentId로 쓰일 녀석이다.

 

 

Client secret을 추가한다. 여기서 Value와 secret id가 필요하다.

value는 처음 생성할때만 보이기 때문에 잘 저장해놓도록 한다.

여기에 access control로 들어가서 service princial을 등록해준다.

여기선 subscription id가 필요하다.

 

이제 자바 코드로 돌아가자.

 

pom.xml에 아래 api를 추가한다.

        <dependency>
            <groupId>com.microsoft.azure</groupId>
            <artifactId>adal4j</artifactId>
            <version>1.6.7</version>
        </dependency>

참고로 adal4j는 2020년 6월부로 지원 중단된 레거시 api이다.

안타깝게도 본인은 해당 api 사용시 필요한 설정값들을 찾지 못하겠어서 레거시를 쓰기로 했지만,

앞으로도 계속 지원할 api를 쓰고 싶다면, 아래 api를 사용하는 것이 좋다.

 

 

GitHub - AzureAD/microsoft-authentication-library-for-java: Microsoft Authentication Library (MSAL) for Java http://aka.ms/aadv2

Microsoft Authentication Library (MSAL) for Java http://aka.ms/aadv2 - GitHub - AzureAD/microsoft-authentication-library-for-java: Microsoft Authentication Library (MSAL) for Java http://aka.ms/aadv2

github.com

 

이제 access token을 얻어서 POST 요청을 만들어서 보내면 된다.

 

각 값을 가져오는 위치는 다음과 같다.

tenentId: Azure Active Directory에서 생성한 Service principal의 tenent 정보

clientId: service principal의 Certificate&secret에서 Secret ID

value: service principal의 Certificate&secret에서 vlaue

subscriptionId: Azure FrontDoor의 subsciption id

profileName: azure front door 의 이름

resourceGroupName: azure front door가 속한 resouce group의 이름

endpointName: front door에서 생성한 각 endpoint의 이름

 

access token을 가져오는 메서드는 getAccessToken()으로 구현했고,

나머지 post 요청을 보내는 코드는 purgeCdn으로 생성한다. 

예외처리나 로깅은 모두 제거했으므로 필요에 따라 알아서 추가해서 쓰면 된다.

 

CdnPurgeService.java

@Service
public class CdnPurgeService {
    private static final String RESOURCE = "https://management.core.windows.net";
    private static final String LOGIN_URL = "https://login.microsoftonline.com";
    @Value("${azure.cdn.tenent-id}")
    private String tenentId;
    @Value("${azure.cdn.client.secret.id}")
    private String clientId;
    @Value("${azure.cdn.client.secret.value}")
    private String value;
    @Value("${azure.cdn.subscription-id}")
    private String subscriptionId;
    @Value("${azure.cdn.profile-name}")
    private String profileName;
    @Value("${azure.cdn.endpoint-name}")
    private String endpointName;
    @Value("${azure.cdn.resource-group}")
    private String resourceGroupName;

    public String getAccessToken() throws MalformedURLException, ExecutionException, InterruptedException {
        String AUTHORITY = LOGIN_URL + "/" + tenentId;

        ExecutorService service = Executors.newFixedThreadPool(1);

        String accessToken = null;
        AuthenticationContext context = null;
        try {
            context = new AuthenticationContext(AUTHORITY, true, service);
            ClientCredential credential = new ClientCredential(clientId, value);
            Future<AuthenticationResult> future = context.acquireToken(RESOURCE, credential, null);
            accessToken = future.get().getAccessToken();
        } finally {
            service.shutdown();
        }
        return accessToken;
    }

    public void purgeCdn(List<String> paths) throws JSONException, JsonProcessingException, MalformedURLException {


        RestTemplate restTemplate = new RestTemplate();
        String url = "https://management.azure.com/subscriptions/" +
                subscriptionId
                + "/resourceGroups/"
                + resourceGroupName
                + "/providers/Microsoft.Cdn/profiles/"
                + profileName
                + "/endpoints/"
                + endpointName
                + "/purge?api-version=2019-12-31";
        HttpHeaders headers = new HttpHeaders();
        headers.set("Content-Type", "application/json");
        headers.set(HttpHeaders.AUTHORIZATION, "Bearer " + getAccessToken());
        headers.set("api-version", "2019-12-31");

        ObjectMapper objectMapper = new ObjectMapper();




        String body = objectMapper.writeValueAsString(new PurgeBodyDto(paths));
        HttpEntity<String> request =
                new HttpEntity<>(body, headers);
        try {
            ResponseEntity<String> responseEntityStr = restTemplate.postForEntity(url, request, String.class);
            responseEntityStr.getBody();
        } catch (HttpClientErrorException ex) {
        }


    }

PurgeBodyDto.java

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.util.List;

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class PurgeBodyDto {
    private List<String> contentPaths;
}

 

요청 생성하는 부분 코드는 아래를 참고했다.

(참고로 C# 코드이다.)

 

 

CDN – //Cloud notes from my desk -Maheshk

Recently I had a chance to work on this ask where one of the developer wanted a sample code to purge the CDN content by hitting this REST API instead portal. Initially I followed this link but do not wanted to give my username and password as explained the

maheshkumar.wordpress.com

 

실행시켜보면 202 응답이 나온다.

스펙에 200, 202 응답이 나올 수 있다고 되어 있으니 요청은 잘 들어갔다고 보면 된다.

(참고로 권한이 제대로 부여가 안되어있으면 401 UnAuthorized가 뜬다)

202 Accepted는 될 수도 있고 안될수도 있습니다 느낌이 있어서 찝찝하긴 하지만,

어쨌든 성공이다.

 

추가)

아래 문서에 purge에 대한 제한이 기록되어 있다.

 

Purge requests take approximately 2 minutes with Azure CDN from Verizon (standard and premium), and approximately 10 seconds with Azure CDN from Akamai. Azure CDN has a limit of 100 concurrent purge requests at any given time at the profile level.

 

즉, purge를 보내면 akamai cdn 사용시 10초, verzion 사용시 2분이고, 동시에 100개의 purge 요청만 처리할 수 있다는 것이다. 

따라서, 상황에 맞게 잘 써야할 것으로 보인다. 

 

https://docs.microsoft.com/en-us/azure/cdn/cdn-purge-endpoint

 

Purge an Azure CDN endpoint

Learn how to purge all cached content from an Azure Content Delivery Network endpoint. Edge nodes cache assets until their time-to-live expires.

docs.microsoft.com

 

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함