Azure Function ile Rest API

Merhaba, Serverless serisinin bu bölümünde Http Trigger ile Azure Functions kullanarak bir Rest API oluşturacağız. Örneğimizde database olarak birçok ekibin aşına olduğu SQL Server kullanacağız. Bunu yaparken Serverless bir SQL Server Database oluşturacağız. Örnek uygulama ile Serverless teknolojilerini kullanarak ne kadar kolay ve hızlı bir şekilde API geliştirebileceğimizi beraber göreceğiz.

Örnek senaryomuza geçmeden önce Serverless ve Azure Functions ve Rest Api nedir kısaca inceleyelim.

Serverless Nedir?

Serverless, uygulamaların Bulut sağlayıcılar tarafından barındırıldığı ve geliştiricilerin sunucu, yazılım ve donanım yönetimi ihtiyacını ortadan kaldıran bir yapıdır.

Detaylı bilgi için makaleyi inceleyebilirsiniz.

Azure Functions Nedir?

Azure Functions, küçük kod parçalarını kolayca çalıştırmamızı sağlayan, uygulama geliştirmeyi hızlandırmak ve kolaylaştırmak için oluşturulmuş ve altyapı ihtiyaçlarının tamamen Azure tarafından yönetildiği serverless bir yaklaşımdır.

Detaylı bilgi için makaleyi inceleyebilirsiniz.

Rest API Nedir?

REST(Representational State Transfer) : Client/Server arasındaki haberleşmeyi sağlayan, HTTP protokolü kullanan bir mimaridir. Rest mimarisinde Json, Xml ve Text gibi formatlarda veri transferi sağlanabilir.REST mimarisi ile uyumlu olan servislere RESTful servisler denmektedir.

Daha fazla bilgi için wikipedia linkini inceleyebilirsiniz.

Rest Api bir veri kaynağının en uç kısmı olarak düşünebiliriz. Verilerin ulaşılmasını, güncellenmesini ve silinmesini sağlar.

Örnek Uygulama Senaryosu

Bizden üç farklı özel ürün için Landing Page’ler oluşturmamızı ve bu Landing Page’lerde müşteri taleplerini toplamak için birer Talep formu eklememiz istensin.

Formlara girilen dataların database’e kaydedilmesi ve bu taleplerin bir admin sayfasında listelenmesi istemiş olsun. (Admin sayfasına bu örnekte girmeyeceğiz)

Talep formlarının oluşturulması, güncellenmesi, silinmesini ve görüntülenmesi için Http Trigger , Azure Functions ve Azure Sql Db kullanarak adım adım uygulamamızı geliştireceğiz.

Uygulamayı geliştirirken aşağıdaki teknolojileri kullanacağız;

  • Visual Studio 2019 ve .Net Core 3.1
  • C#
  • Azure Functions
  • Azure SQL Server Database
  • Entity Framework

Yukarıdaki tabloyu kısaca özetleyecek olursak Landing Page sayfalarından Azure functions da oluşturduğumuz Rest API’a istekler gelerek talepler SQL Database’e yazılacak.

Azure Portal’da (Resource) Kaynakların oluşturulması

Projemizde kullanmak üzere Resource Group, Azure Functions App, Storage Account ve Azure Sql Database’e ihtiyacımız var. Şimdi sırasıyla bunları oluşturalım.

Resource Group oluşturulması

Azure Portal’a giriş yapıyoruz (https://portal.azure.com) ve arama çoğundan “Resource Group” yazarak açılan ekranda “Create” diyoruz.

Resource Group” oluşturma ekranında Resource Group için “AzureFunctionsRestApi” ve Region için “West Europe” seçiyoruz ve Create diyerek Resource Group’umuzu oluşturuyoruz.

Daha önceki örneklerde hatırlarsanız “West Europe” bölgesini seçmiştik. Çünkü Türkiye’ye en yakın bölge burası. Eğer farklı bir region seçerseniz gecikmeler ve yavaşlıklar söz konusu olabilir.

Varolan ve yeni açılacak olan bölgeleri görmek için alttaki linki inceleyebilirsiniz.

Azure Function App oluşturma

Arama çubuğuna “Function App” yazıp“Add” diyerek yeni bir Function App projesi oluşturalım. Function App Name için “CustomerRequestTracking” diyelim ve diğer bilgileri alttaki gibi dolduralım.

Bir sonraki hosting adımında “azurefuncrestapisa” adında bir StorageAccount oluşturalım. Operation System için “Windows” ve Plan için “consumption” planı seçerek devam ediyoruz.

Bir sonraki monitoring adımında Application insights “enable” işaretleyerek uygulamamızın monitör edilmesini sağlıyoruz.

Function app create dediğimizde ayarlarda girdiğimiz Resource’ların deployment işlemi hakkında bir sayfa ile karşılaşacağız. Deployment tamamlandığında resource’a erişim için bir link görünecek.

Function App’imizi oluştururken Azure Functions’ın ihtiyacı olan Storage Account’u ve monitoring yapabilmek içinde Application Insights Resource’unu oluşturmuş olduk.

Azure SQL Database Oluşturma

Şimdi sıra Azure Sql Database’i oluşturmaya. Azure Portalda arama çubuğuna “Azure SQL” yazarak çıkan ekranda “Create” diyelim. Bizi üç farklı plan karşılayacak.

Konumuz Serverless olduğu için Serverless sql database’i seçiyoruz ve “Create” diyoruz.

Sql Database oluşturma ekranında Database adını “customerrequesttrackingdb” olarak ekledim. Diğer gerekli bilgileri de girerek “Create” diyoruz.

Configure Database linkine tıkladığımızda Dabase’imizi nasıl kullanacağımız ile alakalı seçimler karşılayacaktır. Serverless katmanını seçiyoruz. Bu sayede kullanılan kaynakların sanal çekirdeklere göre otomatik olarak ölçeklenmesi sağlanacaktır.

Azure Sql Database servisimiz oluştuktan sonra “Settings” altında “Configure” sekmesinden dilerseniz farklı bir değişiklik yapabilirsiniz.

Bir sonraki adımda ise Firewall Rule’ları tanımlamamız gerekiyor. Azure Sql Database oluşturduğumuzda hangi IP’lerin bağlanacağı ve Azure Servislerinden ve Resource’lardan sql server’a bağlanılabileceğini tanımlamamız gerekmektedir. Aksi halde sql server’a erişim problemi yaşayabiliriz.

Firewall Settings’den “Allow Azure Services…” için “Evet” diyerek Azure kaynaklarından sql server’a erişimi aktif hale getiriyoruz. Local’den test edebilmek için ise “Add Client IP” diyerek firewall rule’lara IP adresimizi eklememiz gerekiyor. Save diyerek ekrandan çıkıyoruz.

Firewall tanımlamasınıda yaptığımıza göre son olarak Tablo’muzu yaratarak uygulamamızı geliştirmeye başlayabiliriz. (Ef code first migration yerine QueryEditor’ü inceleyebilmek için bu yöntemi tercih ettim).

Sql Database’in içerisinde Preview olan Query Editör’e tıklıyoruz. Buradan basitçe bir sql tablosu oluşturacağız. Sql Create Table scripti ile Run diyerek tablomuzu oluşturuyoruz.

CREATE TABLE [dbo].[RequestForms]([CreatedDate] [datetime] NOT NULL,[LandingPage] [nvarchar](256) NOT NULL,[NameSurname] [nvarchar](64) NOT NULL,[EMail] [nvarchar](64) NOT NULL,[PhoneNumber] [nvarchar](16) NULL,[Description] [ntext] NULL)

Gerekli olan kaynakları ve veritabanımızı oluşturduğumuza göre artık uygulamamızı oluşturmaya geçebiliriz.

Azure Function Projesi Oluşturma

AzureFunctionsRestAPI” isminde bir solution dosyası oluşturalım ve “Add New Project” diyerek “Azure Functions” projesi ekleyelim.

Proje ismi olarak “CustomerRequestTracking.Functions” diyerek Create diyoruz ve bir sonraki ekranda trigger’ları sonradan eklemek için “Empty” seçerek devam editoruz. Her zamanki gibi local ortamda çalışacağımız için Storage Account’u emulator seçmeyi unutmayın.

Projemizi oluşturduktan sonra kullanmak üzere dört adet klasör oluşturdum. Bunlar Data, Functions, Service ve Model. Projemizin son hali aşağıdaki gibi görünüyor.

Öncelikle Modelimizi oluşturalım. RequestForm adında bir sınıf oluşturuyorum.

public class RequestForm{public Guid Id { get; set; } =  Guid.NewGuid();public DateTime CreatedDate { get; set; }public string LandingPage { get; set; }public string NameSurname { get; set; }public string EMail { get; set; }public string PhoneNumber { get; set; }public string Description { get; set; }}

Entity Framework Core

Projeye Entity Framework eklemek için Nuget Package Manager’ı açıp alttaki iki kütüphaneyi projemize ekleyelim.

  • Microsoft.EntityFrameworkCore
  • Microsoft.EntityFrameworkCore.SqlServer

CsProj dosyamızı incelersek PackageReferans olarak EntityFrameworkCore paketlerini göreceğiz.

Data klasörü altında DbContext’den türeyen DataContext adında bir sınıf oluşturalım.

Entity Framework DbContext sınıfı veritabanı üzerinde işlemlerin yapıldığı sınıftır.

Gerekli ayarlamaları yaparak devam ediyoruz.

SqlDatabase’imize bağlanmak için local.settings.json dosyamızda “SqlServerConnection” adında bir variable oluşturalım. Daha sonra Value kısmına Azure Sql Database’imizin ConnectionString bilgisini tanımlayalım.

Şimdi CRUD operasyonlarını yapacağımız Service katmanını oluşturalım. IRequestFormService isminde bir Interface ekleyelim.

RequestFormService isminde bir sınıf oluşturalım ve interface’den türetelim.

Servislerimizi register edebilmek için Startup dosyasımızı oluşturmamız gerekiyor. Hatırlarsanız Azure Functions projemizde default olarak startup dosyası gelmiyordu. Alttaki paketi NuGet Package Manager’dan ekleyerek startup dosyamızı oluşturmalıyız.

Install-Package Microsoft.Azure.Functions.Extensions

Azure Functions’da Dependency Injection (DI) kullanımı hakkında daha fazla bilgi için yazıyı inceleyebilirsiniz.

Microsoft.Azure.Functions.Extensions” paketini kurdukdan sonra Startup dosyamızı yapılandırabiliriz. Oluşturduğumuz Startup sınıfını “FunctionsStartup” abstract sınıfından implemente ediyoruz. Configure methodu içerisinde bağımlılıklarımızı ve DbContext tanımlamız ile connection cümlesini ekliyoruz.

Artık CRUD işlemlerini yapacağımız Function’ları oluşturabiliriz.

Functions klasörü içerisinde “Add New Functions” diyoruz. API oluşturacağımız için tüm Function’lar “HttpTrigger” olarak çalışacak.

Ayrıca Authorization Level olarak “Function” seçeceğiniz.

Azure Functions nedir ve nasıl kullanılır konularını anlattığım yazıma alttan ulaşabilirsiniz.

Aşağıda oluşturduğumuz HttpTrigger function’ı görüyoruz. İşaretli alanları sırası ile inceleyelim.

  1. Azure Function sınıfı static olarak gelmektedir. Constructer’a DI tanımımızı yapabilmek için bu static özelliğini silmemiz gerekiyor.
  2. Azure Functions oluştururken “AuthorizationLevel.Function”’ı seçtik. Bu sayede Azure Function’ımıza dışarıdan anonim erişime kapattık sadece Function App’den oluşturduğumuz Default Key ile erişim sağlanacaktır.

3. Function için Http yanıt methodunu tanımlıyoruz. Boş bırakılırsa hepsini destekleyecektir.

4. Function’ın yanıt vereceği URL için route tanımlaması yapılan kısım.

Şimdi sırası ile tüm CRUD işlemleri için fonksiyonlarımızı oluşturacağız. Kullanacak olduğumuz fonksiyonları HttpTrigger olarak oluşturalım.

CreateRequestForm fonksiyonunu inceleyecek olursak öncelikle static tanımını silerek Constructor’da DI tanımını ekliyoruz. HttpMethod olarak “post” setleyip Route olarak “create” ismini veriyoruz. Body kısmında HttpRequest işleminde gönderilen veriyi alıp Create işlemini tamamlıyoruz ve geriye log mesajında kullandığımız mesajı dönüyoruz.

Benzer işlemleri diğer fonksiyonlar içinde yapacağız şimdi uygulamamızı çalıştırıp test edelim.

Uygulamamızı çalıştırınca alttaki gibi hata ile karşılaştım. “Could not load file or assembly ‘Microsoft.Extensions.DependencyInjection.Abstractions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60’. Sistem belirtilen dosyayi bulamiyor.” Bu hatanın sebebi versiyon çakışmasından dolayı.

Çözüm için EntityFrameworkCode kütüphanesinin versiyonunu düşererek hatayı aşabiliriz.

5.0.2 versiyonunu 3.1.9 versiyonuna çekiyorum.

Projeyi tekrar çalıştırdığımızda debug console’da oluşturduğumuz functionları görüyoruz.

Şimdi test etme zamanı.

Test’e başlamadan önce IP Adresimin değişme ihtimaline karşı sql Database Firewall ayarlarında IP adresimi kontrol edip ekliyorum.

Ayrıca eğer local.settings.json dosyasını hala yapılandırmadıysanız Connection String’lere ulaşmak için;

  1. Azure Portal > Storage Account > Access Keys > Connection String.
  2. Azure Portal > Sql Database > Connection String
local.settings.json file

Tüm bilgileri değiştirdiğimize göre şimdi Postman ile API’a istekte bulunabiliriz.

Create Request Form functionına “http://localhost:7071/api/create” ile Body’deki örnek bilgilerle Post isteği gönderelim.

Sonuç olarak log için hazırladığmız mesaj başarılı bir şekilde döndü. Console Loglarında da işlemin başarışı bir şekilde tanımlandığını gördük.

Şimdi Azure Sql Database’e gidip Query Editor’den kayıt işlemini inceleyelim. Gördüğünüz gibi kayıt işlemi başarılı bir şekilde tamamlandı.

Diğer tüm fonksiyonları sırası ile denediğimde işlemlerin başarılı bir şekilde tamamlandığını gördüm.

Uygulamanın Azure’a Publish edilmesi

Visual Studio’da projede sağ tıklayıp Publish diyoruz. Açılan ekranda sırası ile;

Azure > Azure Function App (Windows) > CustomerRequestTracking (Consumption) seçerek finish diyoruz.

Manage Azure App Settings’e tıklayarak AppSettings tanımlamalarımız için sunucu ve local’i eşitliyoruz.

Gerekli işlemleri tamamlayınca publish diyerek uygulamamızı Azure’ a gönderiyoruz. Publish işlemi başarılı bir şekilde sonuçlandığında Function App’de oluşturduğumuz tüm functionları görüyor olacağız.

Şimdi Postman ile Azure’a deploy ettiğimiz uygulamayı test edelim. Test edebilmemiz için Function App’e gidip öncelikle App Keys altındaki default key’i almamız gerekmekte. Hatırlarsanız Auth. Level için “Function” tanımlamıştık ve ananim ulaşımlar için fonksiyonlarımızı kapattık.

Fonksiyonlara ulaşırken alttaki patternde request’ler göndermeliyiz.

https://{FunctionAppName}.azurewebsites.net/api/{Route}/?Code={DefaultKey}

Postman ile Create ve List isteğinde bulunduğumuzda aşağıdaki gibi başarılı olarak sonuç almış olduk.

Sonuç

Azure Functions kullanarak örnek senaryo üzerinden nasıl Rest API oluşturacağımızı adım adım inceledik. Gördüğünüz gibi kısa sürede çok az kodlama yaparak ve altyapı ile hiç ilgilenmeden hızlıca uygulamamızı geliştirdik.

Azure Functions App ve Azure Sql Database’i “Consuption” plan ile oluşturduk. Bu kullandığımız kadar ödeyeceğiz anlamındadır. Consuptio planda en büyük sorunlardan bir tanesi Cold Start problemi. Burada daha önce bahsetmiştim.

Fakat kontrolümüz dışında API çağrısı olursa ne olacak? Birinin Landing Page’lerden milyonlarca spam attığını düşünün. Yüklü bir fatura ile karşılaşmak bize yaptığımız tasarımı ve hayatı tekrar sorgulatacaktır.

Serverless dünyası her ne kadar daha az maliyetlerle uygulama geliştirmemizi sağlasada hataya açık değil. Oluşturduğumuz tasarımda güvenlik, versiyonlama, dökümantasyon gibi ihtiyaçları karşılamak için client app ile Azure functions arasına bir Api Management eklememiz daha doğru olur. Bu sayede öngörülemeyen durumları engellemiş ve daha güvenli bir şekilde API yönetimi sağlamış oluruz.

Bir sonraki makalede görüşmek üzere…

Sorularınız için lütfen yorum yapmaktan ve bana ulaşmaktan çekinmeyin.

Twitter: https://twitter.com/ufukaytas
Linkedin: https://www.linkedin.com/in/ufukaytass/
Github: https://github.com/ufukaytas/

--

--

Ufuk Aytaş
Devops Türkiye☁️ 🐧 🐳 ☸️

Software Architect & Developer @CorendonDutchAirlines, Husband, Dad, Fishing, Coffee addict :) #Serverless #Cloud, #Azure, #Dotnet