ÇSTech
Published in

ÇSTech

Çiçeksepeti’nin ASPNET Core ve Linux Geçişi

ÇSTech ❤️ .NET Core ❤️ Linux

Neden .NET Core?

  • Daha hızlı ve stabil çalışan bir sistem ile kullanıcı deneyimini iyileştirmek.
  • Cross-platform oluşu.
  • Server maliyetlerini azaltacak olması.
  • Yeni teknolojinin sunduklarından faydalanabilmek.
  • Geliştirme ekibinin son teknoloji ile çalışma motivasyonu.

ASPNET Core Geçişi ile Ne Değişti?

  • Yeni geliştirilen ve geliştirilecek olan kütüphane ve araçlara tam uyum sağlayabilir hale geldik.
  • .NET Core’un performans üstünlüğüne, kod içerisinde yapılan iyileştirmeler de eklenince sunucu sayısı azaldı.
  • Düşük makina sayılarında bile düşük cpu ve ram kullanımı ile daha stabil bir sistem elde edildi.
  • Windows makinadan linux makinalara geçildi.
  • Sunucu maliyetlerinde çok ciddi oranda azalma oldu.
  • Saniyelere ulaşabilen response time değerleri milisaniye seviyelerine düştü.
  • Yapılan iyileştirmelerle birlikte hata sayılarında azalma oldu.
  • Yeni build pipeline’ı ve .NET Core’un build performansı sayesinde build süreleri azaldı.
  • Geliştirme ekibi artık platform bağımsız şekilde kod yazabilir hale geldi.

Neden Linux Makina Üzerinde Host Ettik?

  • Her ne kadar içerisindeki birçok yapı mikroservislere bölünmüş ve yükü hafifletilmiş de olsa halen monolith ve büyük çaplı bir uygulamaya sahiptik.
  • Kaynak tüketiminin bir container için fazla olduğunu düşündük.
  • EC2/Compute Engine yönetimi konusunda infrastructure ekibinin deneyimi yüksekti.

Nasıl Bir Yol İzledik?

  • Uygulamanın genel değerlendirmesi.
  • Core’da karşılığı olmayan bağımlılıkların çözülmesi.
  • Temel kütüphanelerin soyutlanması.
  • Uygulanan VCS(git) branch modeli.
  • Kod içerisindeki dönüşümün gerçekleştirilmesi.
  • CI Pipeline.
  • Linux makina üzerinde çalıştırılması.
  • İsteklerin ASPNET Core uygulamasına yönlendirilmesi.

Uygulamanın Genel Değerlendirmesi

.NET Core’da Karşılığı Olmayan Bağımlılıkların Çözülmesi

Temel Kütüphanelerin Soyutlanması

Geliştirme ortamında, editör olarak Rider, işletim sistemi olarak macOS üzerinde çalıştık. iterm2, zsh ve VS Code diğer önemli araçlardı.

Uygulanan VCS(git) Branch Modeli

  • .csproj’lar kökten değişiyor. Her zaman conflict çıkarırlar(değişiklik varsa). Use local deyin ve geçin. Sadece yeni paket eklenmişse sorun yaşarsınız. O da zaten build alınca görülüp düzeltilir.
  • global.asax, web.config artık yok. Her zaman conflict çıkarır(değişiklik varsa). Değişikliğin ne olduğunu inceleyip use local deyin. Sonra değişikliği core tarafında uygulayın.
  • package.json’lar her zaman conflict çıkarır(değişiklik varsa). Onların hepsini sildik. Use local deyin ve geçin.
  • ChildAction’ların hepsi ViewComponent oldu yani dosyaların yeri bile değişti. Her zaman conflict çıkarır(değişiklik varsa). Burada dikkat. Yapılan değişikliği bulup ViewComponent içerisinde aynısını yapmanız gerekir.
  • Proje içerisinden ayırıp kütüphanelere taşıdığınız kodlar conflict çıkarırlar(değişiklik varsa). Gerekli değişiklikler testpit edilip kütüphane üzerinde uygulanmalı.
  • Yukarıdaki maddeler hariç diğer her türlü değişiklik çoğunlukla hiç conflict çıkarmaz ya da normalde yaşadığımız conflict çözme sürecinden daha zor olmazlar.

