# Clustering

OvenMediaEngine은 클러스터링을 지원하며 고가용성(HA)과 확장성을 보장합니다. 이를 위해 `OriginMap` 및 `OriginMapStore` 기능을 제공합니다. [OriginMap](#originmap)은 각 엣지(Edge) 서버에 오리진(Origin) 서버 정보를 구성하는 방식이고, [OriginMapStore](#originmapstore)는 오리진 서버와 엣지 서버가 Redis 서버를 통해 동적으로 정보를 공유하는 방식입니다.

## OriginMap

<figure><img src="/files/DZrSqnximMDQOhp4M8b0" alt=""><figcaption></figcaption></figure>

엣지로 실행되는 OvenMediaEngine은 사용자가 요청할 때 외부 서버에서 스트림을 가져옵니다(pull). 외부 서버는 OVT가 활성화된 다른 OvenMediaEngine이거나 RTSP를 지원하는 다른 스트림 서버일 수 있습니다.

OVT는 Origin-Edge 간에 스트림을 중계하기 위해 OvenMediaEngine에서 정의한 프로토콜이며 OVT는 SRT 및 TCP를 통해 실행될 수 있습니다. SRT 프로토콜에 대한 자세한 내용은 [SRT Alliance](https://www.srtalliance.org/) 사이트를 방문해 주십시오.

### Origin&#x20;

OvenMediaEngine은 오리진에서 엣지로 스트림을 전달하기 위한 OVT 프로토콜을 제공합니다. OvenMediaEngine을 오리진으로 실행하려면 다음과 같이 OVT 포트 및 OVT 퍼블리셔(Publisher)를 활성화해야 합니다:

```xml
<Server version="5">
	<Bind>
		<Publishers>
			<OVT>
				<Port>9000</Port>
			</OVT>
		</Publishers>
	</Bind>
	<VirtualHosts>
    		<VirtualHost>
		    	<Applications>
				<Application>
					...
					<Publishers>
						<OVT />
					</Publishers>
				</Application>		
			</Applications>
		</VirtualHost>
	</VirtualHosts>
</Server>
```

### Edge

엣지의 역할은 오리진으로부터 스트림을 수신하고 분배하는 것입니다. 수백 개의 엣지를 구성하여 플레이어로 트래픽을 분산시킬 수 있습니다. 테스트 결과, 단일 엣지는 AWS C5.2XLarge를 기준으로 WebRTC를 통해 4-5Gbps 트래픽을 스트리밍할 수 있었습니다. 수천 명에게 스트리밍해야 하는 경우 여러 엣지를 구성하여 사용할 수 있습니다.

엣지는 오리진에서 스트림을 가져오기 위해 OVT와 RTSP를 지원합니다. 가까운 시일 내에 더 많은 프로토콜을 지원할 예정입니다. OVT를 통해 가져온 스트림은 인코딩되지 않고 우회(bypass)됩니다.

OvenMediaEngine을 엣지로 실행하려면 다음과 같이 설정 파일에 Origins 엘리먼트를 추가해야 합니다:

```markup
<VirtualHosts>
    <VirtualHost>
        <Origins>
            <Properties>
                <NoInputFailoverTimeout>3000</NoInputFailoverTimeout>
                <UnusedStreamDeletionTimeout>60000</UnusedStreamDeletionTimeout>
            </Properties>
            <Origin>
                <Location>/app/stream</Location>
                <Pass>
                    <Scheme>ovt</Scheme>
                    <Urls><Url>origin.com:9000/app/stream_720p</Url></Urls>
                    <ForwardQueryParams>true</ForwardQueryParams>
                </Pass>
            </Origin>
            <Origin>
                <Location>/app/</Location>
                <Pass>
                    <Scheme>OVT</Scheme>
                    <Urls><Url>origin.com:9000/app/</Url></Urls>
                </Pass>
            </Origin>
            <Origin>
                <Location>/</Location>
                <Pass>
                    <Scheme>RTSP</Scheme>
                    <Urls><Url>origin2.com:9000/</Url></Urls>
                </Pass>
            </Origin>
        </Origins>
    </VirtualHost>
</VirtualHosts>
```

`<Origin>`은 어떤 요청에 대해 어디서 스트림을 가져올지에 대한 규칙입니다.

`<Origin>`은 `<Location>`에 설정한 애플리케이션이 서버에 존재하지 않을 경우 해당 이름으로 애플리케이션을 자동으로 생성하는 기능이 있습니다. 시스템에 애플리케이션이 존재하면 해당 애플리케이션에 스트림이 생성됩니다.

#### \<Properties>

<mark style="color:purple;">**NoInputFailoverTimeout**</mark>**&#x20;(default 3000)**

NoInputFailoverTimeout은 설정된 시간 동안 입력이 없을 경우 다음 URL로 전환하기까지의 시간(밀리초)입니다.

<mark style="color:blue;">**UnusedStreamDeletionTimeout**</mark>**&#x20;(default 60000)**

UnusedStreamDeletionTimeout은 설정된 시간(밀리초) 동안 시청자가 없으면 OriginMap으로 생성된 스트림을 삭제하는 기능입니다. 이는 오리진과 엣지의 네트워크 트래픽과 시스템 리소스를 절약하는 데 도움이 됩니다.

#### \<Origin>

Origin의 엘리먼트에 대한 자세한 설명은 다음과 같습니다:

<mark style="color:blue;">**Location**</mark>

Origin은 VirtualHost에 속해 있기 때문에 이미 도메인으로 필터링되어 있습니다. 따라서 Location에는 도메인 영역을 제외하고 일치시킬 App, Stream, File을 설정합니다. 요청이 여러 Origin과 일치하는 경우 그중 가장 위에 있는 것이 실행됩니다.

<mark style="color:blue;">**Pass**</mark>

Pass는 Scheme과 Url로 구성됩니다.

`<Scheme>`은 오리진 스트림에서 가져올 때 사용할 프로토콜입니다. 현재 `OVT` 또는 `RTSP`로 구성할 수 있습니다.

오리진 서버가 OvenMediaEngine인 경우 `<Scheme>`에 `OVT`를 설정해야 합니다.

`<Scheme>`에 `RTSP`를 설정하여 RTSP 서버에서 스트림을 가져올 수 있습니다. 이 경우 `<RTSPPull>` 프로바이더(provider)가 활성화되어 있어야 합니다. Origin에 의해 자동으로 생성되는 애플리케이션은 모든 프로바이더가 활성화되므로 걱정할 필요가 없습니다.

`Urls`는 오리진 스트림의 주소이며 여러 개의 URL로 구성될 수 있습니다.

`ForwardQueryParams`는 재생을 요청한 URL의 쿼리 스트링 부분을 서버로 전달할지 여부를 결정하는 옵션입니다.(**기본값 : true**) 일부 RTSP 서버는 쿼리 스트링에 따라 스트림을 분류하므로 이 옵션을 false로 설정하고 싶을 수 있습니다. 예를 들어, 사용자가 WebRTC를 재생하기 위해 `ws://host:port/app/stream?transport=tcp`를 요청하면 `?transport=tcp` 또한 RTSP 서버로 전달될 수 있으므로 RTSP 서버에서 스트림을 찾지 못할 수 있습니다. 반면 OVT는 아무런 영향을 미치지 않으므로 기본 설정으로 사용할 수 있습니다.

### Rules for generating Origin URL

OvenMediaEngine이 요청할 최종 주소는 설정된 Url과 Location을 제외한 사용자의 요청을 결합하여 생성됩니다. 예를 들어 다음과 같이 설정된 경우:

```markup
<Location>/edge_app/</Location>
<Pass>
    <Scheme>ovt</Scheme>
    <Urls><Url>origin.com:9000/origin_app/</Url></Urls>
</Pass>
```

사용자가 `http://edge.com/edge_app/stream`을 요청하면 OvenMediaEngine은 `ovt://origin.com:9000/origin_app/stream`으로 주소를 만듭니다.

## OriginMapStore

<figure><img src="/files/jAgzN8osLRcxBZ26YCyY" alt=""><figcaption></figcaption></figure>

`OriginMapStore`는 클러스터 내에서 자동 확장(autoscaling)을 쉽게 지원하도록 설계되었습니다. 클러스터 내의 모든 오리진 서버와 엣지 서버는 Redis를 통해 스트림 정보와 오리진 OVT URL을 공유합니다. 즉, 오리진 서버에 스트림이 생성되면 오리진 서버는 해당 스트림에 접근하기 위한 app/stream 이름과 OVT URL을 Redis 서버에 설정합니다. 엣지는 사용자의 재생 요청이 들어올 때 Redis 서버로부터 해당 `app/stream`에 해당하는 OVT URL을 가져옵니다.

이는 오리진 서버와 엣지 서버를 확장할 때 기존 설정을 업데이트할 필요가 없음을 의미합니다. 따라서 모든 오리진을 하나의 도메인으로 그룹화하고, 모든 엣지를 하나의 도메인으로 묶을 수 있습니다. `OriginMapStore`를 사용하면 추가 구성 없이 클러스터 내에서 오리진 또는 엣지를 확장할 수 있습니다.

`OriginMapStore` 기능은 Redis Server 5.0.7로 테스트되었습니다. 오리진과 엣지의 Server.xml에 다음 설정을 추가하여 이 기능을 활성화할 수 있습니다. 오리진 서버의 Server.xml에는 반드시 설정해야 한다는 점에 유의하십시오. 이는 오리진이 자신의 OVT URL을 등록할 때 사용되므로 OVT 퍼블리셔(publisher)로 접근할 수 있는 도메인 이름이나 IP 주소만 설정하면 됩니다.

{% code overflow="wrap" %}

```xml
<VirtualHost>
    ...
    <OriginMapStore>
        <!-- In order to use OriginMap, you must enable OVT Publisher in Origin and OVT Provider in Edge. -->
        <RedisServer>
            <Host>192.168.0.160:6379</Host>
            <Auth>!@#ovenmediaengine</Auth>
        </RedisServer>
        
        <!-- This is only needed for the origin server and used to register the ovt address of the stream.  -->
        <OriginHostName>ome-dev.airensoft.com</OriginHostName>
    </OriginMapStore>
    ...
</VirtualHost>
```

{% endcode %}

## Dynamic Application

엣지 서버가 모든 애플리케이션을 미리 구성하는 것은 불가능하거나 매우 번거로운 일입니다. 그래서 `OriginMap`과 `OriginMapStore`는 스트림을 생성할 때 애플리케이션이 존재하지 않으면 동적으로 애플리케이션을 생성하는 기능이 있습니다. `<Name>*</Name>`으로 애플리케이션 구성을 복사하여 새로운 애플리케이션을 생성합니다. 즉, 이름이 `*`인 특별한 애플리케이션이 동적 애플리케이션 템플릿입니다.

```xml
<Applications>
    <Application>
        <Name>*</Name>
        <Type>live</Type>
        <OutputProfiles>
            ...
        </OutputProfiles>
        <Providers>
            <OVT />
        </Providers>
        <Publishers>
            <AppWorkerCount>1</AppWorkerCount>
            <StreamWorkerCount>8</StreamWorkerCount>
            <WebRTC>
                <Timeout>30000</Timeout>
                <Rtx>false</Rtx>
                <Ulpfec>false</Ulpfec>
                <JitterBuffer>false</JitterBuffer>
            </WebRTC>
            <LLHLS>
                <ChunkDuration>0.5</ChunkDuration>
                <SegmentDuration>6</SegmentDuration>
                <SegmentCount>10</SegmentCount>
                <CrossDomains>
                    <Url>*</Url>
                </CrossDomains>
            </LLHLS>
        </Publishers>
    </Application>
</Applications>
```

## Load Balancer

로드 밸런서를 구성할 때 L4 스위치, LVS 또는 GSLB와 같은 타사 솔루션을 사용해야 하지만 DNS 라운드 로빈(Round Robin) 사용을 권장합니다. 또한 클라우드 기반의 [AWS Route53](https://aws.amazon.com/route53/?nc1=h_ls), [Azure DNS](https://azure.microsoft.com/en-us/services/dns/) 또는 [Google Cloud DNS](https://cloud.google.com/dns/)와 같은 서비스도 좋은 대안이 될 수 있습니다.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ovenmediaengine-enterprise.gitbook.io/guide/ko-kr/features/high-availability/clustering.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
