Azure SQL Veritabanı Bakım Süreçlerini İyileştirmek

Bu yazıyı uzun zamandır üzerine düşündüğümüz ve bulduğumuz bir çözüm üzerine ele alıyorum. Bu yazımızın temel amacı PEAKUP Azure Services paketini neden geliştirdiğimizle doğrudan alakalıdır. Ek olarak doğru kullanım noktasında, ölçeklendirme ile ilgili problemlerin Azure üzerinde aslında çok az maliyetler ile nasıl çözülebildiğini göstermektir. Bu yazının kapsamı ve faydası, birden fazla veritabanı yönetimi, Azure SQL Sunucu üzerinde veritabanlarının bakımını ve performansını arttırmak üzeredir.
Yazının girişinde bahsettiğimiz paketi geliştirirken Azure üzerinde deneyimlediğimiz bir ilginç şeyse, REST üzerinden iletilen tüm Scale Up/Down taleplerinin portal.azure.com üzerinden yapılan taleplerden belkide iki katı kadar kısa bir sürede gerçekleşmesiydi!

Vaka

PEAKUP’ın Velocity ürünü içerisinde yer alan bazı müşterilerimizin kayıtları yüz binleri bazıları da milyonları bulabiliyor. İlerleyen zamanlarda yüz milyonlara hatta milyarlara kadar ulaşacağından eminim. Bu nedenle gerekli bakım stratejilerini daha baştan, en doğru ve pratik şekilde kurgulamak son derece değerli! Ürün içerisinde tek bir veritabanı içerisinde Multi Tenant bir yapı uygularken aynı zamanda KVKK gereği bulut kaynakları kullanmayan müşterilerimiz için yerel sunucu desteği sunuyoruz ya da müşterilerimizin kendilerine ait Azure kaynakları içerisinde tuttukları veritabanlarını da kullanabiliyoruz. Yani bir veritabanı üzerinde birden fazla Multi Tenant yapının yanında birden fazla veritabanı üzerinde de yine birden fazla Multi Tenant bir mimariden bahsediyoruz.

Velocity platformunun her zaman erişime açık olması, her zaman yüksek ve ayrıca aynı performansta olması ürün için ortaya koyduğumuz en önemli prensiplerden yalnızca bir kaçı arasında yer alıyor. Genel olarak kullanım, iş dünyasına hitap ettiği içini iş günleri ve çalışma saatleri içerisinde çok yüksek olsa da mavi yakanın ağırlıklı olduğu ve 24 saat operasyonun devam ettiği müşterilerimizde gece kullanımı da oldukça yüksek oluyor. Bu nedenle bakım süreçlerinin kullanımın görece daha az az saatlerde olduğu zamanlarda olsa da kesinlikle platformu durdurmaması ya da herhangi bir yavaşlığa, kesintiye sebep olmaması gerekiyor. Söz konusu yedi gün yirmi dört saat devam eden bir operasyon olduğunda sürekli erişebilirlik taviz verilebilecek bir konu opsiyonundan çıkıyor.

Sürekli büyüyen veritabanlarında, veritabanının sürekli, doğru ve düzgün bir şekilde yedeklenmesi, verilerin sürekli olarak sıralı bir şekilde depolandığını kontrol etmek veritabanı ölçeklendirme konusundaki en kritik operasyonlardan birisidir. Yedekleme safhası Azure tarafından otomatik olarak yönetildiği için bu yük üzerinizden kalksa da Index’lerin bakımları, Partition’ların gerekli zamanlarda tekrar yapılandırılmaları gibi konular veritabanı üzerinde ciddi anlamda yük yaratan operasyonların başında gelir. Azure SQL içerisinde sorguların performanslarını takip etmek, yavaş sorguları tespit edip bunlar için aksiyon almak “Database recommendations” bölümündeki tavsiyeler eşliğinde kolayca yapılsa da, bakım süreçlerinde bu aksiyonları almaya başladığınızda veritabanı performansıyla ilgili ciddi sorunlar sizleri bekliyor. Üstelik bu problem, On Premise olarak çalışan SQL sunucuları için oldukça güç! İşte bunun için doğru zamanda, doğru miktarda kaynak kullanımı son derece kritik rol oynuyor.

Veritabanın sahip olduğu sunucu tipi(enterprise, developer, express vb.) bir çok geliştirici tarafından çok önem arz etmese de söz konusu bakım olduğunda böylesi kriterlerin değeri ortaya çıkıyor. Zira SQL Server Enterprise içerisinde Index bakımları Online olarak yapılabilirken, system içerisinde herhangi bir duraksama söz konusu olmaktan çıkıyor. Ancak veritabanının kullandığı kaynaklar ve bakımların süresiyle ilgili problemler, problem olmaya devam ediyor. Şu da unutulmamalıdır ki veritabanı üzerinde yapılan her Index, her Partition operasyonu performasın artacağı garantisini vermez… Zira diskin büyümesine haliyle SQL Server tarafından belleğe alınan verinin daha da büyük hale gelmesiyle kaynak kullanımı bir yerden sonra yetersiz oluyor. Özellikle söz gelimi olarak 1, 2, 4 ve 14 hafta olacak şekilde bir Retention Policy, veritabanı üzerinde her zaman yükün artacağını bunun yanı sıra bakım konularının kritik seviyesini en üst seviyeye çekiyor.

Bakım süreçlerinin en hızlı şekilde yapılması hem kullanıcı memnuniyeti, hem ölçeğin sürekli olarak arttırılabilir noktada olması hem de itibar açısından son derece önemli bir hale geliyor. İşte bu nedenle Azure üzerinde kaynakları ihtiyacınız olduğu anda dilediğiniz kadar arttırabilmek ya da azaltabilmek (Scale Up/Scale Down) son derece kilit bir rol oynuyor. Üstelik sadece süreç olarak değil maliyet olarak da!

İhtiyacımız olan senaryo, bakım süresi öncesinde kullandığımız veritabanı planını bir ya da iki üst seviyedeki kaynak oranında arttırmak ve bakım sonrasında eski kaynaklara geri dönebilmek… Böylece arttırılan kaynakların bir kısımı bakım kalan kısmı da platformun düzenli bir şekilde devam etmesi için hazır olarak bekliyor!

Üstelik bu operasyon sırasında, hiçbir bakım işleminin zaman aşımına uğramaması ve bakım sürecini en baştan tekrar başlatmamak ya da veritabanının kilitlenmesi gibi çok büyük riskleri ortadan kaldırmak… Böylece veritabanı üzerindeki maliyete sadece saatlik fiyatlar ile katlanırken, belkide 3-4 saat kadar sürecek bir operasyonu dakikalar içerisinde tamamlayabilmek!
Söz konusu problemlerin bir de, birden fazla sunucunun ya da birden fazla veritabanının olduğu noktalarda problem daha da karmaşıklaşıyor. Zira bir veritabanı ile ilgili böyle bir işlemi haftada bir, elle yapmak çok ciddi vakit almaz ya da kendi içerisinde büyük riskler barındırmaz. Ancak birden fazla sunucu, birden fazla veritabanı ve tüm bunların yanında bakımın yapılma sıklığını düşündüğümüz zaman süreci otomatize etmek artık zorunlu hale geliyor.

Yakın zamanda, PEAKUP olarak sahip olduğumuz bu çözümü Azure’ın REST API istekleriyle çözülebileceğini zaten tahmin ediyorduk. Ancak programatik olarak olması, ilgili sorunu olası bir durumda diğer ürünlerimizde ve hizmetlerimizde kullanabileceğimiz şekilde çözülmesi bizim için en önemli noktalardan birisiydi. Bu nedenle PEAKUP Azure Services çözümünü ele aldık. İlgili kaynak kod içerisinde, yalnızca SQL ile ilgili sorunları değil ek olarak, Web Application konusunda da benzer problemleri keşfedebileceğiniz çözümleri de bulabilirsiniz.

.NET 6 Geçişlerinde Azure DEVOPS Pipeline Incident

Microsoft uzun zamandır .NET 6 tarafında arka arkaya, ara geliştirmeler ve SDK çıkartmaya devam ediyor. PEAKUP’ın Velocity, Analytics ve Data ürünlerinde bu geliştirmeleri uzun zamandır yakından takip ediyoruz. Son SDK içerisindeki performans arttırıcı özellikleri dikkate alıp projeleri .NET 6’nın son sürümüne geçirmeye özen gösteriyoruz. Son zamanlarda çıkan her bir Preview SDK sonrasında DevOps pipeline içerisinde bazı aksaklıklar ve kesintiler yaşamaya başladık. Bugün sizlere bu küçük DevOps kesintisiyle nasıl karşılaştığımızı ve nasıl giderileceğini anlatacağım.

 