Kod İçerisindeki Dönüşümün Gerçekleştirilmesi

  • Sadece application(Web, API, Test) projelerinin TargetFramework’ü netcoreapp olması yeterli. Solution içerisindeki diğer tüm projeler netstandard olarak kalmalı.
  • Örneğin; Project.Service diye bir projeniz var ve içerisinde Project.Core referans verilmiş durumda. Project.Web’e Project.Service’i referans verdiğinizde Project.Web içerisinde tüm Project.Core referansları kullanılabilir haldedir. Bunu bilerek, proje referanslarını olabilecek en sade halde tutun.
  • netcoreapp2.1 ve üstü için bir Web ya da API projesinde gerekli birçok bağımlılığı içeren Microsoft.AspNetCore.App paketini kullanın.
  • Build edilebilir parçalar halinde ilerlemek için en temel kütüphanenizden değişiklik yapmaya başlayın. Örneğin: Project.Core. Ardından Project.Data ve en son Project.Web gibi.
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework
<PreserveCompilationContext>true</PreserveCompilationContext>
<MvcRazorCompileOnPublish>false</MvcRazorCompileOnPublish>
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Project.Manager\Project.Manager.csproj" />
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\Project.Services.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="2.1.1" />
</ItemGroup>
</Project>
  • Tüm bağımlılık registration işlemlerini tek satır halinde tutup, kompleks olanları da ServiceCollectionExtension ve ApplicationBuilderExtensions altına konumlandırdık.
  • Her projenin kendi bağımlılıklarını kendisinin register etmesini sağladık. Ana startup dosyası Web/API projesi altında metodları içerisinde tek satır kod olacak şekilde konumlandırıldı.
Project.Data
|_ InfraStructure
|_ Startup.cs
Project.Service
|_ InfraStructure
|_ Extensions
|_ ApplicationBuilderExtensions
|_ ServiceCollectionExtensions
|_ Startup.cs
Project.Web
|_ InfraStructure
|_ Extensions
|_ ServiceCollectionExtensions
|_ WebStartup.cs
|_ Startup.cs
|_ Program.cs

CI Pipeline

  • Uygulamadaki third party referanslarda bir değişiklik olmadığı sürece dotnet restore yapılmamalı. Önceden restore edilmiş paketler kullanılmalı.
  • dotnet restore komutu sadece bir defa çalıştırılmalı. dotnet build , dotnet test ve dotnet publish gibi komutların da build ve restore komutlarını tekrar çalıştırdığı unutulmamalı. bu komutlara yerine göre — no-restore — no-build argümanları verilmeli.
  • dotnet restore veya npm install gibi komutlar ile gelen paket dosyaları nihai pakete dahil edilmemeli.
  • .pdb dosyaları da pakette olacak fakat isterseniz silebilirsiniz. Yine de bazen profile etmek istediğinizde olmaları faydalı.
var
|_ aspnetcore
|_ Example.Application.Name
|_ 1001
|_ 1005
|_ 1005-01
etc
|_ systemd
|_ system
|_ Example.Application.Name-1005-01.service
|_ nginx
|_ sites-available
|_ Example.Application.Name

Karşılaşılan Diğer Sorunlar ve Çözümleri

# increase the max open file limit for the system
echo "fs.file-max = 640000" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
[Unit]
Description=bla bla bla
[Service]
WorkingDirectory=/any/path/here
...
LimitNOFILE=640000
...
proxy_buffering off;
proxy_read_timeout 7200;
export COMPlus_EnableEventPipe=1
export COMPlus_EventPipeConfig=Microsoft-DotNETCore-SampleProfiler:1:5
dotnet run

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store