업계

기술

조직 규모

대규모(직원 1,000-9,999명)

국가/지역

미국

기술

ASP.NET Core Modernization

회사

Microsoft Teams (Microsoft)

Microsoft Teams "MiddleTier"는 Microsoft Teams의 다양한 시나리오를 지원하는 내부 서비스입니다. Microsoft의 10개 이상의 팀에서 유지 관리하는 700개 이상의 API로 구성된 가장 큰 서비스 중 하나입니다. 지난 2년 동안 이 서비스에 속한 50개 이상의 프로젝트(라이브러리, 테스트, 애플리케이션)가 .NET 표준 2.0 및 .NET Core 3.1로 변환되었으며 기능 및 성능이 동일하거나 그 이상이며 이제 거의 완전히 실행되고 있습니다. 프로덕션에서 .NET Core 3.1을 사용하고 다음에는 .NET 6으로 이동하려고 합니다. 이 마이그레이션 전에 서비스는 ASP.NET Core 2.2 MVC 파이프라인을 사용하여 .NET Framework 4.6.2에서 실행되었습니다. 35개의 Azure 데이터 센터에 배포된 Azure Service Fabric에서 실행됩니다.

MiddleTier는 매일 작업하는 수백 명의 개발자에게 제공하는 기능 면에서 초대형 서비스이기 때문에 이 마이그레이션의 범위가 컸습니다.

마이그레이션 동기 부여

팀은 다음과 같은 이유로 .NET Core 3.1로 전환하게 되었습니다.

  • 성능 및 비용 효율성 향상
  • .NET Framework 4.6.2의 수명이 곧 종료될 것 같습니다.
  • 플랫폼 간 지원
  • 더 나은 개발자 환경을 위한 최신 프레임워크로 이동

.NET Core 3.1로 마이그레이션한 후의 이점

.NET Core 3.1로 마이그레이션한 후 팀은 다음과 같은 향상된 기능을 발견했습니다.

  • 25% CPU 개선
  • 인프라 비용 약 25% 절감
  • 향상된 스레드 풀 사용
  • 연간 .NET 릴리스로 전환하기 위한 기술적 부채 및 노력 감소

다음 차트는 .NET Framework와 .NET Core 간의 비교를 보여줍니다. 앞으로 .NET 6에서는 더 많은 개선 사항을 볼 수 있을 것입니다.

.NET Framework의 57% 피크 CPU 및 .NET Core의 42% 피크 CPU를 보여주는 차트
CPU 비교
.NET Core로 마이그레이션한 후 사용량이 많은 작업자 스레드의 감소를 보여주는 차트
바쁜 작업자 스레드 비교
.NET Core로 마이그레이션한 후 사용량이 많은 IO 스레드의 감소를 보여주는 차트
사용 중인 IO 스레드 비교

접근

전체 마이그레이션은 세 단계로 나뉩니다.

3가지 마이그레이션 단계(준비, 실행, 검증 및 롤아웃)에 대한 활동을 보여주는 그래픽

또한 두 이진 파일을 모두 사용할 수 있도록 하고 .NET Core를 천천히 롤아웃할 수 있도록 애플리케이션을 .NET Framework 및 .NET Core에 다중 대상으로 지정하기로 했습니다.

학습

OData 및 기타 REST API는 경로 접두사를 공유할 수 없습니다.

해당 서비스에는 많은 REST 엔드포인트와 함께 OData 엔드포인트가 거의 없습니다. 이 두 가지는 끝점에 대해 동일한 라우팅 접두사를 공유했습니다. 이것은 .NET Framework에서 제대로 작동했지만 라우팅 변경으로 인해 .NET Core에서 작동이 중지되었습니다. 이 문제를 해결하기 위해 OData API를 다른 경로 접두사로 옮겨야 했습니다.

OData 클라이언트 라이브러리의 성능 문제

The HttpWebRequest pattern with OData clients to make calls to downstream OData APIs results in higher latency compared to .NET Framework. This was due to a regression in .NET Core in which the framework doesn't cache connections. This is already resolved in newer versions of .NET.

Azure Service Bus SDK 문제

The Azure Service Bus SDK had to be upgraded as part of this migration since the old version isn't .NET Standard compatible. The latest version of the Azure Service Bus SDK sends the request payload in JSON format whereas the older SDK sends the payload in XML format. To continue using XML payload, they had to use the DataContractSerializer.

다중 대상 지정을 위한 Service Fabric 프로젝트의 문제

Service Fabric 프로젝트(sfproj)는 기본적으로 다중 대상 지정을 지원하지 않습니다. 두 대상 프레임워크에 대한 Service Fabric 패키지를 생성하기 위해 빌드 파이프라인에서 해결 방법을 수행해야 했습니다.

이전 버전의 MimeKit NuGet 관련 문제

The older version of MimeKit can have issues with double byte characters, thus language specific validation is advised in this scenario. They uncovered similar issues when they rolled out to deployments located in Asian geography.

고전적인 ASP.NET의 단점

  • .NET Core에서 내부로 표시된 일부 .NET Framework 클래스의 사용을 제거해야 했습니다.
  • MVC async suffix dropped from action names as mentioned in the ASP.NET Core breaking changes for versions 3.0 and 3.1 article. If any of the code paths are dependent on the action name, it can cause a change in behavior.
  • Synchronous IO operations are by default turned off on all servers starting in .NET Core 3.0 as mentioned in the dotnet/aspnetcore#7644 GitHub issue.
  • StreamContent를 HTTP 요청 콘텐츠로 보낼 때 Content-Length 헤더가 Content.Headers에 설정되지 않았습니다. 다운스트림 호출에서 오류가 발생할 수 있습니다.
  • .NET 프레임워크는 문자열에 대한 안정적인 해시 코드를 생성하지만 .NET Core는 생성하지 않습니다.
  • The Required attribute from the System.ComponentModel.DataAnnotations namespace behaves differently in .NET Core. On .NET Framework, this attribute doesn't do any model validation for non-null fields but on .NET Core it does.

미래

.NET의 모든 새 릴리스에는 복원력, 확장 가능, 성능 및 보안 서비스를 구축하려는 우리의 목표를 달성하는 데 계속 도움이 되는 엄청난 생산성 및 성능 개선 사항이 제공됩니다. 팀은 다음에 .NET 6으로 업그레이드하여 .NET의 개선 사항을 계속 활용할 것입니다.