Derinlemesine yazılım eğitimleri için kanalımı takip edebilirsiniz...

Aspire 13.2 İle AI Agent’ları Ölçeklendirme: Parallel Development İçin Gelen İzolasyon Katmanı

Merhaba,

Aspire, yapay zekâ destekli geliştirme dünyasında gerçekten oyunun kurallarını değiştiren bir yaklaşım sunmaktadır. Düşünsenize, tek bir Program.cs dosyasıyla, içerisinde backend API’leri, python servisleri, frontend uygulamaları, veritabanları yahut message queue’ları olan, tamamen orkestre edilmiş ve test edilmeye hazır, baştan sona distributed olan bir sistemi ayağa kaldırabilmekteyiz. Bu özellik, agent’lara ciddi bir güç kazandırıyor olsa da iş bununla da bitmemektedir. Aspire’ın MCP Server altyapısı sayesinde agent’lar sistemdeki kaynakların durumunu kod üzerinden sorgulayabilmekte, log’lara erişebilmekte ve sorunları doğrudan analiz edip çözebilmektedir. Yani artık AI agent’lar sadece tekil bileşenlerle değil, tüm sistemle etkileşime girerek çalışabilmektedir. Bu da geliştirme süreçlerini ciddi anlamda sadeleştirmekle birlikte hızlandırmaktadır.

Ancak iş ölçeklemeye geldiğinde Aspire 13.2 sürümünden önce ‘port çakışmaları’ gibi kritik bir sorun söz konusuydu. Aynı anda birden fazla worktree üzerinden Aspire AppHost çalıştırmak istendiğinde, tüm instance’lar aynı port’ları kullanmaya çalıştığından, paralel çalışan AI agent’larla geliştirme yapmak neredeyse imkansız hale gelmekteydi.

Bu sorunu çözmek için bizler manuel yöntemlerin dışında her worktree’ye özel port ataması yapan bir izolasyon katmanı geliştirmeye çalışıyor, script’ler ve akıllı bir MCP proxy kullanarak her instance’ın birbirinden tamamen bağımsız çalışmasını sağlamaya çalışıyorduk.

Aspire 13.2 ile birlikte bu problem kökünden çözülmekte ve bir AppHost‘un birden fazla instance’ını paralel olarak rahatlıkla çalıştırmamıza olanak tanıyan izolasyon modu gelmektedir. Tabi bizler, bu port izolasyonu seviyesine geçmeden önce Aspire’ın yapay zekâ agent’ları için neden mükemmel olduğunun istişaresiyle konuya giriş yapacak ardından bu izolasyon modunu sizlere tanıtıyor olacağız…

Aspire Yapay Zekâ Agent’ları İçin Neden Mükemmeldir?

Aspire, AI agent’larıyla geliştirme yaparken klasik yaklaşımların ötesine geçmemizi sağlar. Bunun temel nedeni, agent’lara sadece kod yazdırmakla kalmayıp, tüm sistemi yönetebilecek bir yetenek kazandırmasıdır.

En kritik avantajlarından biri, yukarıdaki satırlarda bahsedildiği üzere tek bir Program.cs üzerinden komple bir distributed sistemin ayağa kaldırılabilmesidir. Tüm sistemin merkezi bir noktadan orkestre edilmesi, agent’lar açısından parçalı bir yapı yerine bütüncül bir sistem üzerinden çalışma imkanı sağlamaktadır. Bu da agent geliştirme açısından büyük avantaj sağlamaktadır.

Bir diğer önemli nokta ise Aspire’ın MCP Server yetenekleridir. Bu yapı sayesinde AI agent’lar;

  • Sistem kaynaklarının durumunu programatik olarak sorgulayabilmektedir
  • Log’lara erişebilmektedir
  • Hataları analiz edip çözüm üretebilmektedir

Yani agent artık sadece salt olarak kod yazan bir araç değil; sistemi gözlemleyen, anlayan ve gerektiğinde müdahale eden aktif bir operatöre dönüşmektedir. Ki bu yaklaşımın en büyük etkisi geliştirme süreçlerinde görülmektedir. Normalde saatler sürebilecek kurulum, entegrasyon ve test süreçleri ciddi ölçüde sadeleşmektedir. Agent tarafından tüm sistem kontrol edilebileceği için geliştirme döngüsü hızlanmakta ve insan müdahalesi minimuma inmektedir.

Özetle Aspire;

  • Agent’lara sistem kurma ve yönetme yeteneği kazandırmaktadır
  • Tüm bileşenleri merkezi ve orkestre bir yapıda sunmaktadır
  • AI agent’larının sistemle doğrudan etkileşim kurmasını sağlamaktadır
  • Geliştirme süreçlerini hızlandırmakta ve sadeleştirmektedir

Örnek vermemiz gerekirse bir yapay zekâ agent’ı aşağıdaki gibi birkaç satır kodla eksiksiz bir distributed uygulamayı rahatlıkla ayağa kaldırabilmektedir:

var builder = DistributedApplication.CreateBuilder(args);