Uygulamalarımızı .NET 6 ile geliştirirken, Azure Web Application içerisinde host ederek çalışmalarını sağlıyoruz. Burada beklentimiz her bir SDK çıktıktan sonra Microsoft Container Registry servislerinde hemen yansıyan SDK Container paketleri gibi Web Application tarafında da ilgili SDK için kurulumların yapılması ve hazır olarak beklemesidir.

Ancak Microsoft 6.0.100-preview.7.21379.14 ve 6.0.1-RC paketinde Azure takımlarının geçişleri bizi bu konuda oldukça şaşırtıyor! Zira DevOps Pipeline içerisinde kurguladığımız Build aşamasında spesifik olarak 6 sürümlerinin en sonunu kullanmasını belirttiğimiz bir davranış Build ve Release Pipeline içerisinde herhangi bir hataya sebep olmasa da uygulamaya Deploy edildikten sonra sizleri sürpriz bir problem bekliyor!

Azure Web Application içerisinde .NET 6’nın RC paketi bulunmuyor! Kudu SCM üzerinde DOTNET SDK listesini incelediğiniz zaman RC paketinin eksik olduğunu ve uygulamanın bu nedenle hiçbir Exception fırlatmadan dakikalarca ayağa kalkmaya çalıştığını görebilirsiniz.

Problemin giderilmesi için Azure Web Application içerisindeki son SDK versiyonunu Pipeline içerisinde spesifik olarak belirtmeniz yeterli olacaktır!

 

Önü Alınmayan CPU Yükselişi ve Profiling Aracılığıyla Tespit Edilmesi

Bu problem boyunca yaptığımız ciddi code refactor, test ve daha az kaynak ile daha fazla performans elde ettiğimiz çalışmaları makale içerisine dahil etmedim. 8 Mart 2021 günü 2 Instance olacak şekilde Azure Web Application’da çalışan Velocity uygulaması bir anda CPU göstergelerinde ciddi artışlar olduğu ile ilgili hatalar fırlatmaya başladı. PEAKUP’da bu tarz problemlere yaklaşımımız genelde “öncelikle yangını söndür, söndüremiyorsan kontrol altına al ve süreci inceleyip, problem ortadan kaldır” şeklindedir.

Her ne kadar Auto Scaling ile ilgili Azure ayarlarını yapmış olsak da her bir Velocity müşterisi onboarding (tüm içeriklerin girildiği ve kullanıcı eğitimlerinin verildiği) sürecini tamamladıktan sonra kendi içerisindeki kullanıcılarına portal kullanımını duyurdukları zaman sistemi ikinci bir ekranda genel olarak izliyoruz. Anlık gelen kullanıcı sayısını Power BI üzerinden kendi geliştirdiğimiz Analytics Tool’u ile izliyoruz. Bu tarih için planladığımız, olası ansızın gelebilecek bir yük yoktu. Ancak ürünün kullanımı gereği bazı müşteriler portal içerisinden duyuru yaptığında da ansızın bir yük gelebiliyordu. Bu durumda Azure üzerinde otomatik olarak ölçeklendirme için CPU, Memory vb. metrikler üzerinde kurguladığımız alarmlar devreye giriyor ve anında olası bir problemin önüne geçiyorduk.

Bu defa taşıdığımız yük, günlük trafiğimizin ortalamasında olmasına rağmen 12 Instance açıkken bile bir türlü CPU ile ilgili problemi çözemiyorduk. Üzerinden toplantı odaları, yaklaşan toplantılarım vb. bilgileri çektiğimiz ONE uygulaması ve Authenticator uygulaması da herhangi bir spike ile karşı karşıya kalmamasına rağmen Velocity’de sıra dışı bir durum vardı.

Problemi gidermek için kontrol ettiğimiz, denediğimiz bazı adımlar;

  • Bağlı çalışan tüm diğer uygulamaların kaynakları ve veri tabanları yeterli seviyede yükü kaldırıyor mu?
    • Buradaki amacımız Velocity ve diğer tüm ürünlerimizin ortak olarak kullandığı Authenticator ya da bağlı olduğu herhangi bir servisin veritabanı tarafında ya da backend tarafda gönderdiğimiz talepler karşısında herhangi bir bottleneck yaşanıp yaşanmadığını kontrol etmek oldu. Hiçbir problem tespit edilemedi. Aksine fazla kaynak rezerve edildiği tespit edilip bazı kaynaklarda düşüşe gidildi.
  • Öncelikle SQL Server içerisinde Created alanına göre anormal bir veri artışı var mı?
    • Bazı müşteriler ürünü beyaz ve mavi yaka şeklinde ayırıp bu kullanıcılara portallarını belli bir arayla açabiliyorlar. Son gelen kullanıcı sayısında herhangi bir ani artış olup olmadığını inceledik. Ek olarak Velocity’nin free versiyonu tarafından gelebilecek olası bir artış var mı yok mu bu metrikleri kontrol ettik ve sıradışı bir durum tespit edemedik.
  • JSON Formatındaki Verinin Büyüklüğü Bizi Ne Kadar Etkiliyor?
    • Neredeyse iki yıllık haberleşme kayıtlarını, günlük verilerin girildiği, yüzbinlerce telefon numarasının olduğu bazı widgetların içerisindeki veriler işlenirken acaba CPU tarafında buna bağlı bir kilitlenme mi var sorusu aklımıza geldi. Bunun için müşterilerimizden en büyük veriye sahip olan Widgetlardan beş tane seçip bunlara, test ortamında random veriler girmeye başladık ve CPU tarafında hiçbir değişim olmadığını tespit ettik. Sorun yine çözülmedi!
  • Diğer uygulamalara bağlanıp veri çeken Widgetlarımız(Twitter, Toplantı Odaları, İzin Uygulaması, Haberler vb.) widgetlar tarafında mı bir problem var?
    • Bir Intranetin en önemli olan hizmetlerinden olan Toplantı Odaları, Yaklaşan Toplantılarım, Dış Kaynak Haberleri, Bugün Kimler Uzaktan çalışıyor gibi katma değeri en yüksek ama en fazla CPU tüketimi sağlayan widgetları tek tek kontrol ettik. Her birisini teker teker kullanımdan kaldırıp sonrasında CPU ile ilgili durumu monitör ettik. Ciddi bir düşüş gözlemlendi.
  • Problem Spesifik bir serviste mi? Başka servisleri de etkiliyor mu?
    • Bunu görmek için, Velocity’nin kullandığı tüm servislere Apache’nin AB toolu ile hem localde hem de DEV Stage içerisinde Linux bir makine üzerinden 1000 tane 50 Concurrent request göndererek metrikleri takip ettik. Velocity dışında One servisinde bir problem keşfedildi ve giderildi. Ancak sorun Velocity tarafında sürmeye devam etti.

Yüksek CPU kullanacak tüm Widgetları tek tek incelemeye başladık. Önce portaldan kaldırıp sonrasında oluşan yükün artış veya azalış durumuna göre hareket edecektik.

İlgili widgetlarla ilgili tam bir factoring süreci başlatmak üzereyken problemin tekrar yaşandığını ancak bu defa CPU’daki yükselişlerin daha kısa süre içerisinde normale döndüğünü gözlemledik.

Problemin JSON tipindeki verileri işlediğimiz bir aşamadan kaynaklanmadığından emindim. Çünkü CPU tarafındaki kaynakları tüketebilecek diğer tüm işlemler (Image Processing, Video Processing) başka bir servis içerisinde, döviz-hava durumu gibi widgetlar da başka bir servis içerisinden geliyordu. Bu nedenle JSON tarafında en çok işlem yaptığımız methodları inceleyip tekrar testlere başladık.

Velocity içerisindeki Dependency Injection apısı tamamen kullanıcını yaptığı ilk request sonrasında kurgulanmaktadır. Kullanıcının bağlı olduğu Tenant Hybird mi yani İstanbul’daki bir sunucuda mı çalıştığı yoksa Azure üzerinde Cloud’da mı çalıştığı yapılan ilk requestten sonrasında kurgulanmaktadır. Bu aşamada gelen kullanıcının kim olduğunun tanımını yapan endpointi yani tüm isteklerin aktığı OnActionExecutionAsync methodunu incelemeye başladım.

HttpClient kütüphanesi bu gibi arka arkaya yapılan işlemler için önerilmediğinden dolayı IHttpClientFactory tarafından aldığımız CreateClient methoduyla gelen tüm HttpClient objelerini saatlik olarak isimlendirmeye başladık.

İlk başlarda yaşadığımız spike problemi devam etse de CPU’daki %100 ve üzeri oranda takılı kalma problemi yine süre olarak ciddi anlamda düşüş gösterse de problem hala devam etti.

Problemi daha detaylı incelemek için Azure’un Web Application’a özel olarak sunduğu, tüm metrikleri inceleyebileceğiniz bir uygulaması bulunmaktadır. Bu uygulama application Insight olarak geçer. Velocity’de temel özellikleriyle birlikte açık olan bu uygulamanın tüm Profiling ile ilgili özelliklerini açmaya karar verdik.

Kaynakları arttırmaya devam edip, Azure Application Insight ile problemi araştırmaya, metrikleri toplamaya devam ederken şununla karşılaştık. Application Insight sonrasında ortalama olarak çok küçük sayıda diyebileceğimiz isteklerde bile uygulamada CPU %110’ün üzerine çıkmaya başladı. Araştırdığımızda buna başka geliştiricilerin de maruz kaldığını öğrendik. Haliyle Application Insight tarafını tamamen kapattık ve sorun büyük oranda çözülmüş gibi görünmeye başladı.

 

Sonrasındaki bir hafta boyunca herhangi bir problem olmadan devam eden süreç ilerleyen zamanlarda yüksek Memory Exception hatalarıyla tekrar baş göstermeye başladı… Uygulamalarımızı Web Application içerisinde InProcess olacak şekilde doğrudan IIS’e vermekteydik. Application Insight’ın yarattığı yükü kaldırmak ve direkt olarak performansı koruyabilmek için Kestrel üzerinden bir Reverse Proxy yarattık ve artık hataları çok daha derinlemesine görmeye başladık.

 

Uygulama içerisinde Kestrel sayesinde her bir Request ve SQL sorgusunun çıktısını görmeye başladık. Artık Application Insight’ı açıp bunun yanında ek olarak uygulamanın çalıştığı anda yarattığı hataları görebilir hale geldik. Takım arkadaşlarım Fatih Doğan ve Fatih Memiş’in de bu aşamada dahil olduğu süreçte Code Review aşamasına geçtik. Bottleneck (dar boğaz) yaşadığımız yerin daha uygulamaya gelen ilk isteğin işlendi süreçten başlayıp son aşamasına kadar bütün kodu satır satır kontrol etmeye başladık. Bu esnada artık Kestrel’dan hem daha mantıklı hem de daha yardımcı olacak hataları almaya başladık. Zira uygulama bir yerden sonra CPU tarafında herhangi bir problem yaşamasa da memory tarafında ciddi şekilde sorunlar yaşadığımızı ve bunun kurguladığımız Dependecy Injection mimarisinden oluştuğunu keşfettik.

Normal web uygulamalarında tüm Dependency’ler Startup içerisinde tanımlanırken, Velocity’de neredeyse bütün database ile alakalı Dependency’ler ilk requesttin geldiği BaseController içerisinde tanımlanıyor. Bunun sebebi gelen talebi karşılarken minimum seviyede kaynağı ayağa kaldırmak ve bazı davranışsal değişikliklerin request bazında olabilmesini sağlayabilmektir.

Dependency yapısını yönetmek için Startup.cs içerisinde ayağa Singleton olarak kaldırdığımız IServiceCollection Instance’ı problemin ana kaynağı gibi görünmeye başladı.

İhtiyaç olduğu kadar Depdency’i ayağa kaldırdığımız aşamada kullandığımız IServiceCollection sınıfının Scope ile ilgili işlemler bittikten sonra artık kullandığı kaynakları Memory’den atmadığını ve bunun bütün uygulamayı etkilediğini fark ettik. Normalde içerisinden çektiğimiz BuildServiceProvider methodu ile çektiğimiz bir servisi artık IServiceProvider ile yüklemeye karar verdik.

Geçişi sağladıktan sonra metrikleri takip ettiğimizde çok ciddi düşüşün olduğunu fark ettik. Bottleneck’e sebep olan şeyin Startup’da Singleton olarak eklediğimiz IServiceCollection Instance’ının BaseController içerisinde tekrar yeni bir IServiceCollection üzerinden alınması olduğunu keşfettik ve IServiceCollection yerine IServiceProvider ile ihtiyacımız olan Dependency kurgusunu sağladık. Böylece sorun ortadan kalkmış oldu.

Bu süreçte yaşanan sorunlar nedeniyle bizi hoşgörüyle karşılayan tüm Velocity müşterilerine, Fatih Doğan, Fatih Memiş ve tüm Velocity takımına teşekkür ederim.

Bir .Net Framework Projesini .Net Core’a Geçirirken Dikkat Edilecek Hususlar

PEAKUP’da kendi ürünlerimizin ihtiyacı olan bazı veriyi uygulama bazlı tutmak yerine tek bir merkezden sağlamak üzere uzun zaman önce geliştirdiğimiz bir “Data” projesi bulunuyor. Öncelikle biraz uygulamanın ne yaptığından ve neleri barındırdığından bahsetmek istiyorum. Projeyi henüz .NET Core ilk çıktığında geliştirmeye başlayıp, .NET Core’un biraz daha stabil hala gelmesini beklemek için .Net Framework ile geliştirdik.  Veri tabanı tamamen EntityFramework Code First ile tasarlandı. Veri tabanı olarak Azure SQL Server kullanıyoruz. Bu servis içerisinde hemen hemen her uygulamada ihtiyaç duyulan; kıta, ülke, şehir gibi coğrafi bilgilerin yanında 2020, 2021 yılı resmî tatil günleri, anlık hava durumu bilgisi ve döviz kuru ve benzeri gibi bilgiler yer almaktadır. Servis içerisinde verilerin sunumu için kullandığımız web uygulamasının yanında, hava durumu ve döviz için birden fazla kaynağa bağlanıp veri çeken ve bunları hem veri tabanına hem de Redis ile daha hızlı çıktılar vermek için Cache’e yazan iki Azure Job projesi daha bulunmaktadır.

Neden .Net Core’a Geçiş Yapıyoruz?

Öncelikle Microsoft’un .Net Core için uzun süredir yaptığı geliştirme eforuna ve olup bitene baktığımızda .Net Framework için uzun vadede geliştirmelerin bir süre sonra duracağını ya da kısıtlı bir hale geleceğini ön görebilmek hiç zor değil.  Anlatacağım birtakım şeyler .Net Framework ile de mümkün olsa da çıktılarının .NET Core kadar iyi olmadığı ya da süreç içerisinde ekstra zaman kaybına sebep olan bazı sorunlar yaşandığı aşikâr!

Projeye yakın zamanda eklemek istediğimiz; Image Compression, Video Compression gibi özellikler için arayıp bulduğumuz kütüphanelerin yalnızca .Net Core tarafında geliştirildiğini görmek, daha uzun vadede yapılacak geliştirmeler için bu eforu neredeyse yarı yarıya düşürmek anlamında çok önemli durumdadır.

Uygulamaya istek gönderen diğer PEAKUP ürünlerindeki kullanıcı sayısı giderek artarken dolaylı olarak tuttuğumuz hava durumu ve döviz verisinde de büyük bir artış gözlemleniyor. Uygulaya gelen istek sayısı ve verinin büyüklüğü arttıkça Response sürelerindeki artış ve hem web uygulamasının hemde kullandığımız SQL veri tabanının artık maliyet ve performans olarak bir probleme dönüşmesinin önünü almak en önemli sebepler arasında yer almaktadır.

Şu anda projeyi standart bir şekilde iki ayrı Git Branch’inde tutuyoruz. Geliştirmeleri Dev’de yapıp, her şeyin tamam olduğunu gördükten sonra master’a Merge edip bütün süreçteki Deployment faaliyetini manuel olarak yürütüyoruz. Sık sık açıp üzerinde geliştirme yaptığımız bir proje olmasa da bu sürecin Azure DevOps ile tamamen manuel ve elle Deploy edilir bir halden çıkartılıp. Otomatik olarak Deploy eden, veri tabanında Migration’ları kendisi çalışan bir hale doğru ilerlemesi arzu ettiğimiz bir geliştirme süreci, bunu .NET Core ile daha verimli ve daha hızlı bir şekilde yapmanın önü .NET Framework’e göre oldukça daha esnek zira proje içerisinde paket yönetimi daha kolay bir şekilde tasarlanmış.

