1장 - Dispatcher 개념, 패턴 및 패턴 방지

개요

이 장에서는 Dispatcher의 역사와 역학에 대해 간략하게 소개하고, AEM 개발자가 구성 요소를 디자인하는 방법에 영향을 주는 방법에 대해 설명합니다.

개발자가 인프라에 관심을 가져야 하는 이유

Dispatcher은 대부분의 AEM 설치에서 필수적인 부분입니다(일부 설치는 아님). Dispatcher 구성 방법과 팁 및 요령을 설명하는 많은 온라인 문서를 찾을 수 있습니다.

그러나 이러한 정보 조각은 항상 매우 기술적인 수준에서 시작합니다. 즉, 원하는 작업을 이미 알고 있다고 가정하고 원하는 작업을 수행하는 방법에 대한 세부 정보만 제공합니다. Dispatcher로 수행할 수 있는 작업과 수행할 수 없는 작업에 대해 기능 및 이유 ​를 설명하는 개념적 문서를 찾지 못했습니다.

앤티패턴: 애프터스톤의 Dispatcher

이러한 기본 정보의 부족은 많은 AEM 프로젝트에서 보았던 많은 안티 패턴으로 이어집니다.

  1. Dispatcher이 Apache 웹 서버에 설치되므로 이를 구성하는 것은 프로젝트의 "Unix gods"가 수행해야 합니다. 필사의 자바 개발자는 그것에 대해 걱정할 필요가 없다.

  2. Java 개발자는 코드가 작동하는지 확인해야 합니다. 나중에 디스패처가 마술처럼 코드를 빠르게 만듭니다. 디스패처는 항상 사후적 사고입니다. 그러나 작동하지 않습니다. 개발자는 디스패처를 염두에 두고 코드를 설계해야 합니다. 그리고 그는 그것을 하기 위해 그것의 기본 개념들을 알아야 합니다.

"우선 작동하게 하고, 빠르게 만듭니다."가 항상 옳은 것은 아닙니다.

프로그래밍 지침 을(를) 들었을 수 있습니다."먼저 작동하게 만들고 빠르게 만듭니다.". 완전히 틀린 것은 아니다. 그러나 올바른 문맥이 없으면 잘못 해석되어 올바르게 적용되지 않는 경향이 있습니다.

개발자가 코드를 너무 일찍 최적화하지 않도록 해야 합니다. 이 경우 결코 실행되지 않을 수도 있고 너무 드물게 실행되기 때문에 최적화가 최적화에 투입되는 노력을 정당화하기에 충분한 영향을 미치지 못할 수 있습니다. 또한 최적화는 더 복잡한 코드를 초래하여 버그를 도입할 수 있습니다. 따라서 개발자인 경우 각 코드 행을 마이크로 최적화하는 데 너무 많은 시간을 투자하지 마십시오. 올바른 데이터 구조, 알고리즘 및 라이브러리를 선택했는지 확인하고 보다 철저한 최적화가 전체 성능을 향상시킬 수 있는 프로파일러의 핫스팟 분석을 기다립니다.

아키텍처 결정 및 아티팩트

그러나 "먼저 작동하게 하고, 빠르게 만듭니다."라는 조언은 "아키텍처"에 대한 의사 결정에서 완전히 틀립니다. 아키텍처 결정이란 무엇입니까? 간단히 말해서, 그들은 비용이 많이 들고, 어렵고 그리고/또는 나중에 바꿀 수 없는 결정들이다. "비싼" 것은 때때로 "불가능한" 것과 같다는 것을 명심해라. 예를 들어 프로젝트에 예산이 부족하면 비싼 변경 사항을 구현할 수 없습니다. 에 대한 사회 기반 시설 변화는 대부분의 사람들이 떠올리는 그 범주의 첫 번째 변화입니다. 그러나 변화하기에 매우 불쾌해질 수 있는 또 다른 종류의 "건축적인" 유물도 있습니다.

  1. 다른 많은 부분이 사용하는 애플리케이션의 "중앙"에 있는 코드 조각. 이를 변경하려면 모든 종속성을 한 번에 변경하고 다시 테스트해야 합니다.

  2. 아티팩트는 입력이 매우 무작위로 달라질 수 있는 비동기 타이밍 종속 시나리오와 관련되어 있습니다. 변경 사항은 예측할 수 없는 영향을 미칠 수 있으며 테스트하기 어려울 수 있습니다.

  3. 시스템의 모든 부분 및 부분에서 반복적으로 사용되고 재사용되는 소프트웨어 패턴입니다. 소프트웨어 패턴이 최적 상태가 아닌 것으로 판명되면 패턴을 사용하는 모든 아티팩트를 다시 코딩해야 합니다.

기억나니? 이 페이지 맨 위에서 Dispatcher은 AEM 애플리케이션의 필수 부분이라고 말했습니다. 웹 애플리케이션에 대한 액세스는 매우 임의적입니다. 사용자가 예측할 수 없는 시간에 오고갑니다. 결국 - 모든 콘텐츠가 Dispatcher에서 캐시됩니다(또는 캐시되어야 함). 따라서 주의 깊게 살펴보았다면 캐싱이 "아키텍처" 아티팩트로 보일 수 있으므로 팀, 개발자 및 관리자 모두 이해해야 한다는 것을 깨달았을 것입니다.

개발자가 실제로 Dispatcher을 구성해야 한다는 것은 아닙니다. 개념(특히 경계)을 알고 있어야 Dispatcher에서도 코드를 활용할 수 있습니다.

Dispatcher은 코드의 속도를 마술처럼 향상시키지 않습니다. 개발자는 Dispatcher을 염두에 두고 구성 요소를 만들어야 합니다. 따라서, 그는 그것이 어떻게 작동하는지 알 필요가 있습니다.

Dispatcher 캐싱 - 기본 원칙

Dispatcher as 캐싱 Http - 로드 밸런서

Dispatcher은 무엇이며 왜 처음에 "Dispatcher"로 불립니까?

Dispatcher은

  • 가장 먼저 캐시

  • 역방향 프록시

  • Apache의 범용성에 AEM 관련 기능을 추가하고 다른 모든 Apache 모듈과 원활하게 작동하는 Apache httpd 웹 서버용 모듈입니다(예: SSL 또는 SSI에 다음에서 보는 바와 같이 포함됨)

웹 초기에는 사이트에 수백 명의 방문자가 있을 것으로 예상됩니다. 여러 AEM 게시 서버에 대한 요청 로드를 "디스패치됨" 또는 밸런싱한 Dispatcher 한 개의 설정이며 일반적으로 충분했습니다. 따라서 이름이 "Dispatcher"입니다. 그러나 최근에는 이 설정이 더 이상 자주 사용되지 않습니다.

Dispatcher 및 Publish 시스템을 설정하는 다양한 방법은 이 문서의 뒷부분에서 확인할 수 있습니다. 먼저 HTTP 캐싱의 기본 사항으로 시작하겠습니다.

Dispatcher 캐시의 기본 기능

Dispatcher 캐시의 기본 기능

Dispatcher의 기본 사항은 여기에 설명되어 있습니다. Dispatcher는 HTTP 요청을 수신하고 만드는 기능을 갖춘 간단한 캐싱 역방향 프록시입니다. 일반적인 요청/응답 주기는 다음과 같습니다.

  1. 사용자가 페이지를 요청합니다.
  2. Dispatcher은 이미 해당 페이지의 렌더링된 버전이 있는지 확인합니다. 이 페이지에 대한 첫 번째 요청이고 Dispatcher에서 로컬 캐시 복사본을 찾을 수 없다고 가정해 보겠습니다.
  3. Dispatcher이 Publish 시스템에서 페이지를 요청합니다
  4. Publish 시스템에서 페이지는 JSP 또는 HTL 템플릿에 의해 렌더링됩니다
  5. 페이지가 Dispatcher으로 반환됩니다
  6. Dispatcher이 페이지를 캐시합니다
  7. Dispatcher이 페이지를 브라우저에 반환합니다.
  8. 동일한 페이지를 두 번째로 요청하는 경우 Publish 인스턴스에서 다시 렌더링하지 않아도 Dispatcher 캐시에서 직접 제공할 수 있습니다. 이렇게 하면 Publish 인스턴스에서 사용자 및 CPU 사이클에 대한 대기 시간이 절약됩니다.

우리는 마지막 섹션에서 "페이지"에 대해 이야기하고 있었습니다. 그러나 이미지, CSS 파일, PDF 다운로드 등과 같은 다른 리소스에도 동일한 스키마가 적용됩니다.

데이터가 캐시되는 방법

Dispatcher 모듈은 호스팅 Apache 서버가 제공하는 기능을 활용합니다. HTML 페이지, 다운로드 및 그림과 같은 리소스는 Apache 파일 시스템에 간단한 파일로 저장됩니다. 그렇게 간단합니다.

파일 이름은 요청된 리소스의 URL에 의해 파생됩니다. /foo/bar.html 파일을 요청하면 /var/cache/docroot/foo/bar.html 아래에 저장됩니다.

원칙적으로 모든 파일이 캐시되어 Dispatcher에 정적으로 저장되는 경우 Publish 시스템의 플러그를 가져올 수 있으며 Dispatcher은 간단한 웹 서버 역할을 합니다. 하지만 이것은 단지 원리를 설명하기 위한 것이다. 실제 생활은 더 복잡하다. 모든 것을 캐시할 수는 없으며 렌더링 프로세스의 동적 특성으로 인해 리소스 수가 무한대가 될 수 있으므로 캐시가 완전히 "가득 참"인 것은 아닙니다. 정적 파일 시스템의 모델은 Dispatcher의 기능에 대한 대략적인 그림을 생성하는 데 도움이 됩니다. 또한 Dispatcher의 제한 사항을 설명하는 데 도움이 됩니다.

AEM URL 구조 및 파일 시스템 매핑

Dispatcher을 더 자세히 이해하기 위해 간단한 샘플 URL의 구조를 다시 살펴보겠습니다. 아래 예를 살펴보겠습니다.

http://domain.com/path/to/resource/pagename.selectors.html/path/suffix.ext?parameter=value&otherparameter=value#fragment

  • http은(는) 프로토콜을 나타냅니다.

  • domain.com은(는) 도메인 이름입니다.

  • path/to/resource은(는) 리소스가 CRX에 저장되고 이후에 Apache 서버의 파일 시스템에 저장되는 경로입니다.

여기서 AEM 파일 시스템과 Apache 파일 시스템 사이에는 약간의 차이가 있습니다.

AEM에서

  • pagename은(는) 리소스 레이블입니다.

  • selectors은(는) 리소스 렌더링 방법을 결정하기 위해 Sling에서 사용되는 여러 선택기를 의미합니다. URL에는 임의 개수의 선택기가 포함될 수 있습니다. 그것들은 일정 기간별로 분리되어 있다. 선택기 섹션은 예를 들어 "french.mobile.fancy"와 같은 것일 수 있습니다. 선택기에는 문자, 숫자 및 대시만 포함되어야 합니다.

  • "선택기"의 마지막 html을(를) 확장이라고 합니다. AEM/Sling에서는 렌더링 스크립트도 부분적으로 결정합니다.

  • path/suffix.ext은(는) URL의 접미사가 될 수 있는 경로와 유사한 표현식입니다. AEM 스크립트에서 리소스를 렌더링하는 방법을 추가로 제어할 수 있습니다. 이 부분에 대해서는 나중에 전체 섹션이 작성될 예정입니다. 지금은 추가 매개 변수로 사용할 수 있음을 알고 있으면 됩니다. 접미사에는 확장명이 있어야 합니다.

  • ?parameter=value&otherparameter=value은(는) URL의 쿼리 섹션입니다. 임의의 매개 변수를 AEM에 전달하는 데 사용됩니다. 매개 변수가 있는 URL은 캐시할 수 없으므로 매개 변수는 반드시 필요한 경우로 제한해야 합니다.

  • #fragment. URL의 조각 부분이 AEM으로 전달되지 않고 브라우저에서만 사용됩니다. JavaScript 프레임워크에서는 "라우팅 매개 변수"로 사용되거나 페이지의 특정 부분으로 이동합니다.

Apache(아래 다이어그램 참조)에서

  • pagename.selectors.html은(는) 캐시의 파일 시스템에서 파일 이름으로 사용됩니다.

URL에 path/suffix.ext 접미사가 있으면

  • pagename.selectors.html이(가) 폴더로 만들어졌습니다.

  • pagename.selectors.html 폴더의 폴더 path

  • suffix.ext은(는) path 폴더의 파일입니다. 참고: 접미사에 확장명이 없으면 파일이 캐시되지 않습니다.

Dispatcher에서 URL을 가져온 후 파일 시스템 레이아웃

Dispatcher에서 URL을 가져온 후 파일 시스템 레이아웃

기본 제한 사항

URL, 리소스 및 파일 이름 간의 매핑은 매우 간단합니다.

함정 몇 개를 알아차렸을 수도 있지만

  1. URL은 매우 길어질 수 있습니다. 로컬 파일 시스템에 /docroot의 "경로" 부분을 추가하면 일부 파일 시스템의 한도를 쉽게 초과할 수 있습니다. Windows에서 NTFS로 Dispatcher을 실행하는 것은 어려운 문제가 될 수 있습니다. 그러나 Linux를 사용하면 안전합니다.

  2. URL에는 특수 문자와 움라우트가 포함될 수 있습니다. 이는 일반적으로 Dispatcher의 문제가 아닙니다. 그러나 URL은 애플리케이션의 여러 위치에서 해석된다는 점을 염두에 두십시오. 거의 사용되지 않는(사용자 지정) 코드 한 개가 특수 문자에 대해 완전히 테스트되지 않았다는 사실을 확인하기 위해 애플리케이션의 이상한 동작을 자주 목격했습니다. 할 수 있으면 피해야 합니다. 그리고 당신이 할 수 없다면, 철저한 테스트를 위해 계획하십시오.

  3. CRX에서 리소스에는 하위 리소스가 있습니다. 예를 들어 페이지에 여러 개의 하위 페이지가 있습니다. 파일 시스템에 파일 또는 폴더가 있으므로 파일 시스템에서 이 항목을 일치시킬 수 없습니다.

확장명이 없는 URL은 캐시되지 않음

URL에는 항상 확장명이 있어야 합니다. AEM에서 확장 없이 URL을 제공할 수 있지만, 이러한 URL은 Dispatcher에서 캐시되지 않습니다.

http://domain.com/home.html은(는) 캐시 가능 ​입니다.

http://domain.com/home이(가) 캐시 불가능

URL에 접미사가 포함된 경우에도 동일한 규칙이 적용됩니다. 접미사를 사용하려면 확장명이 있어야 합니다.

http://domain.com/home.html/path/suffix.html은(는) 캐시 가능 ​입니다.

http://domain.com/home.html/path/suffix이(가) 캐시 불가능

리소스 부분에 확장명이 없지만 접미사에 확장명이 있으면 어떻게 되는지 궁금할 수 있습니다. 음, 이 경우 URL에는 접미사가 전혀 없습니다. 다음 예를 살펴보십시오.

http://domain.com/home/path/suffix.ext

/home/path/suffix은(는) 리소스의 경로이므로 URL에 접미사가 없습니다.

결론

항상 경로와 접미사 모두에 확장을 추가합니다. SEO를 알고 있는 사람들은 검색 결과에서 순위가 매겨진다고 주장하기도 합니다. 그러나 캐시되지 않은 페이지는 매우 느리고 훨씬 더 낮은 순위를 갖습니다.

충돌하는 접미사 URL

유효한 URL이 두 개 있다고 가정합니다.

http://domain.com/home.html

http://domain.com/home.html/suffix.html

AEM에서 절대적으로 유효합니다. 로컬 개발 시스템에는 Dispatcher이 없으면 문제가 발생하지 않습니다. 또한 UAT 또는 로드 테스트에서도 문제가 발생하지 않을 가능성이 높습니다. 우리가 직면한 문제는 너무 미묘해서 대부분의 시험을 통과했다. 피크 타임에 있고 해결할 시간이 제한되어 있고 서버 액세스 권한 또는 이를 수정할 리소스가 없을 때 이 문제가 사용자에게 매우 큰 영향을 미칩니다. 우리는 그곳에 갔다…

그래서… 뭐가 문제야?

파일 시스템의 home.html은(는) 파일이나 폴더일 수 있습니다. AEM에서와 동시에 둘 다 실행할 수는 없습니다.

먼저 home.html을(를) 요청하면 파일로 만들어집니다.

home.html/suffix.html에 대한 후속 요청에서 유효한 결과를 반환하지만 home.html 파일이 파일 시스템의 위치를 "차단"하므로 home.html을(를) 폴더로 두 번 만들 수 없으므로 home.html/suffix.html이(가) 캐시되지 않습니다.

파일 시스템의 파일 차단 위치로 인해 하위 리소스가 캐시되지 않음

파일 시스템의 파일 차단 위치로 인해 하위 리소스가 캐시되지 않음

반대로 수행하는 경우 먼저 home.html/suffix.html을(를) 요청하면 suffix.html이(가) /home.html 폴더 아래에 먼저 캐시됩니다. 그러나 이후에 home.html을(를) 리소스로 요청하면 이 폴더가 삭제되고 home.html 파일로 대체됩니다.

부모를 리소스로 가져올 때 경로 구조를 삭제하는 중

부모를 리소스로 가져올 때 경로 구조를 삭제하는 중

따라서 캐시된 사항의 결과는 전적으로 임의적이며 수신 요청의 순서에 따라 달라집니다. 문제를 더 까다롭게 하는 것은 일반적으로 디스패처가 두 개 이상 있다는 사실입니다. 또한 성능, 캐시 적중률 및 동작은 Dispatcher 간에 서로 다를 수 있습니다. 웹 사이트가 응답하지 않는 이유를 알아보려면 잘못된 캐싱 순서가 있는 올바른 Dispatcher을 보고 있는지 확인해야 합니다. 운이 좋게도 더 유리한 요청 패턴이 있었던 Dispatcher을 보면, 문제를 찾으려고 시도하다 보면 길을 잃게 될 것이다.

충돌하는 URL 방지

접미사가 있을 때 리소스에 대해 다른 확장자를 사용할 때 파일 시스템의 동일한 경로에 대해 폴더 이름과 파일 이름이 "경합"하는 "충돌 URL"을 방지할 수 있습니다.

  • http://domain.com/home.html

  • http://domain.com/home.dir/suffix.html

둘 다 완벽히 계산이 가능하지만

접미사를 요청하거나 접미사를 함께 사용하지 않을 때 리소스에 대한 전용 확장 "dir"을 선택합니다. 유용한 경우가 드물게 있습니다. 그리고 이러한 사례를 올바르게 구현하는 것은 쉽습니다. 다음 장에서 볼 것처럼 캐시 무효화 및 플러시에 대해 설명합니다.

캐시 불가능 요청

마지막 장에 대한 간략한 요약과 몇 가지 더 많은 예외를 검토하겠습니다. Dispatcher은 캐시 가능으로 구성된 경우와 GET 요청인 경우 URL을 캐시할 수 있습니다. 다음 예외 중 하나에서는 캐시할 수 없습니다.

캐시 가능한 요청

  • Dispatcher 구성에서 캐시 가능하도록 요청을 구성했습니다.
  • 요청은 일반 GET 요청입니다.

캐시 불가능 요청 또는 응답

  • 구성(경로, 패턴, MIME 유형)에 의해 캐싱이 거부된 요청
  • "Dispatcher: no-cache" 헤더를 반환하는 응답
  • "Cache-Control: no-cache|private" 헤더를 반환하는 응답
  • "Pragma: no-cache" 헤더를 반환하는 응답
  • 쿼리 매개 변수가 있는 요청
  • 확장명이 없는 URL
  • 확장명이 없는 접미사가 있는 URL
  • 200 이외의 상태 코드를 반환하는 응답
  • POST 요청

캐시 무효화 및 플러시

개요

마지막 장에서는 Dispatcher이 요청을 캐시할 수 없는 경우 많은 예외를 나열했습니다. 그러나 고려해야 할 사항이 더 있습니다. Dispatcher can ​이(가) 요청을 캐시한다고 해서 반드시 should ​이(가) 되는 것은 아닙니다.

중요한 점은 캐싱은 일반적으로 쉽다는 것입니다. Dispatcher은 응답 결과를 저장하고 다음에 동일한 요청이 들어올 때 반환하면 됩니다. 그렇죠? 틀렸어요!

어려운 부분은 캐시의 무효화 또는 플러시 ​입니다. Dispatcher은 리소스가 언제 변경되었는지 파악하고 다시 렌더링해야 합니다.

언뜻 보기에는 사소한 일처럼 보이지만… 자세히 읽어보면 단일 리소스와 단순 리소스 간의 몇 가지 까다로운 차이점과 여러 리소스의 고도로 매겨진 구조를 사용하는 페이지를 확인할 수 있습니다.

간단한 리소스 및 플러싱

특별한 "thumb" 선택기를 사용하여 요청할 때 각 이미지에 대한 썸네일 렌디션을 동적으로 만들도록 AEM 시스템을 설정했습니다.

/content/dam/path/to/image.thumb.png

그리고 - 물론 - 선택기가 없는 URL로 원본 이미지를 제공하는 URL을 제공합니다.

/content/dam/path/to/image.png

썸네일과 원본 이미지를 모두 다운로드하면 다음과 같은 결과가 나옵니다.

/var/cache/dispatcher/docroot/content/dam/path/to/image.thumb.png

/var/cache/dispatcher/docroot/content/dam/path/to/image.png

Dispatcher 파일 시스템에서.

이제 사용자가 해당 파일의 새 버전을 업로드하고 활성화합니다. 궁극적으로 무효화 요청이 AEM에서 Dispatcher으로 전송됩니다.

GET /invalidate
invalidate-path:  /content/dam/path/to/image

<no body>

무효화는 쉽습니다. Dispatcher의 특수 "/invalidate" URL에 대한 간단한 GET 요청입니다. HTTP-body가 필요하지 않습니다. "payload"는 "invalidate-path" 헤더일 뿐입니다. 또한 헤더의 invalidate-path는 Dispatcher에서 캐시한 파일 또는 파일이 아니라 AEM이 알고 있는 리소스입니다. AEM은 리소스만 알고 있습니다. 리소스가 요청될 때 런타임에 확장, 선택기 및 접미사가 사용됩니다. AEM은 리소스에서 사용된 선택기에 대한 부기를 수행하지 않으므로 리소스 경로는 리소스를 활성화할 때 확실히 알 수 있습니다.

이 정도면 충분합니다. 리소스가 변경된 경우 해당 리소스의 모든 렌디션도 변경되었다고 안전하게 가정할 수 있습니다. 이 예제에서 이미지가 변경된 경우 새 썸네일도 렌더링됩니다.

Dispatcher은 캐시된 모든 렌디션을 사용하여 리소스를 안전하게 삭제할 수 있습니다. It will do something like,

$ rm /content/dam/path/to/image.*

image.pngimage.thumb.png 및 해당 패턴과 일치하는 다른 모든 표현물을 제거합니다.

정말 간단합니다. 요청에 응답하는 리소스만 하나만 사용하는 한.

참조 및 메쉬된 콘텐츠

매시드 콘텐츠 문제

AEM에 업로드된 이미지 또는 기타 이진 파일과 달리 HTML 페이지는 독립적인 동물이 아닙니다. 그들은 떼지어 살고 하이퍼링크와 참조에 의해 서로 고도로 연결되어 있다. 간단한 링크는 무해하지만, 콘텐츠 참조에 대해 이야기할 때는 까다로워집니다. 페이지의 유비쿼터스 위쪽 탐색 또는 티저는 콘텐츠 참조입니다.

콘텐츠 참조 및 이것이 문제가 되는 이유

간단한 예를 살펴보겠습니다. 한 여행사에서 캐나다 여행을 홍보하는 웹페이지가 있다. 이 프로모션은 다른 두 페이지의 티저 섹션("홈" 페이지 및 "겨울 스페셜" 페이지)에 나와 있습니다.

두 페이지 모두 동일한 티저를 표시하므로 작성자에게 표시해야 하는 각 페이지에 대해 티저를 여러 번 생성하도록 요청하는 것은 불필요한 작업입니다. 대신 대상 페이지 "캐나다"는 티저에 대한 정보를 제공하기 위해 페이지 속성의 섹션을 예약합니다. 또는 티저를 모두 렌더링하는 URL을 제공하는 것이 더 좋습니다.

<sling:include resource="/content/home/destinations/canada" addSelectors="teaser" />

또는

<sling:include resource="/content/home/destinations/canada/jcr:content/teaser" />

AEM에서는 매력적으로 작동하지만 Publish 인스턴스에서 Dispatcher을 사용하면 이상한 일이 발생합니다.

웹 사이트를 게시했다고 상상해 보십시오. 캐나다 페이지의 제목은 "Canada"입니다. 방문자가 해당 페이지에 대한 티저 참조가 있는 홈 페이지를 요청하면 "캐나다" 페이지의 구성 요소가 다음과 같이 렌더링됩니다

<div class="teaser">
  <h3>Canada</h3>
  <img …>
</div>

홈 페이지를 into ​합니다. 홈 페이지는 Dispatcher에 의해 티저 및 파일의 헤드라인을 포함하여 정적 .html 파일로 저장됩니다.

이제 마케팅 담당자는 티저 헤드라인이 실행 가능해야 한다는 것을 알게 되었습니다. 그래서 그는 제목을 "캐나다"에서 "캐나다 방문"으로 변경하기로 결정하고 이미지도 업데이트합니다.

그는 편집된 "캐나다" 페이지를 게시하고 이전에 게시된 홈 페이지를 다시 방문하여 변경 사항을 확인합니다. 하지만 거기엔 아무 것도 바뀌지 않았어요 여전히 이전 티저가 표시됩니다. 그는 "겨울 스페셜"을 두 번 점검한다. 해당 페이지는 이전에 요청된 적이 없기 때문에 Dispatcher에 정적으로 캐시되지 않습니다. 따라서 이 페이지는 Publish에서 새로 렌더링했으며 이제 이 페이지에 새로운 "캐나다 방문" 티저가 포함됩니다.

Dispatcher이 홈 페이지에 오래된 포함된 콘텐츠를 저장

Dispatcher이 홈 페이지에 오래된 포함된 콘텐츠를 저장

무슨 일이 있었던 거야? Dispatcher은 렌더링하는 동안 다른 리소스에서 가져온 모든 컨텐츠 및 마크업이 포함된 페이지의 정적 버전을 저장합니다.

파일 시스템 기반 웹 서버인 Dispatcher은 속도가 빠르지만 비교적 간단합니다. 포함된 리소스가 변경되는 경우 이를 인식하지 못합니다. 포함 페이지가 렌더링될 때 있던 콘텐츠에 계속 연결됩니다.

"겨울 특별 광고" 페이지가 아직 렌더링되지 않았으므로 Dispatcher에 정적 버전이 없으므로 요청 시 새로 렌더링되므로 새 티저와 함께 표시됩니다.

Dispatcher은 리소스가 변경될 때 이 리소스를 사용한 모든 페이지를 렌더링하고 플러시하는 동안 해당 리소스가 접촉하는 모든 리소스를 추적한다고 생각할 수 있습니다. 하지만 Dispatcher은 페이지를 렌더링하지 않습니다. 렌더링은 Publish 시스템에서 수행됩니다. Dispatcher은 렌더링된 .html 파일에 어떤 리소스가 들어가는지 알지 못합니다.

아직도 납득이 안 가요? "일종의 종속성 추적" ​을(를) 구현하는 방법이 있어야 한다고 생각할 수 있습니다. was ​이(가) 있습니다. Communiqué 3 AEM의 고조부는 페이지를 렌더링하는 데 사용되는 session ​에서 종속성 추적기를 구현했습니다.

요청 중에 이 세션을 통해 얻은 각 리소스는 현재 렌더링 중인 URL의 종속성으로 추적되었습니다.

그러나 의존성을 추적하는 것은 매우 비싸다는 것이 판명되었습니다. 사람들은 곧 종속성 추적 기능을 모두 끄고 한 html 페이지가 변경된 후 모든 html 페이지를 다시 렌더링하는 데 의존한다면 웹 사이트가 더 빠르다는 것을 알게 되었습니다. 게다가, 그 계획은 완벽하지 않았다 - 거기에는 많은 위험과 예외가 있었다. 리소스를 가져오기 위해 요청 기본 세션을 사용하지 않는 경우와 요청을 렌더링할 일부 도우미 리소스를 가져오기 위해 관리 세션을 사용하는 경우가 있었습니다. 이러한 종속성은 일반적으로 추적되지 않았으며 수동으로 캐시를 플러시하도록 요청하는 운영 팀에 대한 전화 문의 및 골칫거리로 이어졌습니다. 그들이 그것을 하기 위한 표준 절차를 가졌다면 당신은 운이 좋았습니다. 가는 길에 더 많은 문제가 있었지만… 회상하지 맙시다. 이것은 2005년으로 거슬러 올라갑니다. 궁극적으로 이 기능은 기본적으로 Communiqué 4에서 비활성화되었으며 후속 CQ5로 다시 전환되지 않았으며 AEM이 되었습니다.

자동 무효화

전체 플러시가 종속성 추적보다 저렴할 때

CQ5부터 페이지 중 하나만 변경되는 경우 전체 사이트를 다소 무효화하는 데 전적으로 의존합니다. 이 기능을 "자동 무효화"라고 합니다.

그러나 다시 한 번 - 수백 개의 페이지를 버리고 다시 렌더링하는 것이 적절한 종속성 추적 및 부분 다시 렌더링보다 더 저렴할 수 있습니까?

다음과 같은 두 가지 주요 이유가 있습니다.

  1. 평균 웹 사이트에서는 페이지의 작은 하위 집합만 자주 요청됩니다. 따라서 렌더링된 모든 콘텐츠를 버린다고 하더라도 실제로는 그 직후에 수십 개만 요청됩니다. 페이지의 롱테일 렌더링은 실제로 요청될 때 시간이 지남에 따라 분산될 수 있습니다. 따라서 실제로 페이지 렌더링에 대한 로드는 예상만큼 높지 않습니다. 물론 항상 예외가 있습니다. 나중에 빈 Dispatcher 캐시가 있는 대규모 웹 사이트에서 균등하게 배포된 로드를 처리하는 방법에 대해 설명합니다.

  2. 모든 페이지는 기본 탐색으로 연결됩니다. 따라서 거의 모든 페이지가 궁극적으로 서로 종속됩니다. 즉, 가장 현명한 종속성 추적기에서도 우리가 이미 알고 있는 내용을 확인할 수 있습니다. 페이지 중 하나가 변경되면 다른 모든 페이지를 무효화해야 합니다.

안 믿어요? 마지막 요점을 설명해 보겠습니다.

원격 페이지의 콘텐츠를 참조하는 티저가 있는 마지막 예제와 동일한 인수를 사용하고 있습니다. 이제 더 극단적인 예, 즉 자동으로 렌더링된 메인 탐색을 사용하고 있습니다. 티저와 마찬가지로 탐색 제목은 링크된 또는 "원격" 페이지에서 콘텐츠 참조로 그려집니다. 원격 탐색 제목은 현재 렌더링된 페이지에 저장되지 않습니다. 탐색은 웹 사이트의 모든 페이지에서 렌더링됩니다. 따라서 한 페이지의 제목은 기본 탐색이 있는 모든 페이지에서 반복해서 사용됩니다. 또한 탐색 제목을 변경하려면 페이지를 참조하는 모든 페이지 및 각 페이지에서 변경할 수 없고 원격 페이지에서 한 번만 변경해야 합니다.

따라서 이 예제에서 탐색은 대상 페이지의 "NavTitle"을 사용하여 탐색에서 이름을 렌더링하여 모든 페이지를 서로 맞물립니다. "아이슬란드"의 탐색 제목은 "아이슬란드" 페이지에서 가져와서 기본 탐색이 있는 모든 페이지로 렌더링됩니다.

기본 탐색은 필연적으로 NavTitles를 가져와서 모든 페이지의 내용을 결합합니다

기본 탐색은 필연적으로 "NavTitles"를 가져와서 모든 페이지의 내용을 결합합니다

Iceland 페이지의 NavTitle을 "Iceland"에서 "Beautiful Iceland"로 변경하면 다른 모든 페이지의 메인 메뉴에서 제목이 즉시 변경됩니다. 따라서 변경 전에 렌더링되고 캐시된 페이지는 모두 부실 상태가 되어 무효화해야 합니다.

자동 무효화 구현 방법: .stat 파일

이제 수천 페이지의 대형 사이트가 있는 경우 모든 페이지를 루프하고 물리적으로 삭제하는 데 시간이 꽤 걸릴 수 있습니다. 이 기간 동안 Dispatcher은 의도하지 않게 오래된 콘텐츠를 제공할 수 있습니다. 더 심각한 것은 캐시 파일에 액세스하는 동안 충돌이 발생할 수 있기 때문이며, 페이지를 삭제하는 동안 페이지가 요청되거나 즉시 후속 활성화 후 발생한 두 번째 무효화로 페이지가 다시 삭제될 수 있습니다. 얼마나 엉망진창인지 생각해 보세요. 다행히도 이런 일은 일어나지 않습니다. Dispatcher은 이를 방지하기 위해 영리한 방법을 사용합니다. 수백, 수천 개의 파일을 삭제하는 대신 파일이 게시될 때 파일 시스템의 루트에 단순한 빈 파일을 넣으므로 모든 종속 파일이 유효하지 않은 것으로 간주됩니다. 이 파일을 "statfile"이라고 합니다. statfile은 빈 파일입니다. statfile에 중요한 것은 파일의 생성 날짜입니다.

Dispatcher의 생성 날짜가 statfile보다 오래된 모든 파일은 마지막 활성화(및 무효화) 전에 렌더링되었으므로 "유효하지 않음"으로 간주됩니다. 이러한 파일은 물리적으로 여전히 파일 시스템에 있지만 Dispatcher에서는 이를 무시합니다. "부실" 상태입니다. 부실 리소스에 대한 요청이 있을 때마다 Dispatcher은 AEM 시스템에 페이지를 다시 렌더링하도록 요청합니다. 새로 렌더링된 페이지는 파일 시스템에 저장되며, 이제 새 생성 날짜가 표시되고 다시 새로 고쳐집니다.

.stat 파일을 만든 날짜가 오래된 콘텐츠 및 최신 콘텐츠를 정의합니다.

.stat 파일을 만든 날짜가 오래된 콘텐츠 및 최신 콘텐츠를 정의합니다.

왜 ".stat"라고 하는지 물어볼 수 있습니까? 그리고 아마도 ".invalidated"는 아닐까요? 파일 시스템에 해당 파일이 있으면 Dispatcher에서 정적 웹 서버처럼 정적으로 ​제공할 수 있는 리소스를 결정할 수 있습니다. 이러한 파일은 더 이상 동적으로 렌더링할 필요가 없습니다.

그러나 그 이름의 본성은 덜 은유적이다. 다른 속성에서 파일의 수정 시간을 반환하는 Unix 시스템 호출 stat()에서 파생됩니다.

단순 유효성 검사와 자동 유효성 검사 혼합

하지만 기다려… 아까 말하기를, 단일 리소스가 물리적으로 삭제된다고 했습니다. 이제 우리는 더 최근의 상태 파일이 Dispatcher의 눈에 비추어 그것들을 사실상 유효하지 않게 할 것이라고 말한다. 왜 물리적 삭제가 먼저 이루어졌을까요?

답은 간단하다. 일반적으로 두 가지 전략을 동시에 사용하지만 서로 다른 종류의 리소스를 사용합니다. 이미지와 같은 바이너리 자산은 자체 포함되어 있습니다. 정보를 렌더링해야 한다는 점에서 이 리소스는 다른 리소스와 연결되어 있지 않습니다.

