ServiceContext와 Lifecycle
최종 업데이트ServiceContext
Unary 서비스와 StreamingHub 메서드, 그리고 필터 내부에서 this.Context를 통해 ServiceContext에 접근할 수 있습니다.
| 속성 | 타입 | 설명 |
|---|---|---|
| Items | ConcurrentDictionary<string, object> | 요청(request)/연결(connection)당 객체 저장소입니다. |
| ContextId | Guid | 요청(서비스)/연결(StreamingHub)당 고유 ID입니다. |
| Timestamp | DateTime | 요청/연결이 시작된 시간의 타임스탬프입니다. |
| ServiceType | Type | 호출된 클래스입니다. |
| MethodInfo | MethodInfo | 호출된 메서드입니다. |
| AttributeLookup | ILookup<Type, Attribute> | 서비스와 메서드 모두에서 병합된 캐시된 속성들입니다. |
| CallContext | ServerCallContext | Raw gRPC 컨텍스트입니다. |
| MessageSerializer | IMagicOnionSerializer | 사용 중인 시리얼라이저입니다. |
| ServiceProvider | IServiceProvider | 서비스 제공자를 가져옵니다. |
Items는 인증 필터와 같은 곳에서 값을 설정하고, 서비스 메서드에서 가져오기 위해 사용할 수 있습니다.
ServiceContext를 캐시하지 마십시오. ServiceContext는 요청 중에만 유효하며 MagicOnion은 인스턴스를 재사용할 수 있습니다. 요청 후 컨텍스트에서 참조된 객체들의 상태도 정의되지 않습니다.
ServiceContext는 "연결당" 컨텍스트입니다. StreamingHub 내부에서 ServiceContext에 접근할 수 있지만, 동일한 컨텍스트가 연결 전체에서 공유된다는 점을 주의하세요. 예를 들어, Timestamp는 연결이 설정된 시간이며, 메서드와 관련된 속성들은 항상 Connect와 같은 특별한 메서드에 의해 설정됩니다. Items 속성은 Hub 메서드 호출마다 초기화되지 않습니다.
StreamingHubFilter 내부에서는 StreamingHubContext를 사용하세요. StreamingHubContext는 각 StreamingHub 메서드 호출에 대한 컨텍스트입니다.
전역(global) ServiceContext
MagicOnion은 HttpContext.Current처럼 전역으로 현재의 컨텍스트를 가져올 수 있습니다. ServiceContext.Current로 가져올 수 있지만, MagicOnionOptions.EnableCurrentContext = true가 필요합니다. 기본값은 false입니다.
성능과 코드의 복잡성 관점에서 ServiceContext.Current의 사용은 피하는 것을 권장합니다.
Lifecycle
Unary 서비스의 Lifecycle은 의사 코드로 다음과 같습니다. 요청이 수신되고 처리될 때마다 새로운 서비스 인스턴스가 생성됩니다.
async Task<Response> UnaryMethod(Request request)
{
var service = new ServiceImpl();
var context = new ServiceContext();
context.Request = request;
var response = await Filters.Invoke(context, (args) =>
{
service.ServiceContext = context;
return await service.MethodInvoke(args);
});
return response;
}
StreamingHub 서비스의 Lifecycle은 의사 코드로 다음과 같습니다. 연결되어 있는 동안 StreamingHub 인스턴스가 유지되므로 상태를 유지할 수 있습니다.
async Task StreamingHubMethod()
{
var context = new ServiceContext();
var hub = new StreamingHubImpl();
hub.ServiceContext = context;
await Filters.Invoke(context, () =>
{
var streamingHubContext = new StreamingHubContext(context);
while (connecting)
{
var message = await ReadHubInvokeMessageFromStream();
streamingHubContext.Intialize(context);
await StreamingHubFilters.Invoke(streamingHubContext, () =>
{
return await hub.MethodInvoke();
});
}
});
}