PEAKUP tarafından tamamen SaaS olarak geliştirilen uygulamalara geçiş yapan müşterilerin, bütün süreci bir kerede tamamlayıp kullanıcılarına ürünleri duyurduklarına gelen sıra dışı yükü Scale etmek için uygulama tarafında sürekli Azure Servis Planları arasında geçiş yapmaktaydık. Bu hem maliyet olarak hem de uygulamayı Scale etmek konusunda Azure Web Application tarafında birtakım kısıtlamalara neden oluyordu. Azure DevOps ile uygulamanın tamamen Container’lara taşınarak hem kendini Scale Down yapıp hem de ihtiyaç durumunda sınırsız sayıda Container ayağa kaldırarak bütün taleplere, aynı ve hatta daha yüksek hızda cevap vermesi de olmasını istediğimiz özelliklerden birisiydi! Projeyi geçirdikten sonra yaptığım testler ile aslında Docker ve Kubernetes ile ilgili atılacak adımlar için çok erken olduğunu gördükten sonra web uygulamasıyla devam etmeye karar verdim.

Karşılaştığım Problemler ve Çözümleri

  • Routing’de Değişiklik

Üzerinde neredeyse yarım günlük efor harcadığım bu problemle karşılaştığımda geçişin ne kadar sancılı olacağını tahmin etmeye başladım. Proje içerisinde kullandığımız Interface tasarımında iki adet GET metodu bulunuyordu ve bunlardan bir tanesi tüm kayıtları ötekiyse aldığı Id parametresine göre verileri döndürüyordu. Net Core tarafındaki Routing ile ilgili hatalı tasarımların önüne geçilmek için bu daha izin verilmediğini araştırarak öğrendim. Bu nedenle metot içerisindeki Id parametresini Nullable yaparak duruma göre farklı davranan tek bir metot ile devam etmeye karar verdim.

  • Entity Framework Core’daki Değişen İsimlendirmeler

Projeyi geliştirirken kullandığımız modellerin tamamını .NET Core’a geçerken birebir kullandım. Auto Migration sayesinde veri tabanında çıkacak Schema’nın birebir olmasından emindim ancak .NET Framework tarafında ilişkilerin kurulduğu alan isimleri herhangi bir karakter değişimine uğramazken .NET Core’da ilişki için kullanılan alanlar arasında alt çizgi eklendiğini gördüm. Bu nedenle Schema’yı birebir kurmak ve direkt olarak Production’daki verileri taşıyabilmek için haliyle [ForeignKey(“X_Id”)] Attribute’undan faydalanarak kolonlardaki verinin eski standartlara uymasını sağladım.

  • Veri Tabanın Taşınması

Veri tabanında hiçbir veri kaybetmeden yaklaşık 12GB civarındaki verinin kopyasını Azure üzerindeki bir sunucuya çektim. Oradan kendi bilgisayarıma zipleyerek indirdiğim için 12GB civarındaki veriyi 900MB text olarak kendi makineme aldım ve verinin geçişi ile ilgili senaryoları denemeye başladım. Weather (eski hava durumu verisi), Forecast (yeni yayına aldığımız hava durumu verisi) ve Currency tabloları bu veri tabanındaki büyüklüğün başlıca sebeplerindendi. Bu nedenle bu üç tabloyu tek tek geçirerek ilerlemeye karar verdim. Denediğim senaryolar arasında SQL içerisinde adeta benchmarking yaptığımı söyleyebilirim.

Çektiğim dosyayı komple bir veri tabanı üzerinde ayağa kaldırıp ardından verilerin girişini sağlasam da işlemler hem uzun sürüyor hem de belli bir yerden sonra hata verdiğinde bütün süre boşa gidiyordu. Bu nedenle her bir satırın tek tek taşınması ve iki farklı veri tabanındaki Schema’ların birbiri arasındaki uyumu görmek için SQL Management Studio içerisinde varsayılan olarak gelen Import Data seçeneğini tercih ettim. Bu aşamada Entity Framework’ün tarih tipindeki alanlar için .NET Framework’de datetime, .NET Core’da da datetime2 veri tipi farklılığı yarattığını gördüm.

Tekrar projeye dönüp Datetime alanlarının başına [Column(TypeName = “datetime”)]

Attribute’unu ekleyerek bu alanlarında Schema’da veri geçişi için bu şekilde kalmasını sağladım ve verileri başarılı bir şekilde kendi makinamda 15 dakikada taşıdım.

Production’da artık bir EF Core veri tabanı ayağa kaldırmak için Web Uygulaması açarak hem veri tabanını hem de uygulamayı Deploy ettim. Burada .NET Core kullandığım için Linux tipindeki Web Application ile ilerlemeye karar verdim ve sonrasında bazı problemler yaşadım. Bununla ilgili bir sonraki adımlarda bahsettim.

  • Cache Katmanında Kütüphane Değişikliğine Gidilmesi

Hem performans hem de API tasarımı daha iyi olmasının yanında kendisine özel geliştirilen JSON kütüphanesi ile daha performanslı bir önbellek çözümü sunan ServiceStack.Redis kütüphanesini kullanmaktaydık. Ancak hem bu geliştirmeyi yaptığımız Nuget kütüphanesinin uzun zamandır güncellenmediği için bu faydadan uzak kaldığımız hemde Connection Pooling ile ilgili performansını yeterince göremediğimiz için StackOverFlow tarafından geliştirilen StackExchange.Redis kütüphanesine geçiş yaptım.

  • Text. Json’daki Kritik Eksiklikler

Microsoft’un .NET Core içerisinde hem performans hem de JSON işlemleri için uzun zamandır saplantılı bir şekilde System.Text ve altındaki bütün kütüphanelerde geliştirme yaptığını söyleyebilirim. Benchmarking testleri yapıldığında System.Text Namespace’ini kullanan bir çok projede neredeyse her Framework versiyonunda büyük bir performans artışı görüldüğünü uzun zamandır takip ediyordum. Hem Newton.Json hemde ServiceStack.Redis’in JSON kütüphanesinden kurtulmak için API’dan dönen JSON’ları ve Cache’e veri okuma-yazma işlerinde Built’in gelen bir kütüphanenin daha iyi olacağını düşünerek tahmin ettim. Ancak sonrasındaki hayal kırıklığı çok büyük oldu! Zira Newton.Json’dan geçişle ilgili yayınlanan Microsoft dokümanında PreserveReferencesHandling, ReferenceLoopHandling gibi birçok özelliğin henüz geliştirilmediğini gördüm. Bu nedenle Built’in gelen bütün kodu geriye aldım ve Newton.Json ’la devam ettim.

  • Linux Web Uygulamasında Azure Tarafında Tamamlanmamış Özellikler

Uygulamayı öncelikle elle test edebileceğim ve sonrasında performans testleri yapabileceğim, herhangi bir Pipeline beklemeden, Staging sonradan devam etmek üzere standart bir şekilde ayağa kaldırdım. Publish ederek işlemi başlattım ve o gün Azure’da yaşanan bir saatlik bir kesinti ile şans eseri karşılaşıp uygulamada bir problem olduğunu düşündüm. İki saatimi kaybettikten sonra Microsoft tarafında bir Incident yaşandığını ve çalıştığımız Avrupa kıtasındaki bazı işlemlerde problem olabildiği bilgisini aldım. O sırada uygulamanın sonraki adımlarını incelemek üzere diğer çalışmalara başladım. Fark ettim ki kesintiyi iyi ki yaşamışım!

Döviz ve hava durumu ile ilgili çektiğimiz verilerin bazıları anlık akarken bazılarıysa saatlik gelmektedir. Bunları uygulama içerisinden çıkmadan, Azure Job olarak zaten daha öncesinde de ilerletiyorduk. Aynı şekilde kalmasına ve olacaklar ile ilgili problemleri gözlemek için Web Application içerisinde Web Job sekmesini aradığımda sekmeyi bulamadım! Önce uygulamanın Tier’ı ile alakalı olabileceğini düşündüğüm bu problem için uygulamayı bir üst Tier’a geçirdim ve Web Job tekrar gelmedi. Sonrasında araştırdığımda henüz Linux tipindeki Azure Web Application’larda birçok şeyin eksik olduğunu öğrendim. Kesintinin bitmesini beklemeden direkt uygulamayı sildim ve Windows tipinde yeni bir web uygulaması açarak devam ettim.

Bu aşamada bu kararı vermemin sebebi Load testlerde yakalanacak başarıya göre yapının tamamen Kubernetes ve Container üzerinden devam etmesiyle ilgili oldu.

  • Load Testlerin Yapılması

Herkesin Email Marketing şirketi olarak bildiği SendLoop’un mühendislik takımı tarafından geliştirilen hem ücretli hem de ücretsiz bir aracı bulunuyor. https://loader.io/ adresinden erişebileceğiniz bu Tool ile her zaman önce ilk testin buradan geçmesini bekler sonrasında da Apache’nin AB projesi ile yük testlerini gerçekleştiririm. 10,000 isteğe kadar çıkan bu ücretsiz Tool ile ilk test oldukça başarılıydı. Response Time’da ciddi düşüşler görülüyor ancak uygulama belli bir süre sonra yavaşlamaya başlıyordu.

Azure içerisinde Web Application’da Memory’de anlamsız bir şişme ve bir yerden sonra 1MB boyutunda bile yer kalmadığını fark ettim. İstekleri incelediğimde Redis Cache içerisinde kullandığım metodun verinin verilen Key üzerinde OverWrite yerine AddAndWrite senaryosu ile ilerlediğini fark ettim! Hemen bu problemi çözüp paketleri güncelledikten sonra testlere devam ettim.

SendGrid tarafında isteklerin başarılı bir şekilde geçtiğini gördükten sonra AB Tool’u ile testler yapmaya başladım. Bunun için internet bağlantısı çok iyi olarak bir sunucuyu kullandım. Artık her şey hazır ve DevOps’daki son adıma geçebilirdim.

  • DevOps Pipeline Kurulumundaki Yenilikler

Projeyi artık istek alır hale getirdikten sonra makalenin girişinde de bahsettiğim Production, canlı ortam ve son kod geliştirmesiyle birlikte çalışan Beta ve DEV olacak şekilde üç Stage’e ayırmaya başladım. Önce Master yani Production sonrasında da silsileyi takip edecek şekilde geçişleri tamamladım. Her bir Stage için ayrı veri tabanı açtım ve hepsini Master’dan taşımaya devam ettim.

Azure’un DevOps Pipeline’ında yaptığı bir arayüz değişikliği ile ilk defa karşılaştım. Artifact çıktısını Release adımına geçirirken burada bir Versionlama sistemiyle artık kütüphane alt yapısının yani ConnectionString, özel anahtarlar gibi ayarlar ile ilgili yapılan değişikliklerin de bir Step olarak eklendiğini öğrendim.

Why You Must Use Unique Identifier Data Type in Your Primary Key Field?

Database design can affect the entire project’s status critic level. If the complexity of the database-side operations is complicated, the complexity of database-level design and choice of complex queries is likely to be big time cost in the future.
When software developers develop projects in by herself/himself or as a team, the way they usually follow is two-fold. They follow established rules that are already in place/project as a team member but this happens when they are in an existing project. The whole database and architecture design follows the habits they have when they are up to herself/himself.
Developers change their habits in software-side very quickly and always try to find the best, however developers can be quite conservative in database phase. It is not so easy to make changes to database design because it will affect the way that get used to develop. That’s why today I will blog about why we need to use unique identifier data type in the database in the primary key field. This may seem very rubbish or small issue, but it is the base of database and it will save and protect you more thing you can imagine.

Advantages:

• Multitenancy
We use a mutually-tenant structure/design in our applications and products such as Sign&Go professional email signature tool, the easy sms password reset solution Passgate we developed in PeakUp. Even in scenarios where multiple applications or databases are running separately in Azure or AWS, it becomes almost impossible to follow along with the integer data typed records in the process of separating applications from each other in the database where only logs are kept. Another scenario you can also see is that you can think of a resource scenario in multilingual applications that are stored in a single database. It is always easier to set up and track resource records based on unique identifier, even if you have key-value traversal in the resource.

• Security
In a bad security breach scenario with SQL injection, attackers will find it more difficult to exploit weaknesses, as they are quite relaxed at the expiration of the grant by following the numbers 1,2,3 in the id column. It provides a lot of confidence in the way that user-side recordings are prevented from being intercepted by the web address.
Besides, using GUID will be extra helpful if you are exporting your data via web api and want to provide a standard.

Disadvantages:

• Performance
Since the GUID data type has a 4-byte index value, some problems may be encountered if you are not careful in sort operations and join. In addition, you will need the “Created “ field in the process of ordering old or new records, which will actually bring you a more reportable data structure.

• Easy Readability and Registration Test
Testing the data coming to the database or giving a lot of confusion in direct SQL queries can slow down or make it harder because of the size and difficulty of memorizing.

Email Marketing Yaparken Dikkate Edilecek Hususlar

Bir önceki yazımda bir email marketing kampanyasının içeriğini hazırlarken nelere dikkat etmeniz gerektiğini, içeriğin hangi formatta ve hangi teknik niteliklere sahip olmasının yanında mutlaka kendinize ait olan listeye gönderim yapmanız gibi detaylardan bahsetmiştim. Bu yazımda daha çok gönderimlerin optimizasyonu, inbox’a düşme oranını, açılma oranı ve tıklama oranı gibi parametreleri nasıl optimize edeceğinizi anlatacağım.

Öncelikle email gönderimlerini yapmadan önce hedef müşterilerinizin analizini yapmak, müşterinin sizin gönderdiğiniz kategorideki (alışveriş, haber, vb.)  Emailleri ne zaman okuyacağını ön görmeniz gerekiyor. Eğer ön göremiyorsanız aylık periyod içerisinde gün bazında her gün birer veya ikişer saat arayla email gönderimi yaparak A/B testinden elde edeceğiniz bu sonuçlardan yola çıkabilirsiniz. Örnek vermek gerekirse eğer yurt dışına hitap eden bir gönderim yapıyorsanız ağırlıklı olarak müşterileriniz Avrupa kıtasındaysa bu kıtaya en uygun saatte email gönderimi yapmanız sizin için doğru bir seçim olacaktır. Eğer kategori bazında ay başı, mevsim veya sektöre özel (yaz tatili gibi) dönemler kampanyanızın kurgusunda yer alabiliyorsa, bunları da göz ardı etmemek önemli olacaktır. Burada elde ettiğiniz doğru zamanlama verisi, doğru dönemsel aralık belirlenmesi, email marketing kampanyalarınızın yanında varsa mobil uygulamalarınızda da bildirim gönderiminde zamanlama olarak dost bir unsur olarak kullanılabilir.

Email gönderimlerinizi yaptığınız listede eğer hiçbir şekilde dönüşüm alamadığınız adresler varsa bunları ayrıca kategorize edip, bir zaman sonra hala dönüş alınamıyorsa komple listeden çıkartmanız gönderim maliyetlerinizi düşürmenin yanında skorunuzu da yüksek tutmakta oldukça fayda sağlayacaktır. Bu kategorideki müşterilerinize zamanla çok özel teklifler göndererek geri kazanmaya çalışmanız da seçenekleriniz arasında yer alabilir. Bunu genel olarak ilk alışverişlere özel indirimlerin veya fırsatların sunulduğu kampanyaların kurgularında kullanılması tercih edilmektedir.

Standart şablonla email kampanyaları sunmanız müşterileriniz için bir zaman sonra göz aşinalığı yaratması açısından oldukça önemlidir. Kampanya içerisindeki HTML’e gömülü linklerin içerisinde kurulacak utm_source ve utm_medium parametreleri bu aşamada optimizasyon için en uygun seçenek olabilir.

Email gönderimi öncesinde, gönderim yapacağınız domainin IP adresinin Block List içerisinde girip girmediği, reputation gibi sürekli değişebilen durumlarının kontrolünü mutlaka yapmanız hatta mümkünse kendinize ait bir IP adresi üzerinden sadece sizin gönderim yapmanız ISP’ler ve Mail Provider şirketleri tarafından tavsiye edilmektedir.

Bazı kullanıcılar maillerini farklı Client üzerinden takip ediyor olabilir. Bu nedenle farklı tarayıcılarda ve Clientlar’da gönderilen içeriğin nasıl göründüğünü mutlaka gönderim öncesinde test etmeniz sizin için faydalı olacaktır. Bununla ilgili testleri hangi Clientlar üzerinde yapmanız gerektiğini ilk gönderimlerinizden sonra elde edeceğiniz sonuçlardan elde edebilirsiniz. Ayıca webde görüntüle, sayfada gör gibi linkler ile mutlaka ayrıca bir alanda email içeriğinin görüntülenmesini de sağlamanız size ekstra dönüşüm sonuçları sağlayabilir.

E Posta Pazarlamada Doğru Şekilde İçerik Hazırlama

Geçtiğimiz günlerde dünyada Black Friday (Kara Cuma) olarak bilinen indirim kampanyasıyla online alışveriş mağazalarının diğer adıyla e-ticaret sitelerinin kullanıcılarına indirim kampanyaları hakkında gönderdikleri binlerce sms, email ve mobil uygulama üzerinden bildirimlere şahit olduk. Bazen rahatsız edici seviyeye ulaşan bu pazarlama ve reklamcılık aktivitesi aslında doğru yapıldığında hem müşteriyi hem de reklam vereni oldukça kazançlı ve mutlu bir hale getirebilir.

Bu makalede email marketing bölümünü ele alacağız. Email marketing (eposta pazarlama) yaparken dikkat edilmesi gereken hususları gördüğüm ve bildiğim kadarıyla anlatmaya çalışacağım. Eposta pazarlama 3 aşamadan oluşan bir dijital pazarlama yöntemidir. Yaklaşan yılbaşında ve ilerleyen dönemlerde bu makalenin, yapılacak olan email marketing kampanyalarında faydalı olmasını diliyorum. İki ya da üç aşamalı olarak yazacağım bu makalede bir email pazarlama kampanyasının döngüsünde önemli olan noktalara değinmeye çalışacağım.

Email kampanyalarınızı gönderirken kendinize ait olan listeye gönderim yapmanız çok önemlidir. Bir başkasının email listesine gönderim yapmanız hem size hem de kullanıcılara zarar vereceği gibi kanunen de yasaktır. Birçok email gönderim şirketi zaten eğer listenin size ait olmadığını düşünürse veya bundan kuşkulanırsa, bununla ilgili olarak email listesini nereden ve nasıl edindiğinizle ilgili olarak sizden kanıt ve bilgi isteyecektir. Bu aşamada uyguladıkları kontrol algoritmaları ve teknikleri konusunda oldukça başarılı olan email gönderim platformlarının tamamında bu uygulama ile karşılaşacağınızdan emin olabilirsiniz.

Email içeriklerini hazırlarken aşağıda yer alan hususlara dikkat etmeniz, gönderdiğiniz emaillerin hem inbox’a düşerek daha çok dikkat çeken bir bölümde yer almasını hem de açılma ve tıklanma oranlarını arttırarak sarf ettiğiniz eforun dönüşünü sağlayacaktır.

Şunu kesin olarak belirtmek gerekir ki çok büyük listeye sahip olmaktansa çok yüksek açılma, tıklanma ve dönüşüm oranlarına sahip olmak daha iyidir. Büyük listelere sahipseniz ve az açılma oranı problemiyle karşı karşıyaysanız bazı şeyleri yanlış yapıyor olabilirsiniz.

  1. Email İçeriği ve Şablon

Müşterilerinize gönderim yaparken tek bir imajı olduğu gibi göndermeniz neredeyse hiçbir etki yapmayacaktır. Özellikle bilgisayar kullanımı konusunda kısıtlı bir kitleye gönderim yapıyorsanız her şeyi olabildiğince anlaşılır tutmanız gerekmektedir. Bu nedenle imaj yerine HTML içerik veya tamamen Text içerik göndermeniz daha doğru olacaktır.

Photoshop veya bir başka tasarım programıyla çizdiğiniz emailleri HTML’e çevirip gönderirken veya var olan standart email şablonunuzu kullanırken imajlardan olabildiğince kurtulmanız gerekiyor. Bu hem gönderim süresinde etki eden hem de kullanıcının emaili görüntülediği clientda hızlı açılmasını sağlayacaktır. Eğer bolca imajın olduğu bir içeriği gönderiyorsanız mutlaka belli parçalara bölmeniz ve IMG etiketi içerisindeki ALT özelliğini o resimle ilgili olarak doldurmanızı tavsiye ederim.

Fotoğraflara alt özelliğini dolu olarak gönderdiğiniz durumlarda, varsayılan olarak imajların kapalı geldiği tüm email görüntülemelerinde kullanıcıyı fotoğrafları görmeye ve emaili açmaya doğru daha fazla ikna edici bir içeriğe sahip olacaksınız. ALT bilgisi bu aşamada imaj hakkında kullanıcıya ön bilgi sağlamaktadır.

İmajlara alternatif olarak CSS ile uygun şekilde biçimlendirilmiş olarak email şablonlarını %50 imaj %50 Text olarak hazırlamak hem zaman hem de kullanıcı tarafında oldukça uygun bir yöntemdir.

Bu şekilde hem “Satın Al”, “Sepete Ekle”, “Sipariş Ver” gibi butonların bir şekilde kullanıcılar tarafından görüntüleneceğinden kesin olarak emin olabilirsiniz.

  1. İster Pure(Salt) Text içerik isterseniz HTML içerik gönderin, yeni çıkan kanunlarla birlikte kullanıcıların şirketiniz hakkında bilgi sahibi olabilecekleri adres, telefon gibi bilgilere email kampanyanızın en altında yer vermek zorundasınız. Bunun yanında kullanıcıların listeden çıkabileceği linki de aynı şekilde içerik olarak bulundurmak sizi bağlayan bir diğer kanun ve kurallardan birisidir.
  2. Sosyal medya hesaplarınızı, blog adresinizi vb. email kampanyanızda adres ve abonelikten ayrılma bilgilerinin yer aldığı bölümden bir önceki satırda belirtmeniz genel olarak kullanıcıların kampanyanızla ilgilenmiyorsa bile sizi sosyal medyada takip etmenizi sağlayabilecek, onları bu yönde kanalize edebileceğiniz yegâne yollardan birisidir. Sosyal medya gibi linklerin yanında ayrıca mobil uygulamalarınızın linklerini de paylaşmanız oldukça iyi olacaktır.
  3. İçerik içerisinde kullanılan bazı önemli kelimeler ve linklere dikkat etmeniz gerekiyor. BitLy gibi link kısaltma servislerini email kampanyanız içerisinde kullanıyor olmanız, iyi bir spam skoruna sahip olmanıza ve her şeyi doğru yapmanıza rağmen sizi spam kutusuna düşürecektir. Bunun yanında viagra, porn gibi kelimeler Gmail, Hotmail ve Yahoo gibi servisler için abusive filtrelerine veya kullanıcının client’ında kurulu güvenlik uygulamalarına takılacağından direkt olarak gönderimleriniz spam kutusuna düşecektir ve belki de hiçbir şekilde kullanıcıya ulaşmayacaktır.
  4. Gönderdiğiniz içerikte bulunan resimleri bir CDN içerisinde tutmak ve PNG formatında olduğu gibi sıkıştırarak yayına almanız içeriğin hızlıca yüklenmesini sağlar. Bunun için TinyPng sitesinden faydalanabilirsiniz.

Genel olarak bu başlıklar ve kurallar doğrultusunda email içeriklerinizi hazırladığınızda inbox’a ulaşma, görüntülenme, açılma ve tıklamalarda hareketlilik elde edeceğinizi umuyorum. Aslında birçok email sağlayıcısının önerdiği hatta bazılarının zorunlu kıldığı DKIM ve SPF kayıtlarınızı da mutlaka yapmış olmanız gerekmektedir. Bunu domain bilgilerinizi yönettiğiniz kontrol panelinden gireceğiniz ilgili A ve TXT kayıtlarıyla sağlayabilirsiniz.

 

SharePoint Framework (SpFx) İçerisinde jQuery Kullanımı

SharePoint Framework kullanarak geliştirme yaparken UI ve Http istekleri için kullanabileceğiniz birçok seçeneğe sahipsiniz. Popüler JavaScript Framework’lerinden bazılarının isimlerinden bahsetmek gerekirse Angular, React, Vue.js, Knockout başta gelebilir. Bunun yanında dilerseniz JavaScript kütüphanesi olarak jQuery de kullanabilirsiniz. Basit WebPartlar geliştirmek için Pure JavaScript’te iyi bir seçenek olarak köşede durabilir.

Kodun bakımı, yönetilebilir olması, devamlılığın sağlanması, birlikte geliştirilebilirlik ve UI’daki kompleksliğe göre en uygun framework’ü veya kütüphaneyi seçmek elbette size kalıyor. Ben bu yazımda SharePoint Framework ile birlikte jQuery nasıl kullanılabilir bundan bahsedeceğim. Sharepoint Framework ile jQuery‘yi seçme sebebim hem çokça geliştiricinin jQuery’e hâkim olması hem de topluluklar ve doküman anlamında iyi bir kaynağa sahip olması. Bunun yanında ek olarak ihtiyacım olan tüm taleplere cevap verebilir düzeyde olması yeterli bir sebep olacaktır diye düşünüyorum.

Önceki yazılarımda çokça bir proje için SharePoint Framework ile kurulumun nasıl yapıldığını çokça anlattım. Bu nedenle artık kurulum aşamasını geçiyorum ve kurulu bir ortama sahip olduğunuzu varsayıyorum.

Öncelikle “npm install –save jquery@2″ komutunu çalıştırarak projemiz içerisine kütüphaneyi indirelim.

Daha sonra “npm install –save @types/jquery@2” komutunu çalıştırarak jQuery Typinglerini de projemiz içerisine eklemiş olalım. Typingler sayesinde geliştirme yaparken çok güçlü bir intellisense (otomatik tamamlama) desteği alabiliriz.

SharePoint Framework kurulumuna nazaran bu kütüphaneler boyutları küçük olması nedeniyle yüklenme aşamasında çok fazla vakit almayacaktır.

WebPart ile ilgili işlemlerimizi tamamlayıp ilgili projeyi SharePoint online içerisinde deploy ederken scriptleri bundle ettiğimizde bu paket içerisinde jQuery’nin de olması gerekiyor. Bu nedenle configconfig.json dosyayı içerisine aşağıdaki tanımlamayı yapalım.

“externals”: {

“jquery”:”node_modules/jquery/dist/jquery.min.js”

}

sharepoint config dosyası

Projemizi geliştirdiğimiz .ts uzantılı dosyamızda, en yukarıda kütüphaneleri çağırdığımız namespace alanında aşağıdaki tek satırlık kodla jQuery’i hangi alias (takma isim) ile kullanacağımız da belirttikten sonra proje içerisinde jQuery’nin tüm yeteneklerinden faydalanabiliriz. Burada “as” direktifinden sonra kullanacağınız isimlendirme ile tüm class içerisinde sağlayacağınız erişim anahtar kelimesini belirttiğinizi de bildirmek isterim.

import * as jQuery from
‘jquery’;

Bir örnek vermek gerekirse, DOM içerisinde bir objeye en kolay aşağıdaki satırları kullanarak ulaşabilirsiniz.

örnek demo

Bir sonraki yazımızda görüşmek üzere.

SharePoint Framework’de Çok Dilli Geliştirme

SharePoint Framework ile uygulama geliştirirken çok dilli bir yapıya ihtiyacımız varsa bunu Resource yapısını kullanarak çok basit bir şekilde yapabiliriz.

Sharepoint Online ile bu özelliği kullanmak çok kolay. Eğer WebPart içerisinde tanımladığınız diller, kullanıcının alternatif olarak seçtiği diğer diller içerisinde yer alıyorsa gerekli dilde gösterim otomatik olarak yapılıyor.

Öncelikle kullanıcımızın varsayılan dil seçeneğinin yanında kullanmak isteyeceği alternatif dili nasıl ayarlayabiliriz bu adımı tamamlayalım. Bunu en kolay şekilde yapabilmek için aşağıda yer alan linki tıkladıktan sonra gereken adımları takip etmeniz yeterli olacaktır. https://eur.delve.office.com


Ben İngilizce diliyle SharePoint kullandığım için örneği de Türkçe ve İngilizce dil seçenekleri üzerinden anlatacağım. Görüldüğü üzere dil seçenekleri ve diğer alanlarla ilgili olarak Privacy(Gizlilik) ayarları da yapmak mümkün görünüyor.Çok dilli portalların yanında, birden fazla ülkeden SharePoint kullanıcısına sahipseniz buradaki ayarları kullanarak belli standartları genel olarak tanımlayabilmeniz mümkün.

Bir önceki SharePoint Framework’e Giriş ve WebPart Geliştirmek
makalesini takip ederek baştan bir WebPart projesi için kurulum yapabilirsiniz. Bu kurulumu yaptığınızı varsayıyorum.

Microsoft’un en son çıkarttığı, kısa sürede çok sevilen IDE diğer adıyla editörü yani VS Code veya Visual Studio kullanarak uygulamalarınızda gerekli kodu çok kolay bir şekilde yazabilirsiniz. Ben hafifliği ve Cross Platform geliştirmenin mümkün olabilmesi için bu makalede şimdilik Visual Studio Code kullanacağım.

Command Prompt ile gerekli klasörün içerisindeyken “code .” komutuyla projeyi VS Code ile açalım.



Kırmızıyla işaretlediğim alandan da görebileceğiniz üzere ağırlıklı olarak çalışacağımız klasör “src” klasörü. Bunun yanında WebPart uygulamaları geliştirirken versiyon kontrol sistemi olarak Git’de kullanabiliriz. Gerekli dosyalar varsayılan olarak gelmektedir.

Makalemizin ana konusu olan çok dilli yaptığı Resource üzerinden sağlayabilmek için srcloc klasörüne bir göz atalım.

mystrings.d.ts dosyamız Resource mantığı içerisinde “Key” bilgilerinin tutulduğu dosyamız. Bu dosyayı çok dilli bir yapı kullanmıyorsanız bile şimdilik silmeminizi tavsiye ederim. Dosya içerisinde varsayılan olarak gelen 3 adet Property yani key bulunuyor. Bunun yanında ben ekstra olarak ApplicationTitle adında, string veri türünde bir Property/Key daha tanımladım.

Şimdi loc içerisinde tr-TR global Locale Standartını kullanarak bizim için gerekli dosyamızı oluşturalım. Burada kullanacağınız tire karakterinin, alttire yerine normal tire olması önemlidir. Dosya içeriğini aşağıda görebilirsiniz.

Artık dil dosyasıyla ilgili olarak tanımlamalarımız bitti. Hemen WebPart uygulaması üzerinde nasıl kullanacağımızı görelim.

Öncesinde bu dosyaların oluşturulması, intellisense desteği alabilmek ve css ile ilgili. Scss uzantılı dosyalardan gelen uyarılardan kurtulmak için “gulp build” komutunu çalıştırarak projemizi derleyelim.

Proje ile ilgili tüm geliştirmeyi yapacağımız HelloWorldWebPart.js dosyasını açalım. Burada HelloWorldWebPart isimi benim kurulum aşamasında verdiğim isim, elbette siz farklı bir isim vermişseniz farklı olacaktır.

Eğer C# veya Java gibi programlama dillerine hakimseniz dosyayı ilk açtığınızda TypeScript yapısı size çok tanıdık gelecektir.

15. satırda yer alan Render methodu tüm C#’daki Console uygulamalarında yer alan Main methodu gibi uygulamanın başladığı Entry Point olarak kabul edilebilir. Burada proje içerisindeki CSS’in dahi çok programatik bir şekilde kullanıldığını görmek mümkün. Oluşturduğumuz Resource dosyası içerisindeki anahtarlara ${strings.PropertyName } notasyonuyla ulaşmak ve bu aşamada intellisense desteği de alabilmek mümkün.

Uygulamamız en basit şekilde görüntülemek için hazır. “gulp serve” komutuyla uygulamayı çalıştıralım ve iki farklı kullanıcı tarafında hangi dillerin kullanıldığını görelim.

İki farklı Browser’da iki farklı hesaptan giriş yapıp Web Part uygulamasını bir sayfaya eklediğimde elde ettiğimiz sonuç aşağıdaki gibidir!

Makalenin kaynak koduna buraya tıklayarak PeakUp Github hesabından ulaşabilirsiniz.

SharePoint Framework’e Giriş ve WebPart Geliştirmek

Sharepoint Online 2016’nın çıkmasıyla birlikte geliştiricilerin işini ciddi oranda kolaylaştıracak olan Sharepoint Framework’de beraberinde geldi. Bu bir ihtiyaçtan dolayı doğdu çünkü Online tarafta Server-Side kod çalıştırma imkanımız ciddi oranda kısıtlanmış oldu. Ancak Sharepoint Framework sayesinde OnPremise’den farklı olarak ServerSide kodu ciddi ölçüde ClientSide tarafa taşıyarak hem sunucu üzerindeki yükü azaltabiliriz hem de yanında kullanabileceğimiz React, Angular, Vue veya Jquery sayesinde çok şık arayüzler hazırlayabiliriz. TypeScript’in FrameWork içerisinde tercih edilmesi size JavaScript tarafında Object oriented Programming (OOP) niteliklerini elde etmenizi sağlıyor. Bu sayede geliştirme süreçleri kolay, kodun bakımı da ciddi anlamda kolay hale geliyor. Sharepoint Framework genelde SpFx kısaltılmış adıyla dökümanlar içerisinde geçiyor. Gelecek yazılarımızda ben de olabildiğince bu şekilde kullanmaya çalışacağım.

Bilindiği üzere Microsoft son yıllarda development araçları içerisinde Node.js’e yer veriyor. Node.js, Sharepoint Framework’ünü kurup, kullanırken de yine karşımıza çıkıyor. Çünkü tamamen Cloud’a taşınan bir platform, geliştirme ortamında platform bağımlı olması absürd olurdu. Node.js ve yanındaki araçlar sayesinde platform bağımsız olarak dilerseniz Linux veya Mac üzerinde de WebPart geliştirmesi yapabilirsiniz.

Sharepoint Framework kurulumu ve geliştirme için ihtiyacımız olan şeyler sırasıyla;

  1. Node.js
  2. Yeoman (Yo)
  3. Gulp
  4. Visual Studio Code veya direkt olarak Visual Studio

Node.js’in sitesinden son stabil Node.js setup dosyasını indirip kurulumu tamamladıktan sonra Administrator haklarıyla beraber bir Command Prompt ile kuruluma devam edelim. Administrator haklarıyla Cmd açmak için aşağıdaki adımları takip edebilirsiniz.


Şimdi sırasıyla aşağıda yer alan komutları çalıştırarak kuruluma devam edelim. Hangi komutun ne işe yaradığını kısa bir şekilde açıklamaya çalışacağım. Aslında komutlar ne işe yaradıklarını anlatsalar da bazı ince detayları kaçırmasak iyi olur.

  • npm install -g yo gulp
    • Gulp:Hazırladığımız WebPart dosyasını paketleme, solution hazırlama ve js-css dosyasını bundle(sıkıştırma) edip çalıştırmamızı sağlayan bir tool olan Gulp’ı kuralım.
    • Yo diğer adıyla Yeoman, NPM’e alternatif olarak daha başarılı bir paket ve generator yönetim aracı. Facebook tarafından geliştirildi ve güncelleniyor.
  • npm install -g @microsoft/generator-sharepoint
    • Bu aşamada Microsoft vendor’u üzerinden Sharepoint Framework generator dosyalarını çekiyoruz ve belli bir yere kaydediliyor. Bu sayede yeni bir WebPart projesi oluşturduğumuzda tekrar indirip, kurulum yapmamıza gerek kalmıyor. Bu kurulum bağlantı hızınıza göre 5 ile 10 dakika arasında sürebilir.
    • -g parametresinin kullanılması Globally olarak talebin yerine getirilmesini belirtiyor.Böylece paketi her seferinde çekmeden direkt olarak bilgisayarımızın diskinden kullanmış oluyoruz.
  • Son olarak Microsoft’un sitesinden kullandığınız OS veya ihtiyacınıza göre Visual Studio seçeneklerinden birisini indirelim.

Bu aşamaları tamamladıktan sonra ilk WebPart dosyamız için Frameworku kullanmaya başlayabiliriz. Bir Command Prompt(artık cmd.exe olarak adlandıracağım) açalım.

WebPart uygulamaları geliştirirken ben şimdilik Visual Studio Code kullanacağım. Bu nedenle Cmd.exe üzerinde ciddi şekilde mesai harcayacağız bu nedenle bazı basit trickleri veya özellikleri kullanıyor olmamız bizi ciddi anlamda göz yorulmalarından uzakta tutacak ve hataların okunmasını kolaylaştıracaktır.

Ben hem Linux’dan gelen alışkanlık hem de yazdığım komutları daha iyi görebilmek ve hataları kolay takip edebilmek için cmd.exe’nin fontu büyütüp kullanılan rengi değiştiriyorum. Bu adımları takip etmeniz tamamen sizin tercihinize kalmıştır.


Artık herşey tamam olduğuna göre ilk WebPart’ımızı indirip, kurma aşamasına geçebiliriz.

“yo @microsoft/sharepoint” komutunu çalıştırarak kurulumu başlatalım.

Yo bize kurulum aşamasında bazı seçenekler önerecektir. Bunların arasında önemli olanları makalenin ilerleyen bölümlerinde anlatacağım. Yazımın başında da belirttiğim üzere ihtiyacınıza uygun olarak React,Angular veya Jquery frameworklerinden ve kütüphanelerinden faydalanabilirsiniz veya hiçbirisini kullanmadan direkt olarak SPFx kurulumu yapabilirsiniz.

Son zamanların en çok tercih edilan JavaScript Frameworklerinden React seçenekler arasında geliyor. Microsoft’un arkasında durduğu Knockout’da seçenekler arasında bulunuyor. İhtiyaca göre birisini veya daha sonradan dahil ederek Vue, Angular da kullanabilirsiniz. Bu aşama ilerleyen yazılarımızda yer alacaktır diye tahmin ediyorum. Kurulumu aşağıdaki gibi tamamlayınız. Kurulum dosyalarının toplam boyutu 300mb kadar.Boyut sizi aldandırmasın, çekilen klasör sayısı 4.000 kadar bu nedenle işlem biraz sürüyor. Bağlantı ve bilgisayarınızın hızınıza göre tahminde bulunarak bir kahve molası verip kurulumun tamamlanmasını geçebilirsiniz.


Kurulum esnasında önerilen seçeneklerden “Do you want to allow the tenant admin the choice of being able to deploy the solution to all sites immediately without running any feature deployment or adding apps in sites? (y/N)” seçeneği 8 Ağustos 2017 güncellemesinden sonra ortaya çıktı.

Bu seçenek aslında SpFx’e çok kıymetli bir yetenek katıyor. Geliştirdiğiniz WebPartlar tüm Tenantlar veya Site Collectionları içerisinde global bir şekilde eklenebiliyor. Bunun anlamı, geliştirip Deploy ettiğiniz bir WebPart tüm Tenantlar içerisinde hiçbir ikinci adımı takip etmeden görüntülenebilir ve kullanılabilir. Eğer n+1 Collection için WebPart geliştirmesi yapıyorsanız bu sizi ciddi bir efordan kurtaracaktır. Aslında SpFx ile yapılmak istenen şeylerden birisi geliştirme süreçleri içerisinde önemli bir rol alan Continous integreation’u olabildiğince Framework’un yetenekleri arasına katmaktır.

Kurulumun tamamlandığını varsayarak “gulp serve” komutunu çalıştırarak ilk arayüzle tanışabiliriz.


SpFx sayesinde Server-side geliştirmenin yanı sıra çok hızlı bir şekilde uygulamanızı çalıştırabilirsiniz. Bir WebPart üzerinde değişiklik yaptıktan sonra sahip olduğunuz OnPremise üzerinde IIS’I restart etmeniz, Pool kullanıcısına Reload işleminizi yapmanız gerekir. Online tarafta bunların hepsi “gulp serve” komutundan CTRL+C komutuyla çıktıktan sonra tekrar gulp serve komutu verilerek saniyeler içerisinde gerçekleştirilebilir.

Varolan WebPart’ı online üzerine tam anlamıyla deploy etmeden aşağıdaki url’den çok kolay bir şekilde demo olarak aynı Cloud’da çalışıyormuş gibi testinizi yapabilirsiniz.


Url formatı : https://

.sharepoint.com/sites//_layouts/15/workbench.aspx

İlgili kaynak koda PeakUp Github hesabından ulaşabilirsiniz.