반면 HTML 페이지는 상호 의존성이 높습니다. 따라서 이러한 변수에 자동 무효화를 적용합니다. Dispatcher의 기본 설정입니다. 무효화된 리소스에 속하는 모든 파일은 물리적으로 삭제됩니다. 또한 ".html"로 끝나는 파일은 자동으로 무효화됩니다.

Dispatcher은 파일 확장명에 따라 자동 무효화 스키마를 적용할지 여부를 결정합니다.

자동 무효화를 위한 파일 끝을 구성할 수 있습니다. 이론적으로 자동 무효화에 대한 모든 확장을 포함할 수 있습니다. 그러나 이것은 매우 높은 가격에 온다는 것을 명심하십시오. 오래된 리소스가 의도하지 않게 배달되는 것을 볼 수는 없지만 지나치게 무효화되면 배달 성능이 크게 저하됩니다.

예를 들어 PNG 및 JPG이 동적으로 렌더링되고 다른 리소스에 따라 렌더링되는 체계를 구현한다고 가정해 보겠습니다. 고해상도 이미지를 더 작은 웹 호환 해상도로 다시 조정할 수 있습니다. 당신이 있는 동안 압축률도 변합니다. 이 예제의 해상도 및 압축 속도는 고정 상수가 아니라 이미지를 사용하는 구성 요소에서 구성 가능한 매개 변수입니다. 이제 이 매개 변수가 변경되면 이미지를 무효화해야 합니다.

문제 없음 - 방금 자동 무효화에 이미지를 추가할 수 있고 변경 사항이 있을 때마다 항상 이미지를 새로 렌더링할 수 있다는 것을 알게 되었습니다.

목욕물을 가지고 아기를 내쫓다

맞습니다 - 그리고 그것은 큰 문제입니다. 마지막 단락을 다시 읽으세요. "…변경될 때마다 새로 렌더링된 이미지." 아시다시피, 훌륭한 웹 사이트는 계속해서 변경됩니다. 여기에 새 콘텐츠를 추가하고, 오타를 수정하고, 티저를 다른 곳에서 수정합니다. 즉, 모든 이미지가 지속적으로 무효화되므로 다시 렌더링해야 합니다. 그것을 과소평가하지 마라. 이미지 데이터를 동적으로 렌더링 및 전송하는 작업은 로컬 개발 시스템에서 밀리초 단위로 작동합니다. 프로덕션 환경에서는 이러한 작업을 초당 100번 더 수행해야 합니다.

그리고 여기서 확실히 하겠습니다. html 페이지가 변경되면 jpg를 다시 렌더링하고 그 반대로 변경해야 합니다. 자동 무효화할 파일의 "버킷"은 하나만 있습니다. 전체적으로 플러시됩니다. 더 상세한 구조들로 나눌 수 있는 어떤 수단도 없습니다.

자동 무효화가 기본적으로 ".html"에 유지되는 데에는 충분한 이유가 있습니다. 목표는 그 양동이를 가능한 한 작게 유지하는 것입니다. 모든 것을 무효화시켜 목욕물과 함께 아기를 버리지 마십시오 - 단지 안전한 측면에.

자체 포함된 리소스는 해당 리소스의 경로에서 제공되어야 합니다. 그것은 무효화에 많은 도움이 됩니다. 단순하게 유지하고, "/x/y/z"에서 제공되는 "resource /a/b/c"와 같은 매핑 체계를 만들지 마십시오. 구성 요소가 기본 Dispatcher의 자동 무효화 설정에서 작동하도록 합니다. Dispatcher에서 과도하게 무효화된 잘못 설계된 구성 요소를 복구하지 마십시오.

자동 무효화 예외: 리소스 전용 무효화

Dispatcher에 대한 무효화 요청은 일반적으로 복제 에이전트에 의해 Publish 시스템에서 실행됩니다.

종속성에 대해 매우 자신 있는 경우 무효화된 자체 복제 에이전트를 빌드할 수 있습니다.

