연습 - 모놀리식 내의 서비스를 마이크로 서비스로 리팩터링
이제 Fabrikam이 애플리케이션 분석을 완료했으므로 리팩터링 프로세스를 시작하여 모놀리식 아키텍처에서 마이크로 서비스로 서비스를 이동할 준비가 되었습니다. 패키지 처리 서비스를 마이크로 서비스로 이동하도록 애플리케이션을 수정해 보겠습니다.
애플리케이션 리팩터링
업데이트된 애플리케이션을 배포하기 전에 업데이트된 방식을 살펴보겠습니다. 모놀리식 앱에는 패키지를 처리하는 서비스인 PackageProcessor.cs가 있습니다. 애플리케이션의 성능을 분석한 후 이 서비스가 성능 병목으로 확인되었습니다. 고객의 드론 배달 수요가 증가함에 따라 이 서비스에서 드론 배달 일정과 물류를 처리하는 동안 과부하가 발생합니다. 전담 팀이 이 서비스를 완벽하게 관리하므로 마이크로 서비스로 이동하면 성능이 향상되고 개발 민첩성이 향상됩니다.
변경 내용에 대해 자세히 살펴보겠습니다.
드론 배달 이전
클래스는 PackageProcessor
PackageProcessor.cs 파일에서 패키지 처리의 핵심 기능을 처리합니다. 이 예에서는 리소스를 많이 사용하는 일부 작업을 수행합니다. 실제 시나리오에는 배달 시간 및 배달 경로 계산과 이 정보를 사용한 데이터 원본 업데이트가 포함될 수 있습니다.
public class PackageProcessor : IPackageProcessor
{
public Task<PackageGen> CreatePackageAsync(PackageInfo packageInfo)
{
//Uses common data store e.g. SQL Azure tables
Utility.DoWork(100);
return Task.FromResult(new PackageGen { Id = packageInfo.PackageId });
}
}
이 서비스에 대한 요청이 증가함에 따라 리소스 사용률이 증가하며 모놀리식 애플리케이션에 할당된 물리적 리소스로 제한됩니다. 이 서비스를 Azure App Service에 배포하면 수직 확장과 수평 확장이 가능합니다. 가장 많이 사용되는 이 리소스의 크기를 독립적으로 조정하여 성능과 비용을 최적화하는 것이 좋습니다. 이 시나리오에서는 Azure Functions를 사용하여 이 작업을 수행합니다.
드론 배달 이후
배포하기 전에 DroneDelivery 이후 애플리케이션 코드를 살펴보겠습니다. 클래스가 클래스로 PackageProcessor
변경 PackageServiceCaller
되었음을 확인할 수 있습니다. 여전히 IPackageProcessor 인터페이스를 구현하지만 그 대신 마이크로 서비스에 대한 HTTP 호출을 수행합니다.
public class PackageServiceCaller : IPackageProcessor
{
private readonly HttpClient httpClient;
public static string FunctionCode { get; set; }
public PackageServiceCaller(HttpClient httpClient)
{
this.httpClient = httpClient;
}
public async Task<PackageGen> CreatePackageAsync(PackageInfo packageInfo)
{
var result = await httpClient.PutAsJsonAsync($"{packageInfo.PackageId}?code={FunctionCode}", packageInfo);
result.EnsureSuccessStatusCode();
return new PackageGen { Id = packageInfo.PackageId };
}
}
마이크로 서비스는 Azure 함수에 배포됩니다. 해당 코드는 PackageServiceFunction.cs에서 확인할 수 있으며, 다음 코드를 포함합니다.
public static class PackageServiceFunction
{
[FunctionName("PackageServiceFunction")]
public static Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "put", Route = "packages/{id}")] HttpRequest req,
string id, ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
//Uses common data store e.g. SQL Azure tables
Utility.DoWork(100);
return Task.FromResult((IActionResult)new CreatedResult("http://example.com", null));
}
}
Azure Functions에 이 코드를 배치하면 사용자 부하가 증가함에 따라 이 서비스를 독립적으로 확장할 수 있습니다. 나머지 애플리케이션 코드의 서비스는 나머지 애플리케이션에 최적화된 상태로 유지할 수 있습니다. 시스템에 들어오는 드론 배달 요청이 늘어남에 따라 패키지 서비스가 수평 확장됩니다.
이제 애플리케이션을 다시 배포해 보겠습니다. 먼저 리팩터링된 서비스를 Azure Functions에 배포합니다. 그런 다음 App Service에 리팩터링된 애플리케이션을 배포하고 해당 함수를 가리킵니다.
함수 앱 배포
다음 명령을 실행하여 서비스를 가리키는 환경 변수를 설정합니다.
APPSERVICENAME="$(az webapp list \ --resource-group "<rgn>[sandbox resource group]</rgn>" \ --query '[].name' \ --output tsv)" FUNCTIONAPPNAME="$(az functionapp list \ --resource-group "<rgn>[sandbox resource group]</rgn>" \ --query '[].name' \ --output tsv)"
함수 앱을 위한 애플리케이션 코드를 빌드하고 압축해 보겠습니다.
cd ~/mslearn-microservices-architecture/src/after dotnet build ./PackageService/PackageService.csproj -c Release cd PackageService/bin/Release/netcoreapp2.2 zip -r PackageService.zip .
다음 명령을 실행하여 코드를 함수 앱으로 푸시합니다.
az functionapp deployment source config-zip \ --resource-group "<rgn>[sandbox resource group]</rgn>" \ --name $FUNCTIONAPPNAME \ --src PackageService.zip
업데이트된 드론 배달 애플리케이션 배포
이제 서비스가 Azure Functions에서 실행되고 있으므로 드론 애플리케이션이 해당 함수 앱을 가리켜야 합니다.
먼저 함수 앱에 대한 액세스 코드를 가져와야 애플리케이션에서 성공적으로 호출할 수 있습니다. 다음 명령을 실행하여 이 코드를 검색합니다. 다음 단계에서 사용하기 위해 함수 앱 이름과 코드를 표시합니다.
RESOURCEGROUPID=$(az group show \ --resource-group "<rgn>[sandbox resource group]</rgn>" \ --query id \ --output tsv) FUNCTIONCODE=$(az rest \ --method post \ --query default \ --output tsv \ --uri "https://management.azure.com$RESOURCEGROUPID/providers/Microsoft.Web/sites/$FUNCTIONAPPNAME/functions/PackageServiceFunction/listKeys?api-version=2018-02-01") echo "FunctionName - $FUNCTIONAPPNAME" echo "FunctionCode - $FUNCTIONCODE"
Azure Cloud Shell에서 다음 명령을 실행하여 코드 편집기에서 appsettings.json을 엽니다.
cd ~/mslearn-microservices-architecture/src/after code ./DroneDelivery-after/appsettings.json
코드 편집기에서
PackageServiceUri
및PackageServiceFunctionCode
값을 바꿉니다.PackageServiceUri
에서<FunctionName>
을 함수 앱 이름으로 바꿉니다.PackageServiceFunctionCode
에서<FunctionCode>
를 검색한 함수 코드로 바꿉니다. appsettings.json 파일은 다음 예제와 유사해야 합니다.{ "Logging": { "LogLevel": { "Default": "Warning" } }, "AllowedHosts": "*", "PackageServiceUri": "https://packageservicefunction-abc.azurewebsites.net/api/packages/", "PackageServiceFunctionCode": "SvrbiyhjXJUdTPXrkcUtY6bQaUf7OXQjWvnM0Gq63hFUhbH2vn6qYA==" }
Ctrl+S 키를 눌러서 파일을 저장하고 Ctrl+Q 키를 눌러서 코드 편집기를 종료합니다.
다음 명령을 실행하여 업데이트된 애플리케이션을 App Service에 배포합니다.
zip -r DroneDelivery-after.zip . -x \*/obj/\* \*/bin/\* az webapp deploy \ --resource-group "<rgn>[sandbox resource group]</rgn>" \ --name $APPSERVICENAME \ --src-path DroneDelivery-after.zip
사이트가 다시 배포되면 페이지를 새로 고칩니다. 이제 업데이트해야 합니다.
새 아키텍처의 성능 테스트
리소스 제한 서비스가 Azure Functions에서 실행되는 마이크로 서비스로 이동되었으므로 이 변경이 애플리케이션 성능에 미치는 영향을 살펴보겠습니다.
웹 사이트의 홈페이지에서 요청 보내기를 선택합니다. 이 작업은 모놀리식 앱의 요청을 Azure 함수에서 실행되는 마이크로 서비스에 제출합니다.
첫 번째 시도에서는 모놀리식 애플리케이션과 비슷한 결과가 나올 수도 있습니다. 페이지를 새로 고치고 메시지가 표시되면 요청을 다시 제출합니다. 이 단계를 여러 번 수행하면 1초에 100개 메시지가 전송되는 것을 확인할 수 있습니다.
함수 앱이 시작되는 동안은 초기 시도의 속도가 느렸습니다. 실행 후 이 코드가 모놀리식 아키텍처에서 실행 중일 때보다 응답 시간이 더 좋았습니다.
이제 동일한 성능을 제공하면서 아키텍처의 이 부분을 거의 무제한으로 수평 확장할 수 있습니다. 이 애플리케이션 코드를 마이크로 서비스로 이동하여 성능을 5~10배 향상시켰습니다. Fabrikam에는 이 서비스를 전담하는 개발 팀이 있으므로 이 마이크로 서비스를 반복하여 민첩성과 기능 릴리스 증가라는 혜택도 실현할 수 있습니다.