This document is about: SERVER 5
SWITCH TO

새로운 사항

Plugins API 버전 업그레이드

Plugins API 어셈블리 (PhotonHivePlugin.dll) 버전은1.0.x에서 1.1.0로 업데이트되었습니다.

즉, PhotonHivePlugin.dll 1.1.x가 포함된 Photon Server 플러그인 SDK(v5 RC1 또는 그 이상)를 사용하여 사용자 지정 플러그인을 구축하고 이를 서버에서 배포하고 실행하려면 서버 바이너리 파일이 해당 플러그인 API 버전과 일치해야 합니다.

이는 기업 고객의 경우 프라이빗 클라우드를 최소한 Photon Server v5 RC1로 업데이트해야 한다는 것입니다.
이전의 사설 클라우드에 플러그인을 업로드하려고 하면 새 룸을 생성 시 플러그인을 로드하려고 할 때 오류가 발생합니다.

새로운 분리된 환경 구성 파일

이제 플러그인이 자체 파일에서 별도로 구성됩니다.
파일은 이전에 사용한 환경 구성 파일인 "plugin.config" 파일과 동일한 폴더입니다.
환경 구성 구문은 여전히 동일합니다.

새로운 로깅 인터페이스

플러그인으로부터 접근 가능한 새롭게 개선된 로깅 인터페이스를 추가했습니다.

이전 사용되지 않는 방식

v4에서는 IPluginHost 로깅 메소드를 직접 호출하여 사용했습니다.

C#

private IPluginHost pluginHost;

public bool SetupInstance(IPluginHost host, Dictionary<string, string> config, out string errorMsg)
{
    pluginHost = host;
}

///...

this.pluginHost.LogDebug("debug");
this.pluginHost.LogWarning("warning");
this.pluginHost.LogError("error");
this.pluginHost.LogFatal("fatal");

새로운 방식

IPluginHost 로깅 메소드를 호출하는 대신에, 플러그인 인스턴스당 새로운 IPluginLogger 객체를 생성해야 하고 이것을 사용하여 플러그인에서 발생한 모든 것을 기록하는 데 사용합니다:

C#

public const string PluginName = "MyPlugin";

private IPluginLogger pluginLogger;

public override bool SetupInstance(IPluginHost host, Dictionary<string, string> config, out string errorMsg)
{
    pluginLogger = host.CreateLogger(PluginName);
    // ...
}

// ...

this.pluginLogger.LogDebug("debug");
this.pluginLogger.LogWarning("warning");
this.pluginLogger.LogError("error");
this.pluginLogger.LogFatal("fatal");

로거의 이름을 설정할 때(IPluginHost.CreateLogger(loggerName)로 전달), 로거 이름 앞에 Plugin.을 붙입니다.
예를 들어, MyPlugin.MyClass로 설정한 경우, Plugin.MyPlugin.MyClass에 기록됩니다.
로그 수준이 최대 수준으로 설정된 경우 위의 코드에서 이러한 로그 항목을 생성합니다:

2020-01-31 17:10:07,394 [1] DEBUG  Plugin.MyPLugin - debug
2020-01-31 17:10:07,901 [1] WARN  Plugin.MyPLugin - warning
2020-01-31 17:10:08,152 [1] ERROR  Plugin.MyPLugin - error
2020-01-31 17:10:08,724 [1] FATAL  Plugin.MyPLugin - fatal

개선된 플러그인 호크 프로세싱

ICallInfo는 메소드 호출의 컨텍스트를 나타내는 플러그인 후크 메소드 내부에서 발생하는 아규먼트입니다.
이 컨텍스트 객체는 룸 내부의 정상적인 워크플로우를 보장하기 위해 후크 호출 후 제한된 시간 내에 처리해야 합니다.

익명 함수

HTTP 요청에 대한 콜백으로 익명 함수(lambda 표현식 또는 익명 메소드)를 사용하였다면(아래 예제 참고) 계속 그렇게 사용할 수 있습니다.

익명 메소드로서 HTTP 콜백 예제:

C#

private void SendRequest(ICallInfo callInfo)
{
    HttpRequest request = new HttpRequest
    {
        Callback = delegate
                   {
                       ProcessCallIfNeeded(callInfo);
                   },

lambda 표현식으로서 HTTP 콜백 예제:

C#

private void SendRequest(ICallInfo callInfo)
{
    HttpRequest request = new HttpRequest()
    {
        Callback = (response, userObject) => ProcessCallIfNeeded(callInfo),

그러나 더 이상 사용되지 않는 HTTP 메소드 호출을 교체하는 것이 좋습니다.

C#

PluginHost.HttpRequest(request);

2개의 아규먼트를 받는 새로운 오버로드 메소드로:

C#

PluginHost.HttpRequest(request, callInfo);

이전 방식

이전에는 HTTP 응답 콜백 내부의 ICallInfo 객체를 가져오기 위해 해결 방법을 사용해야 했습니다.
ICallInfo 객체를 저장하기 위해 사용자 지정 옵션인 HttpRequest.UserState를 사용했습니다.

예제:

C#

private void CallbackOldLogic(IHttpResponse response, object userObject)
{
    ICallInfo callInfo = userObject as ICallInfo;
    ProcessCallIfNeeded(callInfo);
}

private void SendRequest(string url, ICallInfo callInfo)
{
    HttpRequest request = new HttpRequest
    {
        Url       = url,
        Callback  = CallbackOldLogic,
        UserState = callInfo
    }
    this.PluginHost.HttpRequest(request);

새로운 방식

이제 새로운 PluginHost.HttpRequest 오버로드 메소드 내부에서 플러그인 후크 컨텍스트 (ICallInfo)를 전달합니다.
그러고 나서 IHttpResponse에서 컨텍스트를 가져올 수 있습니다.

예제:

C#

private void CallbackNewLogic(IHttpResponse response, object userObject)
{
    ICallInfo callInfo = response.CallInfo;
    ProcessCall(callInfo);
}

private void SendRequest(string url, ICallInfo callInfo, object userObject = null)
{
    HttpRequest request = new HttpRequest
    {
        Url       = url,
        Callback  = CallbackNewLogic,
        UserState = userObject,
        CallInfo  = callInfo
    };
    this.PluginHost.HttpRequest(request, callInfo);

새로운 동기 방식

이전의 사용하지 않는 방식

v4에서 우리는 플러그인 후크에 대한 지연 처리를 원하는 경우 비동기 HTTP 요청 또는 타이머에 대해 ICallInfo.Defer를 호출했어야 했습니다.

HTTP 요청 예제:

C#

private void SendRequest(string url, ICallInfo callInfo)
{
    HttpRequest request = new HttpRequest
    {
        Url       = url,
        Async     = true,
        Callback  = delegate { ProcessCallIfNeeded(callInfo); },
    };
    this.PluginHost.HttpRequest(request);
    callInfo.Defer();
}

타이머에 대한 예제:

C#

private void DelayLogic(ICallInfo callInfo, Action logic, int delayMs)
{
    PluginHost.CreateOneTimeTimer(
                () =>
                {
                    logic();
                    ProcessCallIfNeeded(callInfo);
                },
                delayMs);
    callInfo.Defer();
}

새로운 방식

이제 ICallInfo.Defer는 없어졌으며 대신 다음의 경우 우리는 내부적으로 자동으로 후크 컨텍스트 호출을 연기합니다.

  • httpRequest.Async = trueHttpRequest을 전송
  • 타이머 생성

HTTP 요청 예제:

C#

private void SendRequest(string url, ICallInfo callInfo)
{
    HttpRequest request = new HttpRequest
    {
        Url       = url,
        Async     = true,
        Callback  = delegate { ProcessCallIfNeeded(callInfo); },
        CallInfo  = callInfo
    };
    this.PluginHost.HttpRequest(callInfo, request);
}

타이머 예제:

C#

private void DelayLogic(ICallInfo callInfo, Action logic, int delayMs)
{
    PluginHost.CreateOneTimeTimer(
                callInfo,
                () =>
                {
                    logic();
                    ProcessCallIfNeeded(callInfo);
                },
                delayMs);
}

파이버 접근

파이버는 FIFO 방식으로 순차적으로 실행되는 작업 목록입니다.
그렇다고 해서 한 스레드에서 실행되는 것은 아닙니다.
사실 여러 개의 스레드에서 실행되지만 하나씩 실행됩니다.
따라서 첫 번째 작업은 스레드 A에서 실행될 수 있으며, 작업이 완료되면 두 번째 작업은 스레드 B 등에서 실행될 수 있습니다.
그러나 매 순간 단 하나의 스레드만 룸 데이터에 접근합니다.
많은 파이버가 동일한 데이터에 접근하려고 하면 락 메커니즘을 사용합니다.
플러그인에서 룸 파이버를 가져오는 것은 다음과 같습니다.

C#

IPluginFiber fiber = this.PluginHost.GetRoomFiber();

Enqueue

다음을 사용하여 룸의 파이버로 액션을 큐에 넣을 수 있습니다:

C#

PluginHost.Enqueue(someAction);

또는 위에서 얻은 파이버를 사용할수도 있습니다:

C#

int r = fiber.Enqueue(someAction);
if (r == 0)
{
   // success
}
else
{
   // error
}

타이머

IPluginFiberICallInfo가 필요하지 않으며 후크 컨텍스트 외부에서 스레드를 안전하게 실행할 수 있다는 점을 제외하고는 IPluginHost와 동일한 메소드를 공유합니다.

C#

object timer = fiber.CreateOneTimeTimer(someAction, executeAfterMs);
\\ ...
fiber.StopTimer(timer); // in case you want to abort before delay is expired and someAction is executed

C#

object timer = fiber.CreateTimer(someAction, firstExecutionAfterMs, repeatEachMs);
fiber.StopTimer(timer);

IFactoryHost

또한 애플리케이션 전반 서비스(즉, 안티치트 서비스, 브로드캐스팅 등)에 사용할 수 있는 외부 잠금 없는 처리에 대한 새로운 지원도 있습니다.
이 처리는 IPluginFiber 메커니즘을 사용하여 완전히 구축됩니다.
플러그인 파이버는 룸 파이버와 유사하지만 룸 밖에서 작동하는 파이버입니다.
어디에서든지 파이버를 Enqueue를 할 수 있으며 서버 시간을 기준으로 작업이 실행됩니다.
IPluginFiber를 가져오려면 IFactoryPlugin2에서 제공하는 IFactoryHost의 인스턴스가 필요합니다.
IFactoryPlugin2는 표준 IPluginFactory를 확장한 인터페이스입니다.

C#

void SetFactoryHost(IFactoryHost factoryHost, FactoryParams factoryParams);

이 메소드는 플러그인 팩토리가 인스턴스화된 직후 플러그인이 살아있는 동안 한 번 호출되며 플러그인 섬유 및 플러그인 로거를 제공하는 IFactoryHost 인스턴스를 제공합니다:

C#

IPluginFiber CreateFiber();

IPluginLogger CreateLogger(string loggerName);

FactoryHost로 생성된 파이버는 룸 외부(즉, 새 룸을 작성할 때)와 룸 내부 둘 다 사용하여 룸 컨텍스트 외부에서 큐잉 또는 타이머 작업을 수행할 수 있습니다.
마찬가지로, FactoryHost에 의해 만들어진 로거는 이러한 작업 내에서 사용됩니다.

새로운 동기 방식

"동기식 HTTP 요청"(httpRequest.Async = false로 전송된 HttpRequest)의 경우 이제 응답 또는 시간 초과가 발생할 때까지 룸 파이버를 일시 중지합니다(즉, 룸 메시지가 처리되지 않습니다).

이전 IPluginHost.HttpRequest 메소드는 블로킹입니다. HTTP 응답이 수신되거나 제한 시간이 초과될 때까지 리턴하지 않습니다.
이 접근 방식의 주요 문제는 스레드가 차단되고 콜백 실행이 이 스레드의 대기열에 푸시 될 수 있다는 것입니다.
스레드가 차단되었기 때문에 이 콜백을 실행할 수 없습니다.
그 결과 타임 아웃이 발생합니다.
새로운 접근법과의 주요 차이점은 새로운 IPluginHost.HttpRequest 메소드의 비차단성입니다.
절대 블록 되지 않습니다.
즉, 호출이 수행되는 플러그인 후크와 사용된 HTTP 요청 콜백을 모두 업데이트해야 하는 사용자 코드를 다시 작성해야 합니다.
플러그인 후크는 HTTP 큐에 요청을 푸시 한 후 바로 새로운 IPluginHost.HttpRequest 호출이 리턴된다는 것을 알고 있어야 합니다.
완료되지 않은 경우 콜백 내에서 ICallInfo 객체는 처리되어야 합니다(계속 또는 오퍼레이션 중단을 위해 callInfo.Continue 또는 Fail 또는 Cancel 호출)
이제 쓰레드를 블로킹하는 대신에 우리는 룸 파이버를 블록 합니다.
따라서, 요청에 대한 응답이나 타임아웃이 발생할 때까지 새로운 작업은 처리되지 않을 것입니다.

글로벌 밴

RemoveActorReason.GlobalBanned (2)을 전달할 때 마스터 서버는 UserId를 기간 인증 토큰 만료의 최대 2배(기본값은 2 * 1시간) 동안 메모리에 보관하므로 전체적으로 밴된 사용자는 해당 기간 동안 새 룸에 가입할 수 없습니다.
이후 사용자 지정 인증에서 사용자를 거부할 수 있습니다.
또한 이는 현재 룸에 RemoveActorReason.Banned와 동일한 영향을 미칩니다. UserId가 룸 상태의 ExcludedUsers에 추가되고 사용자는 룸에 다시 참여할 수 없습니다.

AuthCookie 업데이트

이제 다음 방법을 사용하여 액터별 보안 인증 쿠키를 업데이트할 수 있습니다:

void IActor.UpdateSecure(string key, object value)

모든 캐시 오퍼레이션 지원

이제 모든 캐시 작업을 실행할 수 있습니다.
클라이언트로 이벤트 전송을 포함하지 않는 모든 캐시 작업의 경우 새 메소드를 사용합니다:

bool IPluginHost.ExecuteCacheOperation(CacheOp operation, out string errorMsg)

더 유연하고 강력한 HTTP 요청 API

  • PUT 메소드용 추가된 지원.
    다른 HTTP 동사도 지원되어야 합니다.
  • HttpRequest 속성(Accept, ContentType)을 사용하여 일부 제한된 HTTP 요청 헤더를 설정할 수 있습니다.
  • IHttpResponse.Headers를 사용하여 HTTP 응답 헤더를 얻을 수 있습니다.
Back to top