자세한 내용을 살펴보는 것은 이 안내서를 조금 벗어나지만, 몇 가지 힌트를 드리고자 합니다.

  1. 네가 무슨 짓을 하고 있는지 잘 알아. 무효화 권리를 얻는 것은 정말 어렵습니다. 오래된 콘텐츠를 제공하지 않도록 자동 무효화가 엄격한 이유 중 하나입니다.

  2. 에이전트가 HTTP 헤더 CQ-Action-Scope: ResourceOnly을(를) 전송하는 경우 이는 이 단일 무효화 요청이 자동 무효화를 트리거하지 않음을 의미합니다. 이( https://github.com/cqsupport/webinar-dispatchercache/tree/master/src/refetching-flush-agent/refetch-bundle) 코드 조각은 복제 에이전트의 시작점이 될 수 있습니다.

  3. ResourceOnly은(는) 자동 무효화만 방지합니다. 필요한 종속성 해결 및 무효화를 실제로 수행하려면 무효화 요청을 직접 트리거해야 합니다. 패키지 Dispatcher 플러시 규칙(https://adobe-consulting-services.github.io/acs-aem-commons/features/dispatcher-flush-rules/index.html)에서 실제로 발생할 수 있는 방식에 대한 영감을 확인할 수 있습니다.

종속성 해결 스키마를 빌드하지 않는 것이 좋습니다. 그러나 너무 많은 노력과 적은 이득이 있을 뿐이며, 앞서 말한 바와 같이, 여러분이 틀릴 수도 있는 것은 너무 많습니다.

대신 다른 리소스에 종속되지 않고 자동 무효화 없이 무효화될 수 있는 리소스를 확인해야 합니다. 하지만 이러한 경우에는 사용자 정의 복제 에이전트를 사용할 필요가 없습니다. 이러한 리소스를 자동 무효화에서 제외하는 사용자 지정 규칙을 Dispatcher 구성에 생성하기만 하면 됩니다.

우리는 메인 내비게이션이나 티저가 의존성의 원천이라고 말했다. 음 - 비동기적으로 탐색 및 티저를 로드하거나 Apache에서 SSI 스크립트와 함께 포함하면 추적할 종속성이 없습니다. 구성 요소를 비동기적으로 로드하는 방법에 대해서는 이 문서의 후반부에서 "Sling Dynamic Includes"에 대해 자세히 설명합니다.

Lightbox에 로드되는 팝업 창이나 컨텐츠에 대해서도 마찬가지입니다. 또한 이러한 조각에는 탐색(예: "종속성")이 거의 없으며 단일 리소스로 무효화할 수 있습니다.

Dispatcher을 염두에 두고 구성 요소 구축

실제 사례에서 Dispatcher 역학 적용

마지막 장에서는 Dispatcher의 기본 역학, 일반적인 작동 방식 및 제한 사항이 무엇인지 설명했습니다.

이제 우리는 이 역학을 프로젝트의 요구 사항에서 찾을 수 있을 만한 구성 요소에 적용하고자 한다. 조만간 직면하게 될 문제를 입증하기 위해 의도적으로 구성 요소를 선택합니다. 걱정하지 마십시오. 모든 구성 요소가 우리가 제시할 만큼의 고려를 필요로 하는 것은 아닙니다. 그러나 이러한 구성 요소를 빌드해야 하는 경우 결과를 잘 알고 있으며 처리 방법을 알고 있습니다.

스풀링 구성 요소(안티) 패턴

응답형 이미지 구성 요소

상호 연결된 바이너리가 있는 구성 요소의 일반적인 패턴(또는 앤티 패턴)을 예시해 보겠습니다. "응답형 이미지"에 대한 구성 요소 "respi"를 만듭니다. 이 구성 요소는 표시된 이미지를 표시된 디바이스에 적용할 수 있어야 합니다. 데스크탑 및 태블릿에서 이미지의 전체 해상도를 보여주며, 휴대폰에서 자르기 폭이 좁은 작은 버전 또는 완전히 다른 모티브(반응형 세계에서는 "아트 방향"이라고 함)를 보여줍니다.

자산이 AEM의 DAM 영역에 업로드되고 응답형 이미지 구성 요소에서는 참조 ​만 됩니다.

응답 구성 요소는 마크업의 렌더링과 이진 이미지 데이터 전달을 모두 처리합니다.

여기에서 구현하는 방식은 많은 프로젝트에서 확인한 일반적인 패턴이며, AEM 핵심 구성 요소 중 하나라도 이 패턴을 기반으로 합니다. 따라서 개발자인 사용자가 이러한 패턴을 조정할 수 있습니다. 캡슐화라는 측면에서는 좋은 점들이 있지만, Dispatcher에서 사용할 수 있도록 하려면 많은 노력이 필요합니다. 우리는 나중에 문제를 완화하는 몇 가지 옵션에 대해 논의할 것이다.

여기서 사용하는 패턴을 "스풀러 패턴"이라고 합니다. 왜냐하면 문제는 Communiqué 3의 초기 시절로 거슬러 올라가는데, 여기에는 리소스에 대해 이진 원시 데이터를 응답에 스트리밍하도록 호출할 수 있는 "스풀" 메서드가 있었습니다.

원래 '스풀링'이라는 용어는 실제로는 프린터와 같이 공유가 느린 오프라인 주변기기를 의미하므로 여기서는 올바르게 적용되지 않습니다. 하지만 어쨌든 우리는 이 용어를 좋아하는데, 왜냐하면 그것은 온라인 세계에서 드물기 때문에 구별할 수 있기 때문이다. 그리고 각각의 패턴은 구별할 수 있는 이름을 가져야 합니다. 그렇죠? 이것이 패턴인지 안티 패턴인지 결정하는 것은 여러분에게 달려 있습니다.

구현

반응형 이미지 구성 요소는 다음과 같이 구현됩니다.

구성 요소에는 두 개의 부분이 있습니다. 첫 번째 부분은 이미지의 HTML 마크업을 렌더링하고, 두 번째 부분은 참조된 이미지의 이진 데이터를 "스풀"합니다. 반응형 디자인이 적용된 최신 웹 사이트이므로 간단한 <img src"…"> 태그가 아닌 <picture/> 태그의 이미지 집합을 렌더링하고 있습니다. 각 장치에 대해 서로 다른 두 이미지를 DAM에 업로드하고 이미지 구성 요소에서 참조합니다.

구성 요소에는 전용 선택기를 사용하여 각각 지정된 세 개의 렌더링 스크립트(JSP, HTL 또는 서블릿으로 구현됨)가 있습니다.

  1. /respi.jsp - HTML 태그를 렌더링할 선택기가 없음
  2. 데스크톱 버전을 렌더링하려면 /respi.img.java
  3. 모바일 버전을 렌더링하려면 /respi.img.mobile.java하세요.

구성 요소는 홈 페이지의 parsys에 배치됩니다. 아래에 CRX의 결과 구조가 나와 있습니다.

CRX에서 응답형 이미지의 리소스 구조

CRX에서 응답형 이미지의 리소스 구조

구성 요소 마크업은 다음과 같이 렌더링됩니다.

  #GET /content/home.html

  <html>

  …

  <div class="responsive-image>

  <picture>
    <source src="/content/home/jcr:content/par/respi.img.mobile.jpg" …/>
    <source src="/content/home/jcr:content/par/respi.img.jpg …/>

    …

  </picture>
  </div>
  …

그리고… 잘 캡슐화된 부품을 완성했습니다.

응답형 이미지 구성 요소 작동 중

이제 사용자가 Dispatcher을 통해 페이지 및 에셋을 요청합니다. 그러면 아래 그림과 같이 Dispatcher 파일 시스템에 파일이 생성됩니다.

캡슐화된 반응형 이미지 구성 요소의 캐시된 구조

캡슐화된 반응형 이미지 구성 요소의 캐시된 구조

사용자가 DAM에 두 꽃 이미지의 새 버전을 업로드하고 활성화한다고 가정해 봅시다. AEM은 다음에 대한 무효화 요청에 따라 을(를) 전송합니다.

/content/dam/flower.jpg

/content/dam/flower-mobile.jpg

Dispatcher에 하지만 이런 요청들은 헛수고다. 콘텐츠가 구성 요소의 하위 구조 아래에 파일로 캐시되었습니다. 이러한 파일은 현재 사용되지 않지만 요청 시 계속 제공됩니다.

구조 불일치로 인해 오래된 콘텐츠 발생

구조 불일치로 인해 오래된 콘텐츠 발생

이 접근법에는 또 다른 주의사항이 있다. 여러 페이지에서 동일한 flower.jpg를 사용하는 것이 좋습니다. 그러면 동일한 에셋이 여러 URL 또는 파일에 캐시됩니다.

/content/home/products/jcr:content/par/respi.img.jpg

/content/home/offers/jcr:content/par/respi.img.jpg

/content/home/specials/jcr:content/par/respi.img.jpg

…

캐시되지 않은 새 페이지가 요청될 때마다 자산은 다른 URL의 AEM에서 가져옵니다. Dispatcher 캐싱과 브라우저 캐싱을 모두 사용하지 않으면 게재 속도가 빨라집니다.

스풀러 패턴이 빛나는 위치

간단한 형식에서도 이 패턴이 유용한 한 가지 자연 예외가 있습니다. 바이너리가 DAM이 아닌 구성 요소 자체에 저장되는 경우입니다. 그러나 이 기능은 웹 사이트에서 한 번 사용된 이미지에만 유용하며 DAM에 에셋을 저장하지 않으면 에셋 관리에 어려움이 있습니다. 특정 자산에 대한 사용 라이선스가 부족하다고 상상해 보십시오. 자산을 사용한 구성 요소를 어떻게 확인할 수 있습니까?

봤지? DAM의 "M"은 Digital Asset Management에서와 같이 "Management"를 나타냅니다. 그 기능을 없애고 싶진 않군요.

결론

AEM 개발자의 관점에서 볼 때 이 패턴은 매우 우아해 보였다. 그러나 Dispatcher의 등장으로 순진한 접근으로는 충분하지 않을 것이라는 점에는 동의할 수 있을 것입니다.

일단 이것이 패턴인지 아니면 안티패턴인지 결정하는 것은 여러분에게 맡깁니다. 위에서 설명한 문제를 완화하는 방법에 대해 이미 염두에 둔 좋은 아이디어가 있으십니까? 잘됐네 그렇다면 다른 프로젝트들이 이러한 문제들을 어떻게 해결했는지 간절히 보아야 한다.

일반적인 Dispatcher 문제 해결

개요

이를 좀 더 캐시 친화적으로 구현하는 방법에 대해 살펴보겠습니다. 몇 가지 옵션이 있습니다. 때때로 당신은 최선의 해결책을 선택할 수 없습니다. 이미 실행 중인 프로젝트에 들어갔을 때 예산이 제한되어 있어 "캐시 문제"를 바로 해결할 수 있을 뿐 완전한 리팩터링을 수행하기에는 충분하지 않을 수 있습니다. 또는 예제 이미지 구성 요소보다 더 복잡한 문제에 직면할 수도 있습니다.

우리는 다음 섹션에서 원칙과 주의 사항에 대해 간략히 설명하겠습니다.

이 역시 실제 경험을 바탕으로 한 것이다. 우리는 이미 야생에서 그 모든 패턴을 보았기 때문에 그것은 학문적인 연습이 아닙니다. 이것이 우리가 여러분에게 몇 가지 반패턴을 보여주고 있는 이유입니다. 그래서 여러분은 다른 사람들이 이미 했던 실수로부터 배울 수 있는 기회를 갖게 됩니다.

캐시 킬러

WARNING
이건 무늬를 없애는 겁니다. 사용하지 마십시오. 절대.

?ck=398547283745과(와) 같은 쿼리 매개 변수를 본 적이 있습니까? 이를 캐시 킬러("ck")라고 합니다. 쿼리 매개 변수를 추가하면 리소스가 캐시되지 않는다는 아이디어입니다. 또한 매개 변수 값으로 난수를 추가하는 경우(예: "398547283745") URL은 고유해지며 AEM 시스템과 화면 간에 다른 캐시 중 어느 것도 캐시할 수 없도록 합니다. 일반적인 중간 용의자는 Dispatcher, CDN 또는 브라우저 캐시 앞에 있는 "Varnish" 캐시입니다. 다시: 그러지 마. 리소스는 가능한 한 오래 캐싱하려고 합니다. 캐시는 당신의 친구입니다. 친구를 죽이지 마세요

자동 무효화

WARNING
이건 무늬를 없애는 겁니다. 디지털 에셋에 사용하지 마십시오. Dispatcher의 기본 구성( > 은 ".html" 파일에만 자동 무효화됨)을 유지해 보십시오.

단기적으로 Dispatcher의 자동 무효화 구성에 ".jpg" 및 ".png"를 추가할 수 있습니다. 즉, 무효화가 발생할 때마다 ".jpg", ".png" 및 ".html"을 모두 다시 렌더링해야 합니다.

이러한 패턴은 비즈니스 소유자가 라이브 사이트에서 변경 사항이 빠르게 구체화되는 것을 보지 못한다고 불평하는 경우 매우 쉽게 구현됩니다. 하지만 이것은 당신에게 좀 더 정교한 해결책을 생각해낼 시간을 벌어줄 수 있을 뿐이다.

성능에 미치는 영향이 매우 크다는 점을 반드시 알고 있어야 합니다. 이렇게 하면 웹 사이트의 속도가 현저히 느려지고 뉴스 포털과 같이 빈번하게 변경되는 로드가 높은 웹 사이트인 경우 안정성에도 영향을 줄 수 있습니다.

URL 지문

URL 지문은 캐시 킬러처럼 보입니다. 하지만 그렇지 않아요. 난수가 아니라 자원의 내용을 특징짓는 값이 된다. 이는 리소스 콘텐츠의 해시이거나(더 간단함) 리소스가 업로드, 편집 또는 업데이트되었을 때의 타임스탬프일 수 있습니다.

Unix 타임스탬프는 실제 구현에 적합합니다. 가독성을 높이기 위해 이 자습서에서는 읽을 수 있는 형식을 사용합니다. 2018 31.12 23:59 or fp-2018-31-12-23-59.

지문은 쿼리 매개 변수를 사용하는 URL과 같이 쿼리 매개 변수로 사용할 수 없습니다. 캐시할 수 없습니다. 선택기나 접미사를 지문에 사용할 수 있습니다.

/content/dam/flower.jpg 파일의 jcr:lastModified 날짜는 2018년 12월 31일 23:59이라고 가정해 보겠습니다. 지문이 있는 URL은 /content/home/jcr:content/par/respi.fp-2018-31-12-23-59.jpg입니다.

이 URL은 참조된 리소스(flower.jpg) 파일이 변경되지 않는 한 안정적으로 유지됩니다. 따라서 무한한 시간 동안 캐시될 수 있으며 캐시 킬러가 아닙니다.

이 URL은 응답형 이미지 구성 요소에서 만들고 제공해야 합니다. 기본 AEM 기능이 아닙니다.

그것이 기본 개념입니다. 그러나 간과하기 쉬운 몇 가지 세부 사항이 있습니다.

이 예에서 구성 요소는 23:59에 렌더링되고 캐시되었습니다. 이제 이미지가 변경되었습니다. 예를 들어 00:00에 변경하겠습니다. 구성 요소 이(가) 해당 마크업에 새 지문 URL을 생성합니다.

should ​이라고 생각할 수 있지만 그렇지 않습니다. 이미지의 이진만 변경되었으며 포함 페이지를 터치하지 않았으므로 HTML 마크업을 다시 렌더링할 필요가 없습니다. 따라서 Dispatcher은 이전 지문이 있는 페이지를 제공하므로 이전 버전의 이미지가 제공됩니다.

이미지 구성 요소가 참조된 이미지보다 최신입니다. 새로운 지문이 렌더링되지 않았습니다.

이미지 구성 요소가 참조된 이미지보다 최신입니다. 새로운 지문이 렌더링되지 않았습니다.

이제 홈 페이지(또는 해당 사이트의 다른 페이지)를 다시 활성화하면 statfile이 업데이트되고 Dispatcher은 home.html이 오래된 것으로 간주하여 이미지 구성 요소의 새 지문으로 다시 렌더링합니다.

하지만 홈페이지는 활성화하지 않았죠? 그리고 어떻게 해서든 터치하지 않은 페이지를 활성화해야 합니까? 또한 페이지를 활성화할 수 있는 권한이 없거나 승인 작업 과정이 너무 길고 시간이 많이 소요되어 짧은 시간 내에 그렇게 할 수 없을 수도 있습니다. 어떻게 해야 할까요?

지연 관리자의 도구 - Statfile 수준 감소

WARNING
이건 무늬를 없애는 겁니다. 그것을 단지 단기적으로만 사용해 시간을 좀 벌고 좀 더 정교한 해결책을 생각해내라.

지연 관리자는 일반적으로 "자동 무효화를 jpgs로 설정하고 statfile 수준을 0으로 설정합니다. 이 설정은 항상 모든 종류의 문제를 캐시하는 데 도움이 됩니다." 기술 포럼에서 이러한 조언을 찾을 수 있으며, 이는 무효화 문제에 도움이 됩니다.

지금까지 statfile 수준에 대해 논의하지 않았습니다. 기본적으로 자동 무효화는 동일한 하위 트리에 있는 파일에만 작동합니다. 그러나 페이지와 에셋이 일반적으로 동일한 하위 트리에 있지 않다는 문제가 있습니다. 페이지는 /content/mysite 아래에 있지만 자산은 /content/dam 아래에 있습니다.

statfile level은 하위 트리의 깊이 루트 노드가 있는 위치를 정의합니다. 위의 예에서 레벨은 "2"(1=/content, 2=/mysite,dam)가 됩니다.

기본적으로 statfile 수준을 0으로 "감소"한다는 생각은 전체 /content 트리를 하나의 하위 트리로 정의하여 페이지와 자산이 동일한 자동 무효화 도메인에서 살게 하는 것입니다. 따라서 레벨(docroot "/"에서)의 큰 트리에서만 를 가질 수 있습니다. 그러나 이렇게 하면 아무런 관련이 없는 사이트에서도 내용이 게시될 때마다 서버의 모든 사이트가 자동으로 무효화됩니다. Trust us: 전체 캐시 적중률을 심각하게 저하시킬 수 있으므로 이는 장기적으로 볼 때 잘못된 생각입니다. AEM 서버에 캐시 없이 실행할 수 있는 충분한 화력이 있기를 바랄 뿐입니다.

좀 더 심층적인 statfile 수준의 모든 이점을 나중에 이해할 수 있습니다.

사용자 지정 무효화 에이전트 구현

어쨌든 - 새로운 URL을 사용하여 다시 렌더링할 수 있도록 ".jpg" 또는 ".png"가 변경된 경우 어떻게든 HTML 페이지를 무효화하도록 Dispatcher에 알려야 합니다.

프로젝트에서 볼 수 있는 것은 (예: 게시 시스템의 특수 복제 에이전트로서, 해당 사이트의 이미지가 게시될 때마다 사이트에 대한 무효화 요청을 보냅니다.

명명 규칙을 사용하여 에셋의 경로에서 사이트 경로를 가져올 수 있으면 도움이 많이 됩니다.

일반적으로 다음과 같이 사이트와 자산 경로를 일치시키는 것이 좋습니다.

/content/dam/site-a
/content/dam/site-b

/content/site-a
/content/site-b

이렇게 하면 사용자 지정 Dispatcher 플러시 에이전트에서 /content/dam/site-a에 변경 사항이 발생할 때 /content/site-a로 쉽게 및 무효화 요청을 보낼 수 있습니다.

실제로 Dispatcher에 무효화하도록 지시하는 경로가 동일한 사이트, 동일한 "하위 트리"에 있는 한 중요하지 않습니다. 실제 리소스 경로를 사용할 필요도 없습니다. "가상"일 수도 있습니다.

GET /dispatcher-invalidate
Invalidate-path /content/mysite/dummy

  1. DAM의 파일이 변경되면 게시 시스템의 리스너가 트리거됩니다

  2. 리스너가 Dispatcher에 무효화 요청을 보냅니다. 자동 무효화로 인해 사이트의 홈 페이지 또는 사이트 상태 파일 수준에서 더 정확하지 않다면 자동 무효화에서 어떤 경로를 전송하든 상관없습니다.

  3. statfile이 업데이트됩니다.

  4. 다음에 홈페이지가 요청되면 다시 렌더링됩니다. 새 지문/날짜는 이미지의 lastModified 속성에서 추가 선택기로 가져옵니다

  5. 이렇게 하면 묵시적으로 새 이미지에 대한 참조가 만들어집니다

  6. 이미지가 실제로 요청되면 새 렌디션이 만들어지고 Dispatcher에 저장됩니다

청소의 필요성

휴. 완료되었습니다. 만세!

아직…

경로,

/content/mysite/home/jcr:content/par/respi.img.fp-2018-31-12-23-59.jpg

무효화된 리소스와 관련이 없습니다. 기억나니? "더미" 리소스만 무효화하고 자동 무효화에 의존하여 "홈"을 무효로 간주했습니다. 이미지 자체가 실제로 삭제되지 않을 수 있습니다. 따라서 캐시는 증가하고 확장되며 확장됩니다. 이미지를 변경하고 활성화하면 Dispatcher 파일 시스템에서 새 파일 이름을 가져옵니다.

캐시된 파일을 실제로 삭제하지 않고 무기한으로 유지하는 데에는 세 가지 문제가 있습니다.

  1. 스토리지 용량을 낭비하고 있습니다. 당연한 것 - 저장고가 지난 몇 년 동안 더 저렴해지고 더 저렴해졌다. 하지만 이미지 해상도와 파일 크기는 또한 지난 몇 년 동안 크리스탈 샤프 이미지에 굶주린 망막 같은 디스플레이가 등장하면서 성장했다.

  2. 하드 드라이브가 더 저렴해졌음에도 불구하고, "저장"은 더 저렴해지지 않았을 수 있습니다. 당사는 데이터 센터 공급업체에서 NAS에 (저렴한) 베어 메탈 HDD 스토리지를 보유하고 있지 않고 가상 스토리지를 대여하는 추세를 보아 왔습니다. 이러한 종류의 스토리지는 좀 더 안정적이고 확장 가능하지만 비용도 좀 더 비쌉니다. 오래된 쓰레기를 저장하여 낭비하고 싶지 않을 수도 있다. 이는 기본 스토리지뿐만 아니라 백업과도 관련이 있습니다. 기본 백업 솔루션이 있는 경우 캐시 디렉토리를 제외하지 못할 수 있습니다. 결국 가비지 데이터도 백업하게 됩니다.

  3. 더 나쁜 예: 특정 이미지에 대한 사용 라이선스를 필요한 기간 동안만 제한하여 구입했을 수 있습니다. 이제 라이선스가 만료된 후에도 이미지를 저장하면 저작권 침해로 보일 수 있습니다. 웹 페이지에 있는 이미지를 더 이상 사용하지 않을 수 있지만 Google에서 계속 찾을 수 있습니다.

그래서 마지막으로, 당신은 모든 파일을 정리하기 위해 하우스키핑 크론잡을 제안할 것입니다… … 이러한 종류의 쓰레기를 통제하기 위해 일주일을 말합시다.

서비스 거부 공격에 URL 지문 악용

그러나 잠시 만요, 이 해결책에는 또 다른 결함이 있습니다.

선택기를 매개 변수로 남용하고 있습니다. fp-2018-31-12-23-59는 일종의 "캐시 킬러"로서 동적으로 생성됩니다. 그러나 일부 지루한 아이 (또는 미친 검색 엔진 크롤러)는 페이지를 요청하기 시작합니다 :

/content/mysite/home/jcr:content/par/img.fp-0000-00-00-00-00.jpg
/content/mysite/home/jcr:content/par/img.fp-0000-00-00-00-01.jpg
/content/mysite/home/jcr:content/par/img.fp-0000-00-00-00-02.jpg

…

각 요청은 Dispatcher을 우회하여 Publish 인스턴스에 로드됩니다. 그리고 더 나쁜 것은 Dispatcher에 따라 파일을 만드는 것입니다.

따라서… 간단한 캐시 킬러로 지문을 사용하는 대신 이미지의 jcr:lastModified 날짜를 확인하고 예상 날짜가 아닌 경우 404를 반환해야 합니다. Publish 시스템에서는 시간이 걸리고 CPU 사이클이 소요됩니다. 애초에 방지하려는 작업입니다.

고주파수 릴리스에서 URL 지문 주의

DAM에서 가져온 자산뿐만 아니라 JS 및 CSS 파일과 관련 리소스에 대해서도 지문 스키마를 사용할 수 있습니다.

Versioned Clientlibs은(는) 이 방법을 사용하는 모듈입니다.

그러나 여기서는 URL 지문을 갖는 또 다른 주의 사항을 직면할 수 있습니다. 이는 URL을 콘텐츠에 연결합니다. URL을 변경하지 않으면 콘텐츠를 변경할 수 없습니다(즉, 수정 날짜를 업데이트). 그것이 우선 지문이 설계된 것입니다. 하지만 새로운 CSS 및 JS 파일과 새로운 지문이 있는 새로운 URL을 사용하여 새로운 릴리스를 롤아웃하는 것을 고려하십시오. 모든 HTML 페이지에는 여전히 이전 지문 URL에 대한 참조가 있습니다. 따라서 새 릴리스가 일관되게 작동하게 하려면 모든 HTML 페이지를 한 번에 무효화하여 새로 지문 처리된 파일에 대한 참조를 사용하여 다시 렌더링하도록 해야 합니다. 동일한 라이브러리를 사용하는 사이트가 여러 개 있는 경우 상당한 양의 다시 렌더링이 필요할 수 있습니다. 여기서는 statfiles을(를) 활용할 수 없습니다. 따라서 롤아웃 이후 Publish 시스템에서 로드 피크를 확인할 수 있도록 준비하십시오. 캐시 워밍이 있는 파란색-녹색 배포를 고려하거나 Dispatcher 앞에 있는 TTL 기반 캐시를 고려할 수 있습니다. 가능성은 무한합니다.

짧은 휴식

와우, 고려해야 할 세부 사항이 많네요, 그렇죠? 그리고 쉽게 이해되고 테스트되고 디버깅되는 것을 거부합니다. 그리고 이 모든 것이 겉으로 보기에 우아한 해결책을 위한 것입니다. 확실히, 그것은 우아하다 - 하지만 오직 AEM 전용 관점에서만. Dispatcher과 함께 그것은 지저분해진다.

또한 - 하나의 기본 경고가 해결되지 않습니다. 이미지가 다른 페이지에서 여러 번 사용되는 경우 해당 페이지 아래에 캐시됩니다. 거기에는 캐싱 시너지가 별로 없다.

일반적으로 URL 핑거프린팅은 툴킷에 탑재하기에 좋은 도구이지만, 기존의 몇 가지 문제만 해결하면서 새로운 문제를 일으킬 수 있기 때문에 신중하게 적용해야 합니다.

그래서… 긴 챕터였어요 하지만 우리는 이 패턴을 너무 자주 보아왔기 때문에 모든 장단점을 포함한 전체 그림을 여러분에게 줄 필요가 있다고 느꼈습니다. URL 지문 은 스풀러 패턴의 고유한 문제 중 일부를 해결하지만 구현하기 위한 노력이 상당히 높으며 다른 - 더 쉬운 - 솔루션도 고려해야 합니다. URL을 제공된 리소스 경로를 기반으로 할 수 있고 중간 구성 요소가 없는지 항상 확인하는 것이 좋습니다. 우리는 다음 장에서 이것에 대해 공부할 것이다.

런타임 종속성 확인

런타임 종속성 해결은 한 프로젝트에서 고려했던 개념입니다. 하지만 그것을 통해 생각하는 것은 꽤 복잡해졌고 우리는 그것을 시행하지 않기로 결정했습니다.

기본 아이디어는 다음과 같습니다.

Dispatcher은 리소스의 종속성에 대해 알지 못합니다. 의미 체계도 거의 없는 단일 파일일 뿐입니다.

AEM도 종속성에 대해 거의 알지 못합니다. 적절한 의미 체계나 "종속성 추적기"가 없습니다.

AEM은 일부 참조를 알고 있습니다. 참조된 페이지나 에셋을 삭제하거나 이동하려고 할 때 이 지식을 사용하여 경고합니다. 에셋을 삭제할 때 내부 검색을 쿼리하면 됩니다. 콘텐츠 참조에는 매우 특별한 양식이 있습니다. "/content"로 시작하는 경로 표현식입니다. 따라서 전체 텍스트 인덱싱을 손쉽게 수행할 수 있으며 필요할 때 쿼리할 수 있습니다.

이 경우 Publish 시스템에서 해당 경로가 변경되었을 때 특정 경로 검색을 트리거하는 사용자 지정 복제 에이전트가 필요합니다.

예:

/content/dam/flower.jpg

Publish에서 변경되었습니다. 에이전트는 "/content/dam/flower.jpg"에 대한 검색을 실행하고 해당 이미지를 참조하는 모든 페이지를 찾습니다.

그런 다음 Dispatcher에 여러 무효화 요청을 발행할 수 있습니다. 자산이 포함된 각 페이지마다 하나씩.

이론적으로, 그것은 효과가 있을 것이다. 그러나 이는 첫 번째 수준의 종속성에만 해당됩니다. 예를 들어 페이지에서 사용되는 경험 조각의 이미지를 사용할 때 다중 수준 종속성에 대해 이 체계를 적용하지 않으려고 합니다. 사실, 우리는 접근 방식이 너무 복잡하고 런타임 문제가 있을 수 있다고 생각합니다. 일반적으로 가장 좋은 방법은 이벤트 처리기에서 고가의 컴퓨팅을 수행하지 않는 것입니다. 특히 검색은 상당히 비쌀 수 있습니다.

결론

스풀러 패턴 을 충분히 논의했으므로 구현에서 사용할 시점과 사용하지 않을 시점을 결정하는 데 도움이 되었기를 바랍니다.

Dispatcher 문제 방지

리소스 기반 URL

의존성 문제를 해결하는 훨씬 더 우아한 방법은 의존성을 전혀 갖지 않는 것이다. 마지막 예제와 같이 한 리소스를 사용하여 다른 리소스를 단순히 프록시할 때 발생하는 인위적인 종속성을 방지합니다. 가능한 한 자주 리소스를 "고립된" 엔티티로 보도록 하십시오.

이 예제는 쉽게 해결됩니다.

구성 요소가 아닌 이미지에 바인딩된 서블릿을 사용하여 이미지 스풀링.

구성 요소가 아닌 이미지에 바인딩된 서블릿을 사용하여 이미지 스풀링.

Assets 원본 리소스 경로를 사용하여 데이터를 렌더링합니다. 원본 이미지를 그대로 렌더링해야 하는 경우 에셋에 AEM 기본 렌더러를 사용할 수 있습니다.

특정 구성 요소에 대해 특수 처리를 수행해야 하는 경우 해당 경로 및 선택기에 전용 서블릿을 등록하여 구성 요소를 대신하여 변환합니다. 우리는 여기서 ".respi"로 모범적으로 그것을 했다. 선택기. 전역 URL 공간(예: /content/dam)에서 사용되는 선택기 이름을 추적하고 이름 지정 충돌을 방지하기 위한 좋은 이름 지정 규칙을 사용하는 것이 좋습니다.

그런데 코드 일관성에는 문제가 없습니다. 서블릿은 구성 요소 슬링 모델과 동일한 Java 패키지로 정의할 수 있습니다.

다음과 같은 글로벌 공간에서 추가 선택기를 사용할 수도 있습니다.

/content/dam/flower.respi.thumbnail.jpg

진정해, 그렇지? 그렇다면 왜 사람들은 스풀러처럼 복잡한 패턴을 떠올릴까요?

외부 구성 요소가 내부 리소스의 렌더링에 거의 아무런 가치나 정보를 추가하지 않았기 때문에 내부 콘텐츠 참조를 피하는 문제를 해결할 수 있으며, 이는 단일 리소스의 표현을 제어하는 정적 선택기 집합에서 쉽게 인코딩될 수 있습니다.

그러나 리소스 기반 URL로 쉽게 해결할 수 없는 한 가지 사례 클래스가 있습니다. 이러한 유형의 사례를 "매개 변수 주입 구성 요소"라고 하고 다음 장에서 설명합니다.

매개 변수 삽입 구성 요소

개요

마지막 장의 스풀러는 리소스 주위의 얇은 래퍼일 뿐이었습니다. 그것은 문제를 해결하는 데 도움보다 더 많은 문제를 야기시켰다.

간단한 선택기를 사용하여 해당 래핑을 쉽게 대체하고 그러한 요청을 제공하는 서블릿을 추가할 수 있습니다.

그러나 "respi" 구성 요소가 프록시 그 이상이라면 어떻게 해야 합니까? 구성 요소가 구성 요소 렌더링에 실제로 기여하는 경우는 어떻게 합니까?

"respi" 구성 요소의 작은 확장을 소개하겠습니다. 그것은 약간의 게임 체인저입니다. 다시 말하지만, 우리는 먼저 새로운 도전을 해결하고 부족한 부분을 보여줄 수 있는 순진한 해결책을 소개할 것이다.

Respi2 구성 요소

respi2 구성 요소는 응답형 이미지를 표시하는 구성 요소입니다(respi 구성 요소처럼). 하지만 약간의 추가 기능이 있어서,

CRX 구조: 게재에 품질 속성을 추가하는 respi2 구성 요소

CRX 구조: 게재에 품질 속성을 추가하는 respi2 구성 요소

이미지는 JPG이며 JPG를 압축할 수 있습니다. jpeg 이미지를 압축하면 파일 크기에 대해 품질을 바꿀 수 있습니다. 압축은 "1"에서 "100" 사이의 숫자 "품질" 매개 변수로 정의됩니다. "1"은 "작지만 낮은 품질"을 의미하며, "100"은 "뛰어난 품질이지만 큰 파일"을 의미합니다. 그렇다면 완벽한 가치는 무엇인가?

모든 IT에서 답은 다음과 같습니다. "상황에 따라 다릅니다."

여기서 모티브에 따라 다릅니다. 텍스트, 건물 사진, 일러스트레이션, 스케치 또는 제품 상자 사진(날카로운 윤곽선과 텍스트 포함)과 같은 모티프와 같은 대비 가장자리가 높은 모티프는 보통 해당 범주에 속합니다. 풍경이나 초상화와 같이 색상과 대비 전환이 부드러운 모티브는 눈에 보이는 품질 손실 없이 조금 더 압축할 수 있다. 자연 사진은 보통 그 범주에 속한다.

또한 - 이미지가 사용되는 위치에 따라 다른 매개 변수를 사용할 수도 있습니다. 티저의 작은 썸네일은 화면 전체의 영웅 배너에 사용된 이미지와 동일한 이미지보다 압축력이 더 우수할 수 있습니다. 즉, 품질 매개 변수는 이미지에서 비롯된 것이 아니라 이미지와 컨텍스트에 영향을 줍니다. 그리고 저자의 취향에 따라.

간단히 말해, 모든 사진에 대해 완벽한 설정은 없습니다. 모든 것을 다 맞출 수 있는 것은 없습니다. 저자가 정하는 것이 가장 좋습니다. 그는 품질에 만족할 때까지 구성 요소에서 속성으로 "품질" 매개 변수를 조정하며 더 이상 대역폭을 희생하지 않습니다.

이제 DAM에 이진 파일과 품질 속성을 제공하는 구성 요소가 있습니다. URL의 형태는 무엇입니까? 스풀링을 담당하는 구성 요소는 무엇입니까?

나이브 방법 1: 속성을 쿼리 매개 변수로 전달

WARNING
이건 무늬를 없애는 겁니다. 사용하지 마십시오.

마지막 장에서 구성 요소에 의해 렌더링된 이미지 URL은 다음과 같습니다.

/content/dam/flower.respi.jpg

없는 것은 품질의 가치입니다. 구성 요소는 작성자가 입력한 속성을 알고 있습니다… flower.respi2.jpg?quality=60과 같이 마크업이 렌더링될 때 구성 요소를 쿼리 매개 변수로 이미지 렌더링 서블릿에 쉽게 전달할 수 있습니다.

  <div class="respi2">
  <picture>
    <source src="/content/dam/flower.respi2.jpg?quality=60" …/>
    …
  </picture>
  </div>
  …

이것은 나쁜 생각이다. 기억나니? 쿼리 매개 변수가 있는 요청은 캐시할 수 없습니다.

Naive Approach 2: 선택기로 추가 정보 전달

WARNING
이것은 안티 패턴이 될 수 있습니다. 조심히 사용하세요.

선택기로 구성 요소 속성 전달

선택기로 구성 요소 속성 전달

마지막 URL의 약간 변형입니다. 이번에만 선택기를 사용하여 속성을 서블릿에 전달하여 결과를 캐시할 수 있습니다.

/content/dam/flower.respi.q-60.jpg

이게 훨씬 낫긴 한데, 지난번 챕터에서 그런 패턴을 찾아보던 악랄한 대본 아이 기억나니? 그는 그가 가치에 대한 반복으로 얼마나 멀리 얻을 수 있는지 볼 것입니다.

  /content/dam/flower.respi.q-60.jpg
  /content/dam/flower.respi.q-61.jpg
  /content/dam/flower.respi.q-62.jpg
  /content/dam/flower.respi.q-63.jpg
  …

이 경우 다시 캐시를 무시하고 게시 시스템에 로드를 생성합니다. 그래서, 그것은 나쁜 생각일지도 모릅니다. 매개 변수의 작은 하위 집합만 필터링하여 이를 완화할 수 있습니다. q-20, q-40, q-60, q-80, q-100만 허용합니다.

선택기를 사용할 때 잘못된 요청 필터링

선택기 수를 줄이는 것이 좋은 시작이었습니다. 일반적으로 유효한 매개 변수의 수를 항상 절대 최소값으로 제한해야 합니다. 이 작업을 영리하게 수행하는 경우 기본 AEM 시스템에 대한 깊은 지식 없이 정적 필터 세트를 사용하여 AEM 외부의 웹 애플리케이션 방화벽을 활용하여 시스템을 보호할 수도 있습니다.

Allow: /content/dam/(-\_/a-z0-9)+/(-\_a-z0-9)+
       \.respi\.q-(20|40|60|80|100)\.jpg

웹 애플리케이션 방화벽이 없는 경우 Dispatcher 또는 AEM 자체에서 필터링해야 합니다. AEM에서 수행하는 경우 다음을 확인하십시오.

  1. 이 필터는 CRX에 너무 많이 액세스하거나 메모리 및 시간을 낭비하지 않고 매우 효율적으로 구현됩니다.

  2. 필터가 "404 - 찾을 수 없음" 오류 메시지에 응답합니다.

마지막으로 다시 한번 강조합시다. HTTP 대화는 다음과 같습니다.

  GET /content/dam/flower.respi.q-41.jpg

  Response: 404 – Not found
  << empty response body >>

잘못된 매개 변수를 필터링했지만 잘못된 매개 변수가 사용될 때 유효한 대체 렌더링을 반환하는 구현도 보았습니다. 20-100의 매개 변수만 허용한다고 가정해 보자. 사이의 값은 유효한 값에 매핑됩니다. 그래서,

q-41, q-42, q-43, …

는 항상 q-40과 동일한 이미지에 응답합니다.

  GET /content/dam/flower.respi.q-41.jpg

  Response: 200 – OK
  << flower.jpg with quality = 40 >>

그 방법은 전혀 도움이 되지 않는다. 이러한 요청은 실제로 유효한 요청입니다. 처리 능력을 소비하고 Dispatcher의 캐시 디렉터리에서 공간을 차지합니다.

301 – Moved permanently을(를) 반환하는 것이 좋습니다.

  GET /content/dam/flower.respi.q-41.jpg

  Response: 301 – Moved permanently
  Location: /content/dam/flower.respi.q-40.jpg

여기 AEM이 브라우저에 알려줍니다. "q-41이(가) 없습니다. 하지만 q-40에 대해 물어볼 수 있습니다.

그러면 대화에 추가 요청 응답 루프가 추가되어 약간의 오버헤드가 발생하지만, q-41에서 전체 처리를 수행하는 것보다 비용이 저렴합니다. q-40에서 이미 캐시된 파일을 활용할 수 있습니다. 하지만 302개의 응답이 Dispatcher에서 캐시되지 않는다는 것을 이해해야 합니다. 우리는 AEM에서 실행되는 논리에 대해 이야기하고 있습니다. 계속해서… 그래서 날씬하고 빠르게 만드는 게 좋죠.

우리는 개인적으로 404가 가장 호응이 좋다. 그것은 무슨 일이 일어나고 있는지 매우 명백하게 만듭니다. 또한 로그 파일을 분석할 때 웹 사이트에서 오류를 감지하는 데 도움이 됩니다. 301은 의도할 수 있으며, 404는 항상 분석하고 제거해야 합니다.

보안 - 특별 행사

요청 필터링

가장 적합한 필터링 위치

마지막 장 끝에서 알려진 선택기에 대한 들어오는 트래픽을 필터링할 필요성을 지적했습니다. 그러면 질문은 사라집니다. 실제로 어디에서 요청을 필터링해야 합니까?

상황에 따라 다르죠 빠르면 빠를수록 좋습니다.

웹 애플리케이션 방화벽

웹 보안을 위해 설계된 웹 응용 프로그램 방화벽 장치나 "WAF"가 있는 경우 이러한 기능을 반드시 활용해야 합니다. 그러나 WAF는 콘텐츠 애플리케이션에 대한 지식이 제한된 사람만 사용하며 유효한 요청을 필터링하거나 너무 많은 유해 요청을 전달한다는 것을 알 수 있습니다. WAF를 운영하는 직원들이 교대 근무와 릴리스 일정이 다른 부서에 할당되어 있으며, 커뮤니케이션이 직속 팀원들과 같이 긴밀하지 않을 수 있고 항상 시간에 변화를 얻지 못하여 결과적으로 개발 및 콘텐츠 속도가 저하되는 것을 알 수 있습니다.

당신은 몇 가지 일반적인 규칙이나 심지어 당신의 직감이 강화될 수 있다고 말하는 차단 목록에 추가하다로 끝날 수 있습니다.

Dispatcher 및 Publish 필터링

다음 단계는 Apache 코어 및/또는 Dispatcher에서 URL 필터링 규칙을 추가하는 것입니다.

여기서는 URL에만 액세스할 수 있습니다. 패턴 기반 필터로 제한됩니다. 더 많은 컨텐츠 기반 필터링(예: 올바른 타임스탬프가 있는 파일만 허용)을 설정해야 하거나 작성자에서 일부 필터링을 제어하려면 사용자 지정 서블릿 필터와 같은 것을 작성하게 됩니다.

모니터링 및 디버깅

실제로 각 수준에 약간의 보안이 제공됩니다. 하지만 어떤 수준에서 요청이 필터링되는지 확인할 수 있는 수단이 있는지 확인하십시오. Publish 시스템, Dispatcher 및 WAF의 로그 파일에 직접 액세스하여 체인의 어떤 필터가 요청을 차단하는지 확인해야 합니다.

선택기 및 선택기 확산

마지막 장의 "selector-parameters"를 사용하는 접근 방식은 빠르고 쉬우며 새 구성 요소의 개발 시간을 단축할 수 있지만 한계가 있습니다.

"quality" 속성을 설정하는 것은 간단한 예에 불과합니다. 그러나 서블릿은 "폭"에 대한 매개 변수가 더 다용적일 것으로 예상한다고 가정해 보겠습니다.

가능한 선택기 값 수를 줄여 유효한 URL의 수를 줄일 수 있습니다. 너비로도 동일한 작업을 수행할 수 있습니다.

품질 = q-20, q-40, q-60, q-80, q-100

width = w-100, w-200, w-400, w-800, w-1000, w-1200

그러나 이제 모든 조합이 유효한 URL입니다.

/content/dam/flower.respi.q-40.w-200.jpg
/content/dam/flower.respi.q-60.w-400.jpg
…

이제 하나의 리소스에 대해 5x6=30개의 유효한 URL이 이미 있습니다. 각 추가 속성은 복잡성을 가중시킵니다. 그리고 적당한 값으로 줄일 수 없는 속성이 있을 수 있다.

그래서, 또한 이 접근법은 한계가 있습니다.

실수로 API 노출

여긴 무슨 일이야? 자세히 살펴보면 정적으로 렌더링된 웹 사이트에서 점차 동적인 웹 사이트로 이동하고 있음을 알 수 있습니다. 또한 의도치 않게 작성자만 사용하려는 고객 브라우저에 이미지 렌더링 API가 표시됩니다.

이미지의 품질과 크기를 설정하는 작업은 페이지를 편집하는 작성자가 수행해야 합니다. 서블릿에 의해 노출된 동일한 기능을 갖는 것은 서비스 거부 공격에 대한 기능 또는 벡터로 볼 수 있습니다. 실제로 무엇인지는 문맥에 따라 다릅니다. 웹 사이트의 비즈니스 중요도 서버에 얼마나 많은 부하가 걸립니까? 헤드룸이 얼마나 남았나요? 구현을 위한 예산이 얼마나 됩니까? 당신은 이 요인들의 균형을 맞춰야 합니다. 장단점을 알고 있어야 한다.

스풀러 패턴 - 재방문 및 재복구

스풀러가 API의 노출을 피하는 방법

우리는 마지막 장에서 스풀러 패턴을 약간 무시했다. 이제 회복할 시간이에요.

스풀러 패턴 은 마지막 장에서 설명한 API 노출 문제를 방지합니다. 속성은 구성 요소에 저장되고 캡슐화됩니다. 이러한 속성에 액세스하기 위해서는 구성 요소에 대한 경로만 있으면 됩니다. 마크업과 이진 렌더링 간에 매개 변수를 전송하는 수단으로 URL을 사용할 필요가 없습니다.

  1. 기본 요청 루프 내에서 구성 요소가 요청되면 클라이언트가 HTML 태그를 렌더링합니다

  2. 구성 요소 경로는 마크업에서 구성 요소로의 역참조 역할을 합니다

  3. 브라우저는 이 역참조를 사용하여 바이너리를 요청합니다

  4. 요청이 구성 요소에 도달함에 따라 이진 데이터의 크기 조절, 압축 및 스풀링을 위한 모든 속성이 제공됩니다

  5. 이미지는 구성 요소를 통해 클라이언트 브라우저로 전송됩니다

스풀러 패턴이 결국 나쁘지 않아서인지 인기가 많은 편이다. 캐시 무효화와 관련하여 번거롭지 않은 경우에만…

뒤집힌 스풀러 - 두 세계의 최고?

그것은 우리에게 질문을 던지게 한다. 왜 우리는 두 세계의 장점을 모두 얻을 수 없을까? 스풀러 패턴 캡슐화를 잘 하고 리소스 기반 URL의 캐싱 속성을 잘 유지하시겠습니까?

우리는 그것을 실제 라이브 프로젝트에서 본 적이 없다는 것을 인정해야 합니다. 하지만 우리는 여기서 여러분의 해결책을 위한 출발점으로서 어떤 방법으로든 약간의 생각과 실험을 해 보도록 합시다.

이 패턴을 반전 스풀러 ​라고 합니다. 모든 캐시 무효화 속성을 사용하려면 반전 스풀러가 이미지 리소스를 기반으로 해야 합니다.

그러나 매개 변수를 노출해서는 안 됩니다. 모든 속성은 구성 요소에 캡슐화되어야 합니다. 하지만 우리는 속성에 대한 불투명한 참조로 구성 요소 경로를 노출할 수 있습니다.

그러면 다음 형식의 URL이 생성됩니다.

/content/dam/flower.respi3.content-mysite-home-jcrcontent-par-respi.jpg

/content/dam/flower은(는) 이미지의 리소스에 대한 경로입니다.

.respi3은(는) 이미지를 전달할 올바른 서블릿을 선택하는 선택기입니다.

.content-mysite-home-jcrcontent-par-respi은(는) 추가 선택기입니다. 이미지 변환에 필요한 속성을 저장하는 구성 요소에 대한 경로를 인코딩합니다. 선택기는 경로보다 작은 문자 범위로 제한됩니다. 여기서 인코딩 방식은 단지 예시적인 것이다. "/"를 "-"로 대체합니다. 경로 자체에도 "-"를 포함할 수 있다는 것은 고려되지 않습니다. 좀 더 정교한 인코딩 방식은 실제 사례에서 권장될 것이다. Base64는 정상이어야 합니다. 그러나 이로 인해 디버깅이 좀 더 어려워집니다.

.jpg은(는) 파일 접미사입니다.

결론

와우… 스풀러 얘기가 생각보다 길어지고 복잡해졌어요. 우리는 당신에게 변명의 여지를 줍니다. 그러나 우리는 Dispatcher 랜드에서 잘 작동하는 것과 그렇지 않은 것에 대한 직관을 배울 수 있도록 좋은 것과 나쁜 것의 많은 측면을 보여주는 것이 필요하다고 느꼈다.

Statfile 및 Statfile-레벨

기본 사항

소개

이전에 statfile ​에 대해 간략하게 언급했습니다. 자동 무효화와 관련되어 있습니다.

마지막으로 수정한 날짜가 statfile's개의 마지막 수정 날짜보다 오래된 경우 자동 무효화되도록 구성된 Dispatcher 파일 시스템의 모든 캐시 파일이 유효하지 않은 것으로 간주됩니다.

NOTE
마지막으로 수정된 날짜는 캐시된 파일이며 클라이언트의 브라우저에서 파일이 요청되어 파일 시스템에서 최종적으로 생성된 날짜입니다. 리소스의 jcr:lastModified 날짜가 아닙니다.

statfile(.stat)의 마지막 수정 날짜는 Dispatcher에서 AEM의 무효화 요청을 받은 날짜입니다.

Dispatcher이 두 개 이상 있는 경우 이로 인해 이상한 효과가 발생할 수 있습니다. 브라우저에 Dispatcher 최신 버전이 있을 수 있습니다(Dispatcher이 두 개 이상 있는 경우). 또는 Dispatcher이 다른 Dispatcher에서 발급한 브라우저 버전이 오래되어 새 복사본을 불필요하게 보냈다고 생각할 수 있습니다. 이러한 효과는 성능 또는 기능 요구 사항에 큰 영향을 주지 않습니다. 브라우저에 최신 버전이 있으면 시간이 지남에 따라 레벨이 조정됩니다. 하지만 브라우저 캐싱 동작을 최적화하고 디버깅하는 경우에는 다소 혼란스러울 수 있습니다. 조심하세요.

/statfileslevel을 사용하여 무효화 도메인 설정

자동 무효화와 상태 파일을 도입할 때 변경 사항이 있고 모든 파일이 상호 종속되어 있는 경우 모든 파일은 유효하지 않은 것으로 간주됩니다.

정확하지 않습니다. 일반적으로 공통 기본 탐색 루트를 공유하는 모든 파일은 상호 종속됩니다. 그러나 하나의 AEM 인스턴스가 여러 개의 웹 사이트(독립 웹 사이트)를 호스팅할 수 있습니다. 일반적인 탐색을 공유하지 않음 - 사실상, 아무 것도 공유하지 않음.

A사이트에 변경 사항이 있어 B사이트를 무효화시키는 것은 아깝지 않을까요? 네, 그렇습니다. 그리고 그렇게 될 필요는 없습니다.

Dispatcher은 사이트를 서로 분리하는 간단한 방법을 제공합니다. statfiles-level.

이 숫자는 파일 시스템에서 두 개의 하위 트리가 "독립"으로 간주되는 수준을 정의하는 숫자입니다.

statfileslevel이 0인 기본 사례를 살펴보겠습니다.

/statfileslevel 0:_ .stat _이 docroot에 만들어졌습니다. 무효화 도메인이 모든 사이트 을(를) 포함하여 전체 설치에 걸쳐 있습니다.

/statfileslevel "0": .stat 파일이 docroot에 만들어집니다. 무효화 도메인은 모든 사이트를 포함한 전체 설치에 걸쳐 있습니다.

무효화된 파일은 Dispatchers docroot의 맨 위에 있는 .stat 파일이 항상 업데이트됩니다. 따라서 /content/site-b/home을(를) 무효화할 때 /content/site-a의 모든 파일도 docroot의 .stat 파일보다 오래되었으므로 무효화됩니다. site-b을(를) 무효화할 때는 필요한 것이 아닙니다.

이 예제에서는 statfileslevel을(를) 1(으)로 설정하는 것이 좋습니다.

이제 게시하여 /content/site-b/home 또는 /content/site-b 아래의 다른 리소스를 무효화하면 .stat 파일이 /content/site-b/에 만들어집니다.

/content/site-a/ 아래의 콘텐츠는 영향을 받지 않습니다. 이 콘텐츠는 /content/site-a/.stat 파일과 비교됩니다. 두 개의 별도 무효화 도메인을 만들었습니다.

statfileslevel 1은(는) 다른 무효화 도메인을 만듭니다

statfileslevel "1"은(는) 다른 무효화 도메인을 만듭니다

대규모 설치는 일반적으로 조금 더 복잡하고 심층적으로 구성됩니다. 일반적인 스키마는 브랜드, 국가 및 언어별로 사이트를 구성하는 것입니다. 이 경우 statfileslevel을 더 높게 설정할 수 있습니다. 1 ​은(는) 브랜드당 무효화 도메인을 만들고, 국가당 2, 언어당 3 ​을(를) 만듭니다.

균질한 부위 구조의 필요성

statfileslevel은 설정의 모든 사이트에 동일하게 적용됩니다. 따라서 모든 사이트가 동일한 구조를 따르고 동일한 수준에서 시작해야 합니다.

포트폴리오에 일부 브랜드가 있으며 일부 브랜드는 소수의 작은 시장에서만 판매되고 다른 브랜드는 전 세계에서 판매된다고 가정해 보겠습니다. 작은 시장은 하나의 지역 언어만을 가지지만 세계 시장에는 두 개 이상의 언어가 사용되는 국가가 있습니다.

  /content/tiny-local-brand/finland/home
  /content/tiny-local-brand/finland/products
  /content/tiny-local-brand/finland/about
                              ^
                          /statfileslevel "2"
  …

  /content/tiny-local-brand/norway
  …

  /content/shiny-global-brand/canada/en
  /content/shiny-global-brand/canada/fr
  /content/shiny-global-brand/switzerland/fr
  /content/shiny-global-brand/switzerland/de
  /content/shiny-global-brand/switzerland/it
                                          ^
                                /statfileslevel "3"
  ..

전자는 2 ​의 statfileslevel이(가) 필요하지만 후자는 3 ​이(가) 필요합니다.

이상적인 상황은 아니야 3(으)로 설정하면 하위 분기 /home, /products/about 사이의 작은 사이트 내에서 자동 무효화가 작동하지 않습니다.

이 값을 2(으)로 설정하면 더 큰 사이트에서 /canada/en/canada/fr 종속 항목을 선언하고 있지만 선언하고 있지 않을 수 있습니다. 따라서 /en의 각 무효화도 /fr을(를) 무효화합니다. 이렇게 하면 캐시 적중률이 약간 줄어들지만 오래된 캐시된 콘텐츠를 전달하는 것보다 훨씬 좋습니다.

물론 가장 좋은 솔루션은 모든 사이트의 뿌리를 동일하게 깊게 만드는 것입니다.

/content/tiny-local-brand/finland/fi/home
/content/tiny-local-brand/finland/fi/products
/content/tiny-local-brand/finland/fi/about
…
/content/tiny-local-brand/norway/no/home
                                 ^
                        /statfileslevel "3"

사이트 간 연결

어느 수준이 적당할까요? 사이트 간 종속성 수에 따라 다릅니다. 페이지 렌더링에 대해 확인하는 포함은 "엄격한 종속성"으로 간주됩니다. 이 안내서 시작 부분에 티저 구성 요소를 도입했을 때 이러한 포함 ​을 보여 주었습니다.

하이퍼링크 ​는 더 부드러운 형식의 종속성입니다. 한 웹 사이트 내에서 하이퍼링크를 사용할 가능성이 높으며 웹 사이트 간에 링크가 있을 가능성도 낮지 않습니다. 단순 하이퍼링크는 일반적으로 웹 사이트 간에 종속성을 만들지 않습니다. 사이트에서 facebook으로 설정한 외부 링크만 생각해 보십시오. facebook에서 변경되는 내용이 있거나 그 반대로 변경되는 경우 페이지를 렌더링하지 않아도 됩니다.

연결된 리소스(예: 탐색 제목)에서 콘텐츠를 읽을 때 종속성이 발생합니다. 이와 같은 종속성은 로컬로 입력한 탐색 제목에만 의존하고 대상 페이지에서 가져오지 않는 경우(외부 링크에서처럼) 방지할 수 있습니다.

예기치 않은 종속성

그러나 설정에서 - 독립적인 것으로 가정되는 - 사이트가 함께 제공되는 부분이 있을 수 있습니다. 프로젝트 중 하나에서 얻은 실제 시나리오를 살펴보겠습니다.

고객은 마지막 장에 스케치된 것과 같은 사이트 구조를 가지고 있었습니다.

/content/brand/country/language

예:

/content/shiny-brand/switzerland/fr
/content/shiny-brand/switzerland/de

/content/shiny-brand/france/fr

/content/shiny-brand/germany/de

각 나라마다 고유한 영역이 있습니다.

www.shiny-brand.ch

www.shiny-brand.fr

www.shiny-brand.de

언어 사이트 간에 탐색할 수 있는 링크가 없고 명백한 포함이 없으므로 statfileslevel을 3으로 설정했습니다.

모든 사이트는 기본적으로 동일한 콘텐츠를 제공합니다. 유일한 차이점은 언어였다.

Google과 같은 검색 엔진은 다른 URL에 동일한 콘텐츠가 "기만적"인 것으로 간주합니다. 사용자는 동일한 콘텐츠를 제공하는 팜을 만들어 등급을 더 높게 매기거나 더 자주 나열하려고 할 수 있습니다. 검색 엔진은 이러한 시도를 인식하고 단순히 콘텐츠를 재활용하는 페이지의 등급을 실제로 낮춥니다.

각 페이지의 헤더 섹션에서 각 관련 페이지에 <link rel="alternate"> 태그를 설정하여 투명 순위를 매기고, 실제로는 동일한 콘텐츠를 가진 페이지가 두 개 이상 있으며, 시스템을 "게임"하려고 하지 않을 수 있습니다("Google에 페이지의 현지화된 버전에 대해 알리기" 참조).

# URL: www.shiny-brand.fr/fr/home/produits.html

<head>

  <link rel="alternate"
        hreflang="fr-ch"
        href="http://www.shiny-brand.ch/fr/home/produits.html">
  <link rel="alternate"
        hreflang="de-ch"
        href="http://www.shiny-brand.ch/de/home/produkte.html">
  <link rel="alternate"
        hreflang="de-de"
        href="http://www.shiny-brand.de/de/home/produkte.html">

</head>

----

# URL www.shiny-brand.de/de/home/produkte.html

<head>

  <link rel="alternate"
        hreflang="fr-fr"
        href="http://www.shiny-brand.fr/fr/home/produits.html">
  <link rel="alternate"
        hreflang="fr-ch"
        href="http://www.shiny-brand.ch/fr/home/produits.html">
  <link rel="alternate"
        hreflang="de-ch"
         href="http://www.shiny-brand.ch/de/home/produits.html">

</head>

모두 연결

모두 연결

일부 SEO 전문가는 이렇게 하면 한 언어로 순위가 높은 웹 사이트의 명성이나 "링크 주스"를 다른 언어로 동일한 웹 사이트로 전달할 수 있다고 주장하기도 합니다.

이 계획은 많은 링크뿐만 아니라 몇 가지 문제를 만들었습니다. n 언어로 p ​에 필요한 링크 수는 p x(n2-n) ​입니다. 각 페이지는 자체(-n)를 제외하고 서로 다른 페이지(n x n)에 연결됩니다. 이 구성표는 각 페이지에 적용됩니다. 4개 언어로 20페이지의 작은 사이트가 있는 경우 각각 240 ​개의 링크입니다.

먼저 편집기에서 이러한 링크를 수동으로 유지 관리하지 않도록 하십시오. 이러한 링크는 시스템에서 자동으로 생성되어야 합니다.

둘째, 정확해야 합니다. 시스템에서 새 "상대"를 감지할 때마다 동일한 콘텐츠(하지만 다른 언어)를 사용하는 다른 모든 페이지에서 연결하려고 합니다.

우리 프로젝트에서는 새로운 상대 페이지가 자주 떴다. 그러나 그들은 "대체" 연결로 구체화되지 않았다. 예를 들어 de-de/produkte 페이지가 독일 웹 사이트에 게시되었을 때 다른 사이트에서는 즉시 표시되지 않았습니다.

그 이유는, 우리의 설정에서 사이트들은 독립적이어야 했다. 따라서 독일 웹 사이트에서의 변경은 프랑스 웹 사이트에서의 무효화를 트리거하지 않았다.

이미 그 문제를 해결하는 방법을 알고 있을 겁니다. statfileslevel을 2로 낮추면 무효화 도메인이 넓어집니다. 물론, 캐시 적중률(특히 발행물 시)도 감소하므로 무효화가 더 자주 발생합니다.

우리의 경우에는 그것은 훨씬 더 복잡했습니다.

같은 내용을 가지고 있음에도 실제 그렇지 않은 브랜드 이름은 각 나라마다 달랐다.

shiny-brand은(는) 프랑스에서 marque-brillant, 독일에서 blitzmarke(으)로 호출되었습니다.

/content/marque-brillant/france/fr
/content/shiny-brand/switzerland/fr
/content/shiny-brand/switzerland/de
/content/blitzmarke/germany/de
…

이는 statfiles 수준을 1로 설정함을 의미합니다. 이로 인해 너무 큰 무효화 도메인이 발생할 수 있습니다.

그 부지를 재구조화하면 그것을 고칠 수 있었을 것이다. 모든 브랜드를 하나의 공통 루트 아래에 병합합니다. 하지만 그 당시에는 능력이 없었기 때문에 - 그것은 레벨 2만 주었을 것입니다.

우리는 레벨 3을 고수하기로 결정했고 항상 최신 "대체" 링크를 가지고 있지 않은 가격을 지불했습니다. 이를 완화하기 위해 Dispatcher에서 "리퍼" 크론 작업이 실행되어 1주 이상 지난 파일이 정리되었습니다. 결국 모든 페이지가 어느 시점에 다시 렌더링되었습니다. 그러나 그것은 각각의 프로젝트에서 개별적으로 결정되어야 하는 상충관계입니다.

결론

Dispatcher의 일반적인 작동 방식에 대한 몇 가지 기본 원칙을 설명했으며 이를 올바르게 수행하려면 구현 노력을 조금 더 기울여야 하고 균형을 맞출 수 있는 몇 가지 예를 제공했습니다.

Dispatcher에서 이 기능이 구성되는 방법에 대한 자세한 내용은 살펴보지 않았습니다. 우리는 당신이 너무 일찍 콘솔에 당신을 잃지 않고 먼저 기본 개념과 문제를 이해 하기를 원했습니다. 또한 실제 구성 작업이 잘 문서화되어 있습니다. 기본 개념을 이해한다면 다양한 스위치가 사용되는 용도를 알고 있어야 합니다.

Dispatcher 팁 및 요령

우리는 이 책의 첫 부분을 어떤 상황에서나 유용할 수 있는 힌트와 요령들의 무작위 수집으로 마무리 지을 것이다. 이전과 마찬가지로 솔루션을 제시하는 것이 아니라 아이디어를 통해 아이디어와 개념을 이해하고 실제 구성을 설명하는 기사에 보다 자세히 연결할 수 있습니다.

무효화 시기 수정

AEM Author 및 Publish을 즉시 설치하는 경우 토폴로지가 약간 이상합니다. 작성자는 Publish 시스템에 콘텐츠를 전송하는 동시에 Dispatcher에 무효화 요청을 전송합니다. Publish 시스템과 Dispatcher은 모두 큐에 의해 작성자와 분리되므로 시간이 다소 불행할 수 있습니다. Publish 시스템에서 콘텐츠가 업데이트되기 전에 Dispatcher은 작성자로부터 무효화 요청을 받을 수 있습니다.

그동안 클라이언트가 해당 콘텐츠를 요청하면 Dispatcher에서 오래된 콘텐츠를 요청하고 저장합니다.

보다 신뢰할 수 있는 설정은 컨텐츠를 받은 Publish 시스템 after ​에서 무효화 요청을 보냅니다. 문서 "게시 인스턴스에서 Dispatcher 캐시 무효화"는 세부 정보를 설명합니다.

참조

helpx.adobe.com - 게시 인스턴스에서 Dispatcher 캐시 무효화

HTTP 헤더 및 헤더 캐싱

옛날에는 Dispatcher이 파일 시스템에 일반 파일을 저장하고 있을 뿐이었다. 고객에게 전달할 HTTP 헤더가 필요한 경우 파일 또는 위치에서 얻은 작은 정보를 기반으로 Apache를 구성하여 이 작업을 수행했습니다. 이는 HTTP 헤더에 크게 의존하는 AEM에서 웹 애플리케이션을 구현할 때 특히 문제가 되었습니다. AEM 전용 인스턴스에서는 모든 것이 제대로 작동했지만 Dispatcher을 사용했을 때는 작동하지 않았습니다.

일반적으로 리소스 경로 및 접미사에 의해 파생될 수 있는 정보를 사용하여 mod_headers을(를) 사용하여 Apache 서버의 리소스에 누락된 헤더를 다시 적용하기 시작했습니다. 그러나 그것이 항상 충분하지는 않았다.

특히 Dispatcher을 사용하더라도 브라우저에 대한 첫 uncached 응답이 전체 범위의 헤더가 있는 Publish 시스템에서 나온 반면 후속 응답은 제한된 헤더 집합이 있는 Dispatcher에서 생성되었다는 것이 짜증스러웠습니다.

Dispatcher 4.1.11 이상에서 Dispatcher은 Publish 시스템에서 생성된 헤더를 저장할 수 있습니다.

이렇게 하면 Dispatcher에서 헤더 논리를 복제하지 않아도 되고 HTTP 및 AEM의 전체 표현력이 출시됩니다.

참조

개별 캐싱 예외

모든 페이지와 이미지를 일반적으로 캐시할 수 있지만, 경우에 따라 예외를 만듭니다. 예를 들어 PNG 이미지는 캐시하지만 CAPTCHA(각 요청에서 변경된다고 가정함)를 표시하는 PNG 이미지는 캐시하지 않으려고 합니다. Dispatcher은 captcha를 captcha로 인식하지 못할 수 있지만 AEM은 확실히 인식합니다. Dispatcher에 응답과 함께 헤더에 따라 을 전송하여 해당 요청을 캐시하지 않도록 요청할 수 있습니다.

  response.setHeader("Dispatcher", "no-cache");

  response.setHeader("Cache-Control: no-cache");

  response.setHeader("Cache-Control: private");

  response.setHeader("Pragma: no-cache");

Cache-Control 및 Pragma는 CDN과 같은 상위 캐싱 계층에 전파되고 해석되는 공식 HTTP 헤더입니다. Dispatcher 헤더는 Dispatcher이 캐시하지 않도록 하는 힌트일 뿐입니다. 상위 캐싱 계층에서 캐시하도록 하면서도 Dispatcher에 캐시하지 않도록 하는 데 사용할 수 있습니다. 사실, 그것이 유용할지도 모르는 사례를 찾는 것은 어렵습니다. 하지만 우리는 어딘가에는 몇 가지가 있다고 확신한다.

참조

브라우저 캐싱

가장 빠른 http 응답은 브라우저 자체에서 제공하는 응답입니다. 요청 및 응답이 네트워크를 통해 높은 부하를 받는 웹 서버로 이동할 필요가 없는 경우.

리소스에 대한 만료 날짜를 설정하여 브라우저가 서버에 파일의 새 버전을 요청할 시기를 결정할 수 있습니다.

일반적으로 Apache의 mod_expires을(를) 사용하거나 더 많은 개별 제어가 필요한 경우 AEM에서 제공되는 Cache-Control 및 Expires 헤더를 저장하여 정적으로 수행합니다.

브라우저에서 캐시된 문서는 세 가지 수준의 최신 상태를 가질 수 있습니다.

  1. 새로 고침 보장 - 브라우저에서 캐시된 문서를 사용할 수 있습니다.

  2. 부실 가능성이 있음 - 먼저 브라우저에서 캐시된 문서가 최신 상태인지 서버에 물어야 합니다.

  3. 부실 - 브라우저가 서버에 새 버전을 요청해야 합니다.

첫 번째는 서버에서 설정한 만료 날짜로 보장됩니다. 리소스가 만료되지 않은 경우 서버에 다시 문의할 필요가 없습니다.

해당 문서가 만료일에 도달한 경우에도 최신 상태로 유지됩니다. 만료 날짜는 문서가 전달될 때 설정됩니다. 그러나 새로운 콘텐츠를 언제 사용할 수 있는지 사전에 알지 못하는 경우가 종종 있습니다. 따라서 이는 보수적인 추정에 불과합니다.

브라우저 캐시의 문서가 새 요청에 전달할 문서와 같은지 확인하기 위해 브라우저는 문서의 Last-Modified 날짜를 사용할 수 있습니다. 브라우저가 서버에 다음과 같은 질문을 합니다.

"6월 10일 버전이 있습니다. 업데이트가 필요합니까?"을(를) 실행하면 서버가 다음으로 응답할 수 있습니다.

"304 - 리소스를 다시 전송하지 않고 버전이 아직 최신 상태입니다". 그렇지 않으면 서버가

"200 - HTTP 헤더의 최신 버전"과 HTTP 본문의 실제 최신 콘텐츠입니다.

두 번째 부분이 작동하도록 하려면 업데이트를 요청할 참조 지점이 있도록 Last-Modified 날짜를 브라우저에 전송해야 합니다.

앞에서 설명한 대로 Last-Modified 날짜가 Dispatcher에 의해 생성되면 브라우저에 의해 파일이 요청될 때 캐시된 파일(및 날짜의 파일)이 생성되기 때문에 요청마다 달라질 수 있습니다. 대안은 "e-tags"를 사용하는 것입니다. 이 숫자는 날짜 대신 실제 콘텐츠를 식별하는 숫자입니다(예: 해시 코드를 생성하여).

ACS Commons 패키지 ​의 "Etag 지원"에서 이 방법을 사용합니다. 그러나 가격과 함께 제공됩니다. E-Tag는 헤더로 전송해야 하지만 해시 코드 계산에서는 응답을 완전히 읽어야 하므로 응답이 배달되기 전에 기본 메모리에서 완전히 버퍼링되어야 합니다. 이 경우 웹 사이트에 캐시되지 않은 리소스가 더 있을 수 있고 AEM 시스템에서 사용하는 메모리를 주시해야 하는 경우 지연에 부정적인 영향을 미칠 수 있습니다.

URL 지문을 사용하는 경우 매우 긴 만료 날짜를 설정할 수 있습니다. 브라우저에서 지문 리소스를 영원히 캐시할 수 있습니다. 새 버전이 새 URL로 표시되어 이전 버전을 업데이트할 필요가 없습니다.

스풀러 패턴을 소개할 때 URL 지문을 활용했습니다. /etc/design(CSS, JS)에서 가져온 정적 파일은 거의 변경되지 않으므로 지문으로 사용하기에 적합한 후보입니다.

일반 파일의 경우 일반적으로 30분마다 HTML 재확인, 4시간마다 이미지 다시 확인 등과 같은 고정 체계를 설정합니다.

브라우저 캐싱은 작성자 시스템에서 매우 유용합니다. 편집 환경을 개선하기 위해 브라우저에서 최대한 캐시하려고 합니다. 안타깝게도 가장 비싼 자산인 html 페이지는 캐시될 수 없습니다. 작성자에서 자주 변경되어야 합니다.

AEM의 UI를 구성하는 Granite 라이브러리는 상당히 오랜 시간 동안 캐시될 수 있습니다. 브라우저에서 사이트의 정적 파일(글꼴, CSS 및 JavaScript)을 캐시할 수도 있습니다. /content/dam의 이미지도 페이지의 복사 텍스트만큼 자주 변경되지 않으므로 대개 15분 동안 캐시될 수 있습니다. 이미지는 AEM에서 대화식으로 편집되지 않습니다. 이러한 구성 요소는 AEM에 업로드되기 전에 먼저 편집되고 승인됩니다. 따라서 텍스트가 텍스트만큼 자주 변경되지 않는다고 가정할 수 있습니다.

편집 모드에 있을 때 UI 파일, 사이트 라이브러리 파일 및 이미지를 캐시하면 페이지 다시 로드 속도가 상당히 빨라집니다.

참조

*developer.mozilla.org - 캐싱

URL 자르기

리소스는 다음 위치에 저장됩니다.

/content/brand/country/language/…

그러나 물론 고객에게 표시하려는 URL은 아닙니다. 미관, 가독성 및 SEO 이유로 도메인 이름에 이미 표시된 부분을 자를 수 있습니다.

도메인이 있는 경우

www.shiny-brand.fi

보통 브랜드와 국가를 그 길에 넣을 필요가 없다. 대신,

www.shiny-brand.fi/content/shiny-brand/finland/fi/home.html

넌 그러고 싶겠지만

www.shiny-brand.fi/home.html

AEM에서 해당 매핑을 구현해야 합니다. AEM은 잘린 형식에 따라 링크를 렌더링하는 방법을 알아야 하기 때문입니다.

그러나 AEM에만 의존하지 마십시오. 이 경우 캐시의 루트 디렉터리에 /home.html과(와) 같은 경로가 있습니다. 이제, 그것이 피니시 또는 독일어 또는 캐나다 웹사이트의 "홈"입니까? 그리고 Dispatcher에 /home.html 파일이 있는 경우 /content/brand/fi/fi/home에 대한 무효화 요청이 들어올 때 Dispatcher에서 이를 무효화해야 한다는 것을 어떻게 알 수 있습니까?

각 도메인에 대해 별도의 docroot가 있는 프로젝트를 보았습니다. 디버깅하고 유지하는 것은 악몽이었고 - 실제로 우리는 그것이 완벽하게 실행되는 것을 보지 못했습니다.

우리는 캐시를 재구성하여 문제를 해결할 수 있다. 모든 도메인에 대한 단일 docroot가 있으며, 서버의 모든 파일이 /content(으)로 시작하므로 무효화 요청이 1:1로 처리될 수 있습니다.

자르는 부분도 아주 쉬웠어요. /etc/map의 해당 구성으로 인해 AEM에서 잘린 링크를 생성했습니다.

이제 요청 /home.html이(가) Dispatcher에 도달하고 있을 때 가장 먼저 내부적으로 경로를 확장하는 재작성 규칙을 적용합니다.

이 규칙은 각 vhost 구성에서 정적으로 설정되었습니다. 간단히 말해서, 규칙들은 이렇게 생겼습니다.

  # vhost www.shiny-brand.fi

  RewriteRule "^(.\*\.html)" "/content/shiny-brand/finland/fi/$1"

파일 시스템에는 작성자 및 Publish에서도 찾을 수 있는 일반 /content 기반 경로가 있으며, 이는 디버깅에 많은 도움이 되었습니다. 올바른 무효화는 말할 것도 없고, 더 이상 문제가 되지 않았습니다.

브라우저의 URL 슬롯에 표시되는 "표시" URL, URL에 대해서만 수행했습니다. 예를 들어 이미지의 URL은 여전히 순수 "/content" URL이었습니다. 검색 엔진 최적화는 기본 URL을 아름답게 하는 것으로 충분하다고 생각합니다.

하나의 공통 docroot가 갖는 또 다른 좋은 기능을 가지고있다. Dispatcher에서 문제가 발생하면 다음을 실행하여 전체 캐시를 지울 수 있습니다.

rm -rf /cache/dispatcher/*

(높은 로드 피크에서는 원하지 않을 수 있는 작업).

참조

오류 처리

AEM 클래스에서는 Sling에서 오류 핸들러를 프로그래밍하는 방법을 알아봅니다. 이는 일반적인 템플릿을 작성하는 것과 크게 다르지 않습니다. 간단히 템플릿을 JSP 또는 HTL로 작성합니까?

예 - 하지만 이것은 AEM 부분만 해당됩니다. Dispatcher이 404 – not found 또는 500 – internal server error 응답을 캐시하지 않습니다.

각(실패한) 요청에서 이러한 페이지를 동적으로 렌더링하는 경우 Publish 시스템에서 로드가 불필요하게 증가합니다.

우리가 유용하다고 생각하는 것은 오류가 발생할 때 전체 오류 페이지를 렌더링하지 않고 장식품이나 논리 없이 해당 페이지의 매우 단순하고 작은 정적 버전만 렌더링하는 것입니다.

물론 이것은 고객이 본 것이 아닙니다. Dispatcher에서 다음과 같이 ErrorDocuments을(를) 등록했습니다.

ErrorDocument 404 "/content/shiny-brand/fi/fi/edocs/error-404.html"
ErrorDocument 500 "/content/shiny-brand/fi/fi/edocs/error-500.html"

이제 AEM 시스템은 Dispatcher에 무언가 잘못되었음을 알릴 수 있으며 Dispatcher은 반짝이고 아름다운 버전의 오류 문서를 전달할 수 있습니다.

여기에 두 가지 사항이 명시되어야 합니다.

먼저 error-404.html은(는) 항상 같은 페이지입니다. 따라서 "제품"에 대한 검색 결과가 생성되지 않았습니다"와 같은 개별 메시지는 없습니다. 우리는 쉽게 그것을 받아들일 수 있습니다.

둘째… 내부 서버 오류가 표시되거나 AEM 시스템이 중단되는 경우 AEM에 오류 페이지를 렌더링하도록 요청할 방법이 없습니다. ErrorDocument 지시문에 정의된 필수 후속 요청도 실패합니다. wget을(를) 통해 정의된 위치에서 오류 페이지를 정기적으로 가져와서 ErrorDocuments 지시문에 정의된 정적 파일 위치에 저장하는 cron-job을 실행하여 이 문제를 해결했습니다.

참조

보호된 콘텐츠 캐싱

Dispatcher은 기본적으로 리소스를 전달할 때 권한을 확인하지 않습니다. 이 기능은 일부러 이렇게 구현됩니다. 공개 웹 사이트를 빠르게 하기 위해서입니다. 로그인하여 일부 리소스를 보호하려면 기본적으로 세 가지 옵션이 있습니다.

  1. Protect은 요청이 캐시에 도달하기 전에 리소스를 캐시에 저장합니다(예: Dispatcher 앞의 SSO(Single Sign-On) 게이트웨이에 의해 또는 Apache 서버의 모듈로)

  2. 중요한 리소스를 캐시되지 않도록 제외하므로 항상 Publish 시스템에서 라이브로 제공합니다.

  3. Dispatcher에서 권한 구분 캐싱 사용

그리고 물론 세 가지 접근 방식을 모두 자신만의 방식으로 적용할 수 있습니다.

옵션 1. 어차피 조직에서 "SSO" 게이트웨이를 적용할 수 있습니다. 액세스 체계가 매우 거칠게 구성된 경우 리소스에 대한 액세스 권한을 부여할지 또는 거부할지 여부를 결정하기 위해 AEM의 정보가 필요하지 않을 수 있습니다.

NOTE
이 패턴에는 각 요청을 가로채기 ​하고 Dispatcher에 대한 요청을 승인 또는 거부하는 실제 인증 ​을 수행하는 게이트웨이 ​가 필요합니다. SSO 시스템이 인증자 ​인 경우 옵션 3을 구현해야 하는 사용자의 ID만 설정됩니다. SSO 시스템의 안내서에서 "SAML" 또는 "OAauth"와 같은 용어를 읽는 경우 옵션 3을 구현해야 한다는 강력한 표시기입니다.

옵션 2. 일반적으로 "캐싱하지 않음"은 좋지 않은 생각입니다. 그 길로 가면 제외되는 트래픽의 양과 중요한 리소스의 수가 작은지 확인합니다. 또는 Publish 시스템에 일부 메모리 내 캐시가 설치되어 있어야 Publish 시스템에서 결과 로드를 처리할 수 있습니다. 이 시리즈의 Part III에 있는 해당 로드에 대해 자세히 알아보십시오.

옵션 3. "권한 구분 캐싱"은 흥미로운 접근 방식입니다. Dispatcher은 리소스를 캐시하고 있지만 전달하기 전에 AEM 시스템에 캐시할 수 있는지 여부를 묻습니다. 이렇게 하면 Dispatcher에서 Publish으로 추가 요청이 작성되지만, 페이지가 이미 캐시된 경우 일반적으로 Publish 시스템에서 페이지를 다시 렌더링하지 않습니다. 그러나 이 접근 방식에서는 몇 가지 사용자 지정 구현이 필요합니다. 자세한 내용은 권한 구분 캐싱 문서에서 확인하세요.

참조

유예 기간 설정

트리 활성화로 또는 콘텐츠를 최신 상태로 유지할 필요가 없는 등 짧은 연속으로 자주 무효화하는 경우 캐시를 지속적으로 플러시하고 방문자가 거의 항상 빈 캐시에 도달하게 될 수 있습니다.

아래 다이어그램은 단일 페이지에 액세스할 때 가능한 타이밍을 보여 줍니다. 요청된 다른 페이지의 수가 더 많아지면 문제는 물론 더 악화됩니다.

자주 활성화하면 대부분의 시간 동안 캐시가 잘못됨

자주 활성화하면 대부분의 시간 동안 캐시가 잘못됨

이러한 "캐시 무효화 폭풍"을 가끔 호출하여 문제를 완화하려면 statfile 해석이 덜 엄격할 수 있습니다.

자동 무효화에 grace period을(를) 사용하도록 Dispatcher을 설정할 수 있습니다. 이렇게 하면 내부적으로 statfiles 수정 날짜에 시간이 더 추가됩니다.

예를 들어 statfile의 수정 시간이 오늘 12시이고 gracePeriod이(가) 2분으로 설정되어 있습니다. 그런 다음 자동 무효화된 모든 파일은 12:01 및 12:02에 유효한 것으로 간주됩니다. 12:02 이후에 다시 렌더링됩니다.

참조 구성에서는 충분한 이유로 2분 gracePeriod을(를) 제안합니다. "2분? 거의 아무것도 아니에요. 내용이 나오기까지 10분 정도 기다릴 수 있습니다… 따라서 더 긴 기간을 설정하고 싶을 수 있습니다. 최소한 이 10분 후에 콘텐츠가 나타난다고 가정해 보겠습니다.

WARNING
gracePeriod이(가) 작동하는 방식이 아닙니다. 유예 기간은 문서가 무효화되어야 하지만 무효화되지 않는 시간대인 not ​입니다. 이 프레임 내에 있는 이후의 각 무효화는 시간대를 연장 ​합니다. 무기한으로 길어질 수 있습니다.

예를 통해 gracePeriod이(가) 실제로 작동하는 방식을 보여 드리겠습니다.

예를 들어 미디어 사이트를 운영하고 있으며 편집 직원이 5분마다 정기적인 콘텐츠 업데이트를 제공하고 있습니다. gracePeriod를 5분으로 설정하는 것이 좋습니다.

12:00에 간단한 예제로 시작하겠습니다.

12:00 - Statfile이 12:00으로 설정되어 있습니다. 캐시된 모든 파일은 12:05까지 유효한 것으로 간주됩니다.

12:01 - 무효화가 발생합니다. 이렇게 하면 그레이트 시간이 12:06으로 늘어납니다.

12:05 - 다른 편집자 그의 기사를 게시 - 다른 유예 기간 12:10으로 유예 시간을 연장합니다.

그리고 그 내용은 무효화되지 않습니다. 각 무효화는 within gracePeriod를 통해 유예 시간을 효과적으로 연장합니다. gracePeriod은(는) 무효화 폭풍을 견딜 수 있도록 설계되었습니다. 하지만 결국에는 비를 맞아야 합니다… 따라서 대피소에 영원히 숨지 않도록 gracePeriod을(를) 상당히 짧게 유지하십시오.

결정론적 유예 기간

무효화 폭풍을 어떻게 견뎌낼 수 있는지 다른 아이디어를 소개하고자 합니다. 그것은 단지 생각일 뿐이다. 프로덕션에서 시도한 적은 없지만, 아이디어를 공유하기에 충분히 흥미로운 컨셉을 찾았습니다.

gracePeriod은(는) 일반 복제 간격이 gracePeriod보다 짧으면 예상할 수 없을 정도로 길어질 수 있습니다.

대체 아이디어는 다음과 같습니다. 고정된 시간 간격에서만 무효화하십시오. 사이의 시간은 항상 오래된 콘텐츠를 제공하는 것을 의미합니다. 무효화는 결국 발생하지만, 여러 무효화가 하나의 "일괄" 무효화에 수집되므로 Dispatcher은 그동안 캐시된 콘텐츠를 제공하고 Publish 시스템에 숨 쉴 수 있는 공기를 제공할 수 있습니다.

구현은 다음과 같습니다.

무효화가 발생한 후에 실행되는 "사용자 지정 무효화 스크립트"(참조)를 사용합니다. 이 스크립트는 statfile's 마지막 수정 날짜를 읽고 다음 간격 중지로 반올림합니다. Unix 셸 명령 touch --time에서 시간을 지정하겠습니다.

예를 들어 유예 기간을 30초로 설정하면 Dispatcher이 statfile의 마지막 수정 날짜를 다음 30초로 반올림합니다. 사이에 발생하는 무효화 요청은 다음 전체 30초를 동일하게 설정합니다.

무효화를 다음 전체 30초로 연기하면 적중률이 증가합니다.

무효화를 다음 전체 30초로 연기하면 적중률이 증가합니다.

무효화 요청과 다음 라운드 30초 슬롯 사이에 발생하는 캐시 히트는 오래된 것으로 간주됩니다. Publish에 업데이트가 있지만 Dispatcher은 여전히 이전 콘텐츠를 제공합니다.

이 접근 방식은 후속 요청이 기간을 비결정적으로 연장한다는 것을 두려워하지 않고도 더 긴 유예 기간을 정의하는 데 도움이 될 수 있습니다. 이전에 언급했듯이, 그것은 단지 아이디어일 뿐이고 우리는 그것을 시험해 볼 기회가 없었습니다.

참조

helpx.adobe.com - Dispatcher 구성

자동 재가져오기

사이트에 매우 특별한 액세스 패턴이 있습니다. 들어오는 트래픽의 부하가 높고 대부분의 트래픽이 페이지의 작은 부분에 집중됩니다. 홈 페이지, 캠페인 랜딩 페이지 및 주요 제품 세부 사항 페이지에는 트래픽의 90%가 전송됩니다. 또는 새 사이트를 운영하는 경우 최신 문서가 이전 문서에 비해 더 높은 트래픽 수를 갖습니다.

이제 이러한 페이지는 너무 자주 요청되므로 Dispatcher에 캐시될 가능성이 높습니다.

임의 무효화 요청이 Dispatcher으로 전송되어 가장 인기 있는 한 페이지를 포함하여 모든 페이지가 무효화됩니다.

따라서 이러한 페이지가 매우 인기 있으므로 다른 브라우저에서 새로 들어오는 요청이 있습니다. 홈 페이지를 예로 들어 보겠습니다.

현재 캐시가 유효하지 않기 때문에, 동시에 들어오는 모든 홈 페이지 요청은 높은 로드를 생성하는 Publish 시스템으로 전달됩니다.

빈 캐시의 동일한 리소스에 대한 병렬 요청: 요청이 Publish으로 전달됩니다

빈 캐시의 동일한 리소스에 대한 병렬 요청: 요청이 Publish으로 전달됩니다

자동 다시 가져오기를 사용하면 이를 어느 정도 완화할 수 있습니다. 대부분의 무효화된 페이지는 자동 무효화 이후에도 여전히 물리적으로 Dispatcher에 저장됩니다. 고려됨 ​일 뿐입니다. 자동 다시 가져오기 ​는 오래된 콘텐츠를 다시 가져오기 위해 게시 시스템에 대한 단일 요청을 시작하는 동안 이러한 오래된 페이지를 몇 초 동안 계속 제공함을 의미합니다.

백그라운드에서 다시 가져오는 동안 오래된 콘텐츠 제공

백그라운드에서 다시 가져오는 동안 오래된 콘텐츠 제공

다시 가져오기를 활성화하려면 자동 무효화 후에 다시 가져올 리소스를 Dispatcher에 알려 주어야 합니다. 활성화한 모든 페이지는 인기 있는 페이지를 포함하여 다른 모든 페이지를 자동 무효화한다는 것을 기억하십시오.

다시 가져오기는 실제로 각 (!)의 Dispatcher에 알리는 것을 의미합니다. 가장 방문 빈도가 높은 항목과 가장 방문 빈도가 높은 항목을 다시 가져오려는 무효화 요청.

이는 리소스 URL(경로뿐만 아니라 실제 URL) 목록을 무효화 요청 본문에 넣음으로써 수행됩니다.

POST /dispatcher/invalidate.cache HTTP/1.1

CQ-Action: Activate
CQ-Handle: /content/my-brand/home/path/to/some/resource
Content-Type: Text/Plain
Content-Length: 207

/content/my-brand/home.html
/content/my-brand/campaigns/landing-page-1.html
/content/my-brand/campaigns/landing-page-2.html
/content/my-brand/products/product-1.html
/content/my-brand/products/product-2.html

Dispatcher에 이러한 요청이 표시되면 평소와 같이 자동 무효화가 트리거되고 Publish 시스템에서 새로운 콘텐츠를 다시 가져오기 위한 요청이 즉시 대기됩니다.

이제 요청 본문을 사용하므로 HTTP 표준에 따라 콘텐츠 유형 및 콘텐츠 길이도 설정해야 합니다.

또한 Dispatcher은 내부적으로 해당 URL을 표시하여 자동 무효화로 인해 이러한 리소스를 유효하지 않은 것으로 간주되더라도 이러한 리소스를 직접 전달할 수 있음을 알게 됩니다.

나열된 모든 URL이 하나씩 요청됩니다. 따라서 Publish 시스템에서 너무 높은 로드를 생성하는 것에 대해 걱정할 필요가 없습니다. 그러나 해당 목록에 URL을 너무 많이 넣고 싶지는 않습니다. 결국 너무 오랫동안 오래된 콘텐츠를 제공하지 않도록 제한된 시간 내에 큐를 처리해야 합니다. 가장 자주 액세스하는 10개의 페이지를 포함시키기만 하면 됩니다.

Dispatcher의 캐시 디렉터리를 살펴보면 타임스탬프로 표시된 임시 파일이 표시됩니다. 이러한 파일은 현재 백그라운드에서 로드되고 있습니다.

참조

helpx.adobe.com - AEM에서 캐시된 페이지 무효화

Publish 시스템 보호

Dispatcher은 유지 관리 목적으로만 사용되는 요청에서 Publish 시스템을 차단하여 약간의 추가 보안을 제공합니다. 예를 들어 /crx/de 또는 /system/console URL을 공개하지 않습니다.

시스템에 WAF(Web Application Firewall)가 설치되어 있어도 문제가 없습니다. 그러나 이는 귀하의 예산에 상당한 양을 추가하며 모든 프로젝트가 WAF를 운영 및 유지 관리할 수 있는 여유가 있는 상황은 아닙니다.

자주 표시되는 것은 더 취약한 리소스에 대한 액세스를 방지하는 Dispatcher 구성의 Apache 재작성 규칙 세트입니다.

그러나 다른 접근 방식을 고려할 수도 있습니다.

Dispatcher 구성에 따르면 Dispatcher 모듈은 특정 디렉터리에 바인딩됩니다.

<Directory />
  SetHandler dispatcher-handler
  …
</Directory>

하지만 이후에 필터링해야 할 때 왜 핸들러를 전체 docroot에 바인딩합니까?

우선 처리기의 바인딩 범위를 좁힐 수 있습니다. SetHandler이(가) 핸들러를 디렉터리에 바인딩하면 핸들러를 URL 또는 URL 패턴에 바인딩할 수 있습니다.

<LocationMatch "^(/content|/etc/design|/dispatcher/invalidate.cache)/.\*">
  SetHandler dispatcher-handler
</LocationMatch>

<LocationMatch "^/dispatcher/invalidate.cache">
  SetHandler dispatcher-handler
</LocationMatch>

…

이렇게 하는 경우 항상 Dispatcher-handler를 Dispatcher의 무효화 URL에 바인딩해야 합니다. 이렇게 하지 않으면 AEM에서 Dispatcher으로 무효화 요청을 보낼 수 없습니다.

Dispatcher을 필터로 사용하는 또 다른 방법은 dispatcher.any에서 필터 지시문을 설정하는 것입니다.

/filter {
  /0001  { /glob "\*" /type "deny" }
  /0002  { /type "allow"  /url "/content\*"  }

우리는 한 지시어의 사용을 다른 지시어의 사용을 의무화하고 있는 것이 아니라 모든 지시어의 적절한 혼합을 권장하고 있다.

그러나 필요한 만큼 가능한 한 빨리 체인 내에 URL 공간을 좁히고 가능한 가장 간단한 방법으로 좁히는 것을 고려해 볼 것을 제안합니다. 이러한 기술은 매우 민감한 웹 사이트에서 WAF를 대체하는 것이 아니라는 점을 여전히 명심하십시오. 어떤 사람들은 이런 기술을 "가난한 사람의 방화벽" 이라고 부르는데, 그 이유가 있다.

참조

apache.org- sethandler 지시문

helpx.adobe.com - 콘텐츠 필터에 대한 액세스 구성

정규 표현식 및 글로브를 사용한 필터링

초기에는 "globs" - 간단한 자리 표시자만 사용하여 Dispatcher 구성에서 필터를 정의할 수 있었습니다.

다행히도 Dispatcher의 이후 버전에서 변경되었습니다. 이제 POSIX 정규 표현식도 사용할 수 있으며 요청의 다양한 부분에 액세스하여 필터를 정의할 수 있습니다. Dispatcher을 처음 사용하는 사람은 당연하게 여길 수 있습니다. 하지만 여러분이 글로브만 가지고 있다면, 그것은 놀라운 일이고 쉽게 간과될 수 있습니다. globs와 regexes의 구문 외에도 너무 비슷하다. 동일한 작업을 수행하는 두 버전을 비교해 보겠습니다.

# Version A

/filter {
  /0001  { /glob "\*" /type "deny" }
  /0002  { /type "allow"  /url "/content\*"  }

# Version B

/filter {
  /0001  { /glob "\*" /type "deny" }
  /0002  { /type "allow"  /url '/content.\*'  }

차이점이 보이나요?

버전 B에서는 작은 따옴표 '을(를) 사용하여 정규 표현식 패턴 ​을(를) 표시합니다. .*을(를) 사용하여 "모든 문자"를 표현합니다.

글로빙 패턴 ​과(와) 반대로 큰따옴표 "을(를) 사용하며 *과(와) 같은 간단한 자리 표시자만 사용할 수 있습니다.

이러한 차이점을 알고 있다면 사소한 것이지만, 그렇지 않은 경우 구성 디버깅 시 따옴표를 쉽게 혼동하고 화창한 오후를 보낼 수 있습니다. 이제 경고 받으세요.

"구성에서 '/url'을(를) 인식합니다… 하지만 요청할 수 있는 필터의 '/glob'은(는) 무엇입니까?

해당 지시문은 메서드 및 경로를 포함하여 전체 요청 문자열을 나타냅니다. 그것은 유효할 수 있다

"GET /content/foo/bar.html HTTP/1.1"

패턴을 비교할 문자열입니다. 초보자는 첫 번째 부분인 method(GET, POST, …)을 잊어버리는 경향이 있습니다. 그래서, 패턴이

/0002 { /glob "/content/\*" /type "allow" }

"/content"가 "GET …"와 일치하지 않으면 항상 실패합니다. 요청.

Globs를 사용하고 싶을 때는

/0002 { /glob "GET /content/\*" /type "allow" }

맞겠죠.

다음과 같은 초기 거부 규칙의 경우

/0001 { /glob "\*" /type "deny" }

이거라도 괜찮아요 그러나 차후 허용의 경우 요청의 개별 부분을 사용하는 것이 더 낫고 명확하며 보다 안전한 방법입니다.

/method
/url
/path
/selector
/extension
/suffix

다음과 같이:

/005  {

  /type "allow"
  /method "GET"
  /extension '(css|gif|ico|js|png|swf|jpe?g)' }

규칙에서 regex와 glob 표현식을 혼합할 수 있습니다.

각 정의 앞에 있는 /005과(와) 같은 "줄 번호"에 대한 마지막 단어

그들은 전혀 의미가 없어요! 규칙에 대한 임의의 분모를 선택할 수 있습니다. 숫자를 사용하는 것은 도식을 생각하는 데 많은 노력을 필요로 하지 않지만, 순서는 중요하다는 것을 명심하십시오.

다음과 같은 규칙이 수백 개 있는 경우:

/001
/002
/003
…
/100
…

/001과 /002 사이에 숫자를 삽입하려면 다음 숫자는 어떻게 됩니까? 그 수를 늘리고 있습니까? 중간 값을 삽입하고 있습니까?

/001
/001a
/002
/003
…
/100
…

또는 /003 및 /001을 다시 정렬하도록 변경할 때 이름과 ID를 변경할 예정이거나

/003
/002
/001
…
/100
…

번호 매기기는 애초에 단순한 선택처럼 보이다가 장기적으로 한계에 다다른다. 솔직히 말해, 식별자를 선택하는 것은 나쁜 프로그래밍 방식입니다.

다른 접근 방식을 제안하려고 합니다. 각 개별 필터 규칙에 대해 의미 있는 식별자가 제공되지 않을 가능성이 높습니다. 하지만 그들은 아마도 더 큰 목적을 제공하기 때문에, 그 목적에 따라 몇 가지 방법으로 그룹화될 수 있습니다. 예를 들어 "기본 설정", "애플리케이션별 예외", "전역 예외" 및 "보안"이 있습니다.

그런 다음 규칙에 따라 이름을 지정하고 그룹화할 수 있으며 구성 리더(친애하는 동료)에게 파일의 일부 방향을 제공할 수 있습니다.

  # basic setup:

  /filter {

    # basic setup

    /basic_01  { /glob "\*"             /type "deny"  }
    /basic_02  { /glob "/content/\*"    /type "allow" }
    /basic_03  { /glob "/etc/design/\*" /type "allow" }

    /basic_04  { /extension '(json|xml)'  /type "deny"  }
    …


    # login

    /login_01 { /glob "/api/myapp/login/\*" /type "allow" }
    /login_02 { … }

    # global exceptions

    /global_01 { /method "POST" /url '.\*contact-form.html' }

그룹 중 하나에 새 규칙을 추가하거나 새 그룹을 만들 수 있습니다. 이 경우 이름 변경/번호 다시 매기기 항목 수는 해당 그룹으로 제한됩니다.

WARNING
보다 정교한 설정은 필터링 규칙을 기본 dispatcher.any 구성 파일에 포함된 여러 파일로 분할합니다. 그러나 새 파일에는 새 네임스페이스가 도입되지 않습니다. 따라서 한 파일에 규칙 "001"이 있고 다른 파일에 규칙 "001"이 있는 경우 오류가 발생합니다. 의미상 강력한 이름을 생각해 내야 하는 이유가 더 있다.

참조

helpx.adobe.com - glob 속성에 대한 패턴 디자인

프로토콜 사양

마지막 팁은 진짜 팁이 아니지만, 어쨌든 당신과 공유할 가치가 있다고 느꼈습니다.

대부분의 경우 AEM 및 Dispatcher은 즉시 사용할 수 있습니다. 따라서 최상위 애플리케이션 빌드를 위한 무효화 프로토콜에 대한 포괄적인 Dispatcher 프로토콜 사양은 찾지 못할 것입니다. 그 정보는 공개적이지만, 약간 많은 자원에 흩어져 있습니다.

우리는 여기서 그 공백을 어느 정도 메우려고 노력한다. 무효화 요청은 다음과 같습니다.

POST /dispatcher/invalidate.cache HTTP/1.1
CQ-Action: <action>
CQ-Handle: <path-pattern>
[CQ-Action-Scope]
[Content-Type: Text/Plain]
[Content-Length: <bytes in request body>]

<newline>

<refetch-url-1>
<refetch-url-2>

…

<refetch-url-n>

POST /dispatcher/invalidate.cache HTTP/1.1 - 첫 번째 줄은 Dispatcher 컨트롤 끝점의 URL이므로 변경하지 않을 수 있습니다.

CQ-Action: <action> - 수행할 작업 <action>은(는) 다음 중 하나입니다.

  • Activate:이(가) /path-pattern.*을(를) 삭제합니다.
  • Deactive: /path-pattern.* 삭제
    /path-pattern/* 삭제
  • Delete: /path-pattern.* 삭제
    /path-pattern/* 삭제
  • Test: "ok"를 반환하지만 아무 작업도 하지 않음

CQ-Handle: <path-pattern> - 무효화할 콘텐츠 리소스 경로입니다. <path-pattern>은(는) 실제로 "경로"이며 "패턴"은 아닙니다.

CQ-Action-Scope: ResourceOnly - 선택 사항: 이 헤더가 설정된 경우 .stat 파일이 터치되지 않습니다.

[Content-Type: Text/Plain]
[Content-Length: <bytes in request body>]

자동 재가져오기 URL 목록을 정의하는 경우 이러한 헤더를 설정합니다. <bytes in request body>은(는) HTTP 본문의 문자 수입니다.

<newline> - 요청 본문이 있는 경우 헤더에서 빈 행으로 구분해야 합니다.

<refetch-url-1>
<refetch-url-2>
…
<refetch-url-n>

무효화된 후 즉시 다시 가져올 URL을 나열합니다.

추가 리소스

Dispatcher 캐싱에 대한 유용한 개요 및 소개: https://helpx.adobe.com/kr/experience-manager/dispatcher/using/dispatcher.html

모든 지시문이 포함된 Dispatcher 설명서에 대해 설명합니다. https://helpx.adobe.com/kr/experience-manager/dispatcher/using/dispatcher-configuration.html

몇 가지 자주 묻는 질문: https://helpx.adobe.com/kr/experience-manager/using/dispatcher-faq.html

Dispatcher 최적화에 대한 웨비나 녹화 - 적극 권장: https://my.adobeconnect.com/p7th2gf8k43?proto=true

프레젠테이션 "컨텐츠 무효화의 저평가된 능력", "adaptTo()" 컨퍼런스(Potsdam 2018 https://adapt.to/2018/en/schedule/the-underappreciated-power-of-content-invalidation.html)

AEM에서 캐시된 페이지 무효화: https://helpx.adobe.com/kr/experience-manager/dispatcher/using/page-invalidate.html

다음 단계

recommendation-more-help
aeb7eb84-65b7-4bed-b296-3028319d2331