var redisCache = builder.AddRedis("redisCache");
var postgreDB = builder.AddPostgres("postgreDB")
                       .WithImage("postgres", "18")
                       .AddDatabase("mydb");

var rabbitMQMessaging = builder.AddRabbitMQ("rabbitMQMessaging")
                               .WithImage("rabbitmq", "latest");

var myAPI = builder.AddProject<Projects.MyAPI>("myAPI")
                   .WithReference(redisCache)
                   .WithReference(postgreDB)
                   .WithReference(rabbitMQMessaging)
                   .WithExternalHttpEndpoints();

var aiService = builder.AddPythonApp("aiService", "../ai-service", "main.py")
                       .WithReference(postgreDB)
                       .WithReference(rabbitMQMessaging)
                       .WithExternalHttpEndpoints();

var myFrontend = builder.AddJavaScriptApp("myFrontend", "../MyFrontend")
                   .WithRunScript("start")
                   .WithReference(myAPI)
                   .WithReference(aiService.GetEndpoint("http"))
                   .WithExternalHttpEndpoints();

builder.Build().Run();

Bu çalışmaya göz atarsak eğer tek kalemde aşağıdaki işlemleri başlattığını söyleyebiliriz;

  • Redis cache ayağa kaldırılmakta,
  • PostgreSQL ayağa kaldırılmakta, veritabanı oluşturulmakta,
  • RabbitMQ message broker ayağa kaldırılmakta,
  • Asp.NET Core API ayağa kaldırılmakta,
  • Python yapay zeka servisi ayağa kaldırılmakta,
  • JavaScript frontend uygulaması ayağa kaldırılmakta
  • ve tüm bu süreçte mevcut bileşenler arasındaki tüm ağ bağlantıları otomatik olarak yapılandırılmaktadır.

Evet… Bir AI agent bu yapılandırmayı rahatlıkla değiştirebilir, çalıştırabilir, tüm sistemi tek elden test edebilir ve yineleyebilir. Ve bunların hepsini otonom olarak gerçekleştirebilir…

Ölçeklendirme Süreçlerinde Gelen İzolasyon Modu Nedir?

Branch İle Worktree Farkı Nedir?
Branch, mantıksaldır. Sadece bir pointer (işaretçi) olarak kullanılmakta ve bir commit’i göstermektedir. Yani dosya falan yoktur, sadece referans işlemi görür.

Worktree ise gerçek klasördür. İçinde dosyalar olan, kodun fiziksel halidir.

Branch, bir kitapta ayraç koyulan sayfadır. Worktree ise kitabın fiziksel kopyasıdır.

Şimdi varsayalım ki, bu Aspire projesini birden fazla worktree üzerinden ayağa kaldırarak ölçeklendirmeye çalışıyoruz. Tabi bunun için aşağıdaki gibi öncelikle iki branch oluşturuyor, ardından bu branch’ler üzerinden de worktree’leri oluşturuyoruz…

۝ git branch feature1
۝ git branch feature2
۝ git worktree add ../proj-feature1 feature1
۝ git worktree add ../proj-feature2 feature2

 
Bu vaziyette beklenen şudur ki, her iki worktree üzerinden dotnet run komutu çalıştırıldığı taktirde port çakışmalarıyla karşılaşılsın. Öyle değil mi?Aspire 13.2 İle AI Agent'ları Ölçeklendirme: Parallel Development İçin Gelen İzolasyon KatmanıAma görselden görüldüğü üzere herhangi bir port çakışması söz konusu değildir! Bunun nedeni, Aspire 13.2 ile dashboard portunun artık process bazlı bir socket/mutex mekanizmasıyla yönetilmesidir. Bu mekanizma sayesinde ikinci instance aynı porta bağlanmaya çalıştığı taktirde, her instance’ın kendi kaynaklarını (Redis, PosgresSQL vs.) ayrı ayrı register etmesi kaydıyla, çakışma yerine aynı dashboard process’ini paylaşmaktadır. Haliyle bu şekilde birden fazla instance’ı ayağa kaldırsak dahi hepsi aynı kaynakları kullanacaktır. Bu da dashboard’a girildiğinde tüm kaynakların tek ekranda görülmesini sağlayacaktır.Aspire 13.2 İle AI Agent'ları Ölçeklendirme: Parallel Development İçin Gelen İzolasyon KatmanıTabi burada bizler için önem arz eden bir durum söz konusudur. O da servislerin ölçeklendirilmesi, yani izolasyonudur. Gelin bunu inceleyerek devam edelim…

Servis İzolasyonu Problemi

Şu anki mevcut yapıda Aspire, her servise random port atamaktadır. Ancak her worktree instance’ı aynı port’taki kaynakları kullandığı için ortak Redis’i, PostgreSQL’i ve RabbitMQ’yu kullanmaktadır. Halbuki olması gereken bunların birbirlerinden worktree seviyesinde izole edilmesidir. Aksi taktirde bir kaynağa feature1‘de yapılan müdahale feature2‘yi de anında etkileyecektir.

feature1 worktree → “redisCache” container’ı başlatıyor
feature2 worktree → aynı isimde container zaten var olduğu için onu reuse ediyor

Bu problemi çözmek ve kaynaklar arasında worktree bazlı izolasyonu sağlamak için aşağıdaki gibi küçük bir yardımcı sınıf geliştirmemiz işimizi görecektir:

    public static class GitFolderResolver
    {
        public static string GetGitFolderName(string? workingDirectory = null)
        {
            try
            {
                var directory = workingDirectory ?? Directory.GetCurrentDirectory();
                var gitPath = FindGitPath(directory);

                if (gitPath is null)
                    return "default";

                if (Directory.Exists(gitPath))
                {
                    var repoDirectory = Path.GetDirectoryName(gitPath);
                    return Path.GetFileName(repoDirectory).Replace(".", "") ?? "default";
                }

                if (File.Exists(gitPath))
                {
                    var gitFileContent = File.ReadAllText(gitPath);

                    if (gitFileContent.StartsWith("gitdir:"))
                    {
                        var gitDirPath = gitFileContent.Substring("gitdir:".Length).Trim();
                        var worktreeSegments = gitDirPath.Split(new[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries);

                        for (int i = 0; i < worktreeSegments.Length - 1; i++)
                            if (worktreeSegments[i] == "worktrees")
                                return worktreeSegments[i + 1];

                        return Path.GetFileName(directory).Replace(".", "") ?? "default";
                    }
                }

                return "default";
            }
            catch
            {
                return "default";
            }

            static string? FindGitPath(string directory)
            {
                var currentDirectory = directory;

                while (!string.IsNullOrEmpty(currentDirectory))
                {
                    var gitPath = Path.Combine(currentDirectory, ".git");

                    if (Directory.Exists(gitPath) || File.Exists(gitPath))
                        return gitPath;

                    var parentDirectory = Path.GetDirectoryName(currentDirectory);
                    if (parentDirectory == currentDirectory)
                        break;

                    currentDirectory = parentDirectory;
                }

                return null;
            }
        }
    }

Yukarıdaki kodda yapılan işlemleri anlayabilmek için şunun bilinmesi gerekmektedir: normal bir Git repo’da .git bir klasörken, worktree’de ise .git bir dosyadır. Haliyle hangi worktree’de olduğumuzu bu dosyayı okuyarak çıkartıyoruz.

Ve ardından AppHost‘da aşağıdaki gibi bu sınıfı kullanarak worktree bazlı container isimlerini ayarlayalım:

.
.
.
var worktreeName = GitFolderResolver.GetGitFolderName();

var redisCache = builder.AddRedis($"redisCache-{worktreeName}");
var postgreDB = builder.AddPostgres($"postgreDB-{worktreeName}")
                       .WithImage("postgres", "18")
                       .AddDatabase("mydb");

var rabbitMQMessaging = builder.AddRabbitMQ($"rabbitMQMessaging-{worktreeName}")
                               .WithImage("rabbitmq", "latest");
.
.
.

Bu işlem neticesinde Aspire’ı ölçeklendirdiğimizde aşağıdaki görselde olduğu gibi her bir worktree’ye karşılık bir container kaynağının üretildiğini göreceksiniz:Aspire 13.2 İle AI Agent'ları Ölçeklendirme: Parallel Development İçin Gelen İzolasyon KatmanıBöylece servisler arası izolasyon başarıyla sağlanmış olacaktır👏

Nihai olarak;

Aspire, ölçeklendirme süreçlerine dair gelmiş olan bu izolasyon katmanı ile AI agent çalışmalarını sıralı çalışan bir yapıdan gerçek anlamda paralel bir yapıya dönüştürmüş bulunmaktadır. Port çakışmaları sorununu kökten çözen bu yenilik, Git worktree’leri üzerinde çalışan birden fazla yapay zeka agent’ının aynı anda tamamen bağımsız ve birbirini engellemeden distributed sistemleri ayağa kaldırmasını, uçtan uca test etmesini ve sistem genelindeki kaynak durumlarını, logları ve izleme verilerini programatik olarak sorgulayarak otonom bir şekilde hata ayıklamasını mümkün kılmaktadır. Böylece tek bir Program.cs dosyasıyla Redis, PostgreSQL, RabbitMQ, API, Python AI Service ve JavaScript Frontend’i içeren karmaşık uygulama yığınlarını saniyeler içerisinde orkastre edebilen Aspire, artık yalnızca tek bir agent için değil; aynı anda dört, beş hatta daha fazla agent için de sorunsuz bir geliştirme altyapısı sunmakta, yapay zeka destekli yazılım üretimini gerçek anlamda endüstriyel ölçekte paralel iş akışlarına taşımış bulunmaktadır.

İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…

Örnek çalışmaya aşağıdaki GitHub reposundan erişebilirsiniz.
https://github.com/gncyyldz/Scaling.AI.Agents.With.Aspire.AppHost

Bu repository, ilgili konuya dair örnek çalışmanın kaynak kodlarını ve mimari yapısını içermektedir. Detaylar için GitHub üzerinden incelemede bulunabilirsiniz.


GitHub’da Görüntüle →

Bunlar da hoşunuza gidebilir...

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir