Queue-Centric İş Düzeni (Azure ile Real-World Cloud Apps Oluşturma)

tarafından Rick Anderson, Tom Dykstra

Fix It Project'i indirin veya E-kitabı indirin

Azure e-kitabıyla Gerçek Dünya Bulut Uygulamaları Oluşturma, Scott Guthrie tarafından geliştirilen bir sunuyu temel alır. Bulut için web uygulamalarını başarıyla geliştirmenize yardımcı olabilecek 13 desen ve uygulama açıklanmaktadır. E-kitap hakkında bilgi için ilk bölüme bakın.

Daha önce birden çok hizmet kullanmanın bir "bileşik" SLA ile sonuçlanabileceğini görmüştük. Burada uygulamanın etkili SLA'sı tek tek SLA'ların ürünüdür . Örneğin, Düzelt uygulaması Web Siteleri, Depolama ve SQL Veritabanı kullanır. Bu hizmetlerden herhangi biri başarısız olursa uygulama kullanıcıya bir hata döndürür.

Önbelleğe alma, salt okunur içerik için geçici hataları işlemenin iyi bir yoludur. Peki uygulamanızın çalışması gerekiyorsa ne olacak? Örneğin, kullanıcı yeni bir Düzelt görevi gönderdiğinde, uygulama görevi yalnızca önbelleğe koyamaz. Uygulamanın işlenebilmesi için Düzelt görevini kalıcı bir veri deposuna yazması gerekir.

Kuyruk merkezli iş düzeni burada devreye girer. Bu düzen, bir web katmanı ile arka uç hizmeti arasında gevşek bağlantı sağlar.

Desen şu şekilde çalışır. Uygulama bir istek aldığında, bir iş öğesini kuyruğa yerleştirir ve yanıtı hemen döndürür. Ardından ayrı bir arka uç işlemi iş öğelerini kuyruktan çeker ve işi yapar.

Kuyruk merkezli iş düzeni şunlar için kullanışlıdır:

  • Zaman alan çalışma (yüksek gecikme süresi).
  • Her zaman kullanılamayabilecek bir dış hizmet gerektiren çalışma.
  • Yoğun kaynak kullanan (yüksek CPU) çalışma.
  • Hız dengelemeden yararlanabilecek çalışmalar (ani yük artışlarına tabidir).

Azaltılmış Gecikme Süresi

Kuyruklar, zaman alan işleri yaparken yararlı olur. Bir görev son kullanıcıyı engellemek yerine birkaç saniye veya daha uzun sürüyorsa, iş öğesini kuyruğa alın. Kullanıcıya "Üzerinde çalışıyoruz" deyip arka planda görevi işlemek için bir kuyruk dinleyicisi kullanın.

Örneğin, çevrimiçi bir satıcıdan bir şey satın aldığınızda, web sitesi siparişinizi hemen onaylar. Ama bu eşyalarının teslim edilen bir kamyonda olduğu anlamına gelmez. Bir görevi kuyruğa koyarlar ve arka planda kredi denetimini yapar, öğelerinizi gönderime hazırlarlar vb.

Kısa gecikme süresine sahip senaryolar için toplam uçtan uca süre, görevi zaman uyumlu olarak yerine getirmekle karşılaştırıldığında kuyruk kullanılarak daha uzun olabilir. Ancak o zaman bile, diğer avantajlar bu dezavantajdan daha ağır basabilir.

Artan Güvenilirlik

Şu ana kadar incelediğimiz Düzelt'in sürümünde web ön ucu, SQL Veritabanı arka ucuyla sıkı bir şekilde birleştirilir. SQL veritabanı hizmeti kullanılamıyorsa, kullanıcı bir hata alır. Yeniden denemeler işe yaramazsa (yani, hata geçiciden daha fazlasıdır), yapabileceğiniz tek şey bir hata göstermek ve kullanıcıdan daha sonra yeniden denemesini istemektir.

SQL Veritabanı arka uç başarısız olduğunda web ön ucunun başarısız olduğunu gösteren diyagram

Kuyrukları kullanarak, kullanıcı Bir Düzelt görevi gönderdiğinde uygulama kuyruğa bir ileti yazar. İleti yükü, görevin JSON gösterimidir. İleti kuyruğa yazıldıktan hemen sonra uygulama geri döner ve kullanıcıya hemen bir başarı iletisi gösterir.

SQL veritabanı veya kuyruk dinleyicisi gibi arka uç hizmetlerinden herhangi biri çevrimdışı olursa, kullanıcılar yeni Düzelt görevlerini göndermeye devam edebilir. Arka uç hizmetleri yeniden kullanılabilir duruma gelene kadar iletiler kuyruğa alınacaktır. Bu noktada arka uç hizmetleri kapsamı yakalar.

SQL Veritabanı hatası olduğunda web ön ucunun çalışmaya devam ettiğini gösteren diyagram

Ayrıca artık ön ucun dayanıklılığı konusunda endişelenmeden daha fazla arka uç mantığı ekleyebilirsiniz. Örneğin, yeni bir Düzeltme Atandığında sahibine bir e-posta veya SMS iletisi göndermek isteyebilirsiniz. E-posta veya SMS hizmeti kullanılamaz duruma gelirse, diğer her şeyi işleyebilir ve ardından e-posta/SMS iletileri göndermek için ayrı bir kuyruğa bir ileti yerleştirebilirsiniz.

Daha önce etkili SLA'mız Depolama × SQL Veritabanı = %99,7 Web Apps ×. (Bkz . Hatalara Karşı Hayatta Kalmak için Tasarım.)

Uygulamayı kuyruk kullanacak şekilde değiştirdiğimizde, web ön ucu yalnızca %99,8 bileşik SLA için Web Apps ve Depolama'ya bağlıdır. (Kuyrukların Azure depolama hizmetinin bir parçası olduğunu, bu nedenle blob depolama ile aynı SLA'ya dahil olduklarını unutmayın.)

%99,8'den daha iyiye ihtiyacınız varsa, iki farklı bölgede iki kuyruk oluşturabilirsiniz. Birini birincil, diğerini ikincil olarak belirleyin. Uygulamanızda, birincil kuyruk kullanılamıyorsa ikincil kuyruğa yük devretme. İkisinin de aynı anda kullanılamama şansı çok azdır.

Hız Dengeleme ve Bağımsız Ölçeklendirme

Kuyruklar hız dengeleme veya yük dengeleme olarak adlandırılan bir şey için de kullanışlıdır.

Web uygulamaları genellikle trafikteki ani artışlara duyarlıdır. Artan web trafiğini işlemek üzere web sunucularını otomatik olarak eklemek için otomatik ölçeklendirmeyi kullanabilirsiniz, ancak otomatik ölçeklendirme yükteki ani ani artışları işlemek için yeterince hızlı tepki vermeyebilir. Web sunucuları bir kuyruğa ileti yazarak yapması gereken bazı işleri boşaltabiliyorsa, daha fazla trafiği işleyebilir. Arka uç hizmeti daha sonra kuyruktan iletileri okuyabilir ve işleyebilir. Gelen yük değiştikçe kuyruğun derinliği artar veya küçülür.

Zaman alan çalışmalarının büyük bir kısmı arka uç hizmetine yüklendiğinde, web katmanı trafikteki ani ani artışlara daha kolay yanıt verebilir. Ayrıca, belirli bir trafik miktarı daha az web sunucusu tarafından işlenebileceği için paradan tasarruf edebilirsiniz.

Web katmanını ve arka uç hizmetini bağımsız olarak ölçeklendirin. Örneğin, üç web sunucusuna ancak kuyruk iletilerini işleyen tek bir sunucuya ihtiyacınız olabilir. Veya arka planda yoğun işlem gücü kullanan bir görev çalıştırıyorsanız daha fazla arka uç sunucusuna ihtiyacınız olabilir.

Kuyruktaki görevleri işlerken Ölçek Katmanlarının bir gösterimini gösteren diyagram

Otomatik ölçeklendirme hem arka uç hizmetlerinde hem de web katmanında çalışır. Arka uç VM'lerinin CPU kullanımına bağlı olarak kuyruktaki görevleri işleyen VM'lerin ölçeğini artırabilir veya azaltabilirsiniz. Veya kuyruktaki öğe sayısını temel alarak otomatik ölçeklendirme yapabilirsiniz. Örneğin, otomatik ölçeklendirmeye kuyrukta en fazla 10 öğe tutmayı denemesini söyleyebilirsiniz. Kuyrukta 10'dan fazla öğe varsa, otomatik ölçeklendirme VM'ler ekler. Bu işlem tamamlandığında otomatik ölçeklendirme, ek VM'leri yok eder.

Düzelt Uygulamasına Kuyruk Ekleme

Kuyruk desenini uygulamak için Düzelt uygulamasında iki değişiklik yapmamız gerekir.

  • Kullanıcı yeni bir Düzelt görevi gönderdiğinde, görevi veritabanına yazmak yerine kuyruğa yerleştirin.
  • Kuyruktaki iletileri işleyen bir arka uç hizmeti oluşturun.

Kuyruk için Azure Kuyruk Depolama Hizmeti'ni kullanacağız. Bir diğer seçenek de Azure Service Bus kullanmaktır.

Hangi kuyruk hizmetinin kullanılacağına karar vermek için uygulamanızın kuyruktaki iletileri nasıl gönderip alması gerektiğini göz önünde bulundurun:

  • İşbirliği yapan üreticileriniz ve rakip tüketicileriniz varsa Azure Kuyruk Depolama Hizmeti'ne göz atabilirsiniz. "İşbirliği yapan üreticiler", birden çok işlemin kuyruğa ileti eklemesi anlamına gelir. "Rakip tüketiciler", birden çok işlemin iletileri işlemek için kuyruktan çektiği, ancak belirli bir iletinin yalnızca bir "tüketici" tarafından işlenebileceği anlamına gelir. Tek bir kuyrukta alabileceğinizden daha fazla aktarım hızına ihtiyacınız varsa ek kuyruklar ve/veya ek depolama hesapları kullanın.
  • Yayımlama/abone olma modeline ihtiyacınız varsa Azure Service Bus Kuyrukları kullanmayı göz önünde bulundurun.

Fix It uygulaması, işbirliği yapan üreticilere ve rakip tüketiciler modeline uygundur.

Dikkat edilmesi gereken bir diğer nokta da uygulama kullanılabilirliğidir. Kuyruk Depolama Hizmeti, blob depolama için kullanmakta olduğumuz hizmetin bir parçasıdır, bu nedenle kullanmanın SLA'mız üzerinde hiçbir etkisi yoktur. Azure Service Bus kendi SLA'sına sahip ayrı bir hizmettir. Service Bus Kuyruklarını kullanırsak ek bir SLA yüzdesini dikkate almak zorunda olurduk ve bileşik SLA'mız daha düşük olurdu. Bir kuyruk hizmeti seçerken, seçiminizin uygulama kullanılabilirliği üzerindeki etkisini anladığınızdan emin olun. Daha fazla bilgi için Kaynaklar bölümüne bakın.

Kuyruk İletileri Oluşturma

Kuyruğa Düzelt görevi koymak için web ön ucu aşağıdaki adımları gerçekleştirir:

  1. CloudQueueClient örneği oluşturun. Örnek CloudQueueClient , Kuyruk Hizmeti'ne yönelik istekleri yürütmek için kullanılır.
  2. Henüz yoksa kuyruğu oluşturun.
  3. Düzelt görevini seri hale getirme.
  4. İletiyi kuyruğa almak için CloudQueue.AddMessageAsync'i çağırın.

Bu işi yeni FixItQueueManager bir sınıfın oluşturucusunda ve SendMessageAsync yönteminde yapacağız.

public class FixItQueueManager : IFixItQueueManager
{
    private CloudQueueClient _queueClient;
    private IFixItTaskRepository _repository;

    private static readonly string fixitQueueName = "fixits";

    public FixItQueueManager(IFixItTaskRepository repository)
    {
        _repository = repository;
        CloudStorageAccount storageAccount = StorageUtils.StorageAccount;
        _queueClient = storageAccount.CreateCloudQueueClient();
    }

    // Puts a serialized fixit onto the queue.
    public async Task SendMessageAsync(FixItTask fixIt)
    {
        CloudQueue queue = _queueClient.GetQueueReference(fixitQueueName);
        await queue.CreateIfNotExistsAsync();

        var fixitJson = JsonConvert.SerializeObject(fixIt);
        CloudQueueMessage message = new CloudQueueMessage(fixitJson);

        await queue.AddMessageAsync(message);
    }

    // Processes any messages on the queue.
    public async Task ProcessMessagesAsync()
    {
        CloudQueue queue = _queueClient.GetQueueReference(fixitQueueName);
        await queue.CreateIfNotExistsAsync();

        while (true)
        {
            CloudQueueMessage message = await queue.GetMessageAsync();
            if (message == null)
            {
                break;
            }
            FixItTask fixit = JsonConvert.DeserializeObject<FixItTask>(message.AsString);
            await _repository.CreateAsync(fixit);
            await queue.DeleteMessageAsync(message);
        }
    }
}

Burada fixit'i JSON biçiminde seri hale getirmek için Json.NET kitaplığını kullanıyoruz. Tercih ettiğiniz serileştirme yaklaşımını kullanabilirsiniz. JSON, insan tarafından okunabilir olmanın avantajına sahipken XML'den daha az ayrıntıya sahiptir.

Üretim kalitesi kodu hata işleme mantığı ekler, veritabanı kullanılamaz hale gelirse duraklatır, kurtarmayı daha temiz işler, uygulama başlatma sırasında kuyruk oluşturur ve "zehir" iletilerini yönetir. (Zehir iletisi, herhangi bir nedenle işlenemeyen bir iletidir. Çalışan rolünün sürekli olarak bunları işlemeye, başarısız olmaya, yeniden denemeye, başarısız olmaya vb. çalışacağı sıraya zehirli iletilerin oturmasını istemezsiniz.)

Ön uç MVC uygulamasında yeni bir görev oluşturan kodu güncelleştirmemiz gerekir. Görevi depoya yerleştirmek yerine, yukarıda gösterilen yöntemini çağırın SendMessageAsync .

public async Task<ActionResult> Create(FixItTask fixittask, HttpPostedFileBase photo)
{
    if (ModelState.IsValid)
    {
        fixittask.CreatedBy = User.Identity.Name;
        fixittask.PhotoUrl = await photoService.UploadPhotoAsync(photo);
        //previous code:
        //await fixItRepository.CreateAsync(fixittask);
        //new code:
        await queueManager.SendMessageAsync(fixittask);
        return RedirectToAction("Success");
    }
    return View(fixittask);
}

Kuyruk İletilerini İşleme

Kuyruktaki iletileri işlemek için bir arka uç hizmeti oluşturacağız. Arka uç hizmeti, aşağıdaki adımları gerçekleştiren sonsuz bir döngü çalıştırır:

  1. Kuyruktan sonraki iletiyi alın.
  2. İletinin seri durumdan çıkararak Düzelt görevine geçin.
  3. Düzelt görevini veritabanına yazın.

Arka uç hizmetini barındırmak için çalışan rolü içeren bir Azure Bulut Hizmeti oluşturacağız. Çalışan rolü, arka uç işlemesi yapabilen bir veya daha fazla VM'den oluşur. Bu VM'lerde çalışan kod, kullanılabilir duruma geldikçe kuyruktan iletiler çeker. Her ileti için JSON yükünü seri durumdan çıkaracağız ve daha önce web katmanında kullandığımız depoyu kullanarak Bt Görevini Düzelt varlığının bir örneğini veritabanına yazacağız.

Aşağıdaki adımlarda, standart web projesi olan bir çözüme çalışan rolü projesinin nasıl ekleneceği gösterilmektedir. Bu adımlar indirebileceğiniz Düzelt projesinde zaten yapılmıştır.

İlk olarak Visual Studio çözümüne bir Bulut Hizmeti projesi ekleyin. Çözüme sağ tıklayın ve Ekle'yi ve ardından Yeni Proje'yi seçin. Sol bölmede Visual C# öğesini genişletin ve Bulut'a tıklayın.

.Net Framework'te yeni proje menüsü ekleme adımlarının ekran görüntüsü

Yeni Azure Bulut Hizmeti iletişim kutusunda, sol bölmedeki Visual C# düğümünü genişletin. Çalışan Rolü'ne tıklayın ve sağ ok simgesine tıklayın.

Aşağıdaki ekran görüntüsünde önceki görüntünün devamı ve Azure Bulut Hizmeti için sağlanan farklı seçimler gösterilir ve doğru görüntü vurgulanır.

(Bir web rolü de ekleyebileceğinize dikkat edin. Düzelt ön ucunu azure web sitesinde çalıştırmak yerine aynı Bulut Hizmetinde çalıştırabiliriz. Bunun, ön uç ve arka uç arasındaki bağlantıların eşgüdümlü olmasını kolaylaştırma konusunda bazı avantajları vardır. Ancak bu tanıtımı basit tutmak için ön ucu bir Azure App Service Web Uygulamasında tutuyoruz ve arka ucu yalnızca Bulut Hizmetinde çalıştırıyoruz.)

Çalışan rolüne varsayılan bir ad atanır. Adı değiştirmek için fareyi sağ bölmedeki çalışan rolünün üzerine getirin ve kalem simgesine tıklayın.

Farklı atamaların ve adların nasıl değiştirileceğini gösteren Çalışan Rolü Projesi'ni gösteren ekran görüntüsü.

İletişim kutusunu tamamlamak için Tamam'a tıklayın. Bu, Visual Studio çözümüne iki proje ekler.

  • yapılandırma bilgileri de dahil olmak üzere bulut hizmetini tanımlayan bir Azure projesi.
  • Çalışan rolünü tanımlayan bir çalışan rolü projesi.

Bir çalışan rolünü gösteren, rolü tanımlayan ve 'MyFixIt' proje çözümü seçeneklerinin listesini gösteren ekran görüntüsü.

Daha fazla bilgi için bkz . Visual Studio ile Azure Projesi oluşturma.

Çalışan rolünün içinde, daha önce gördüğümüz sınıfın ProcessMessageAsyncFixItQueueManager yöntemini çağırarak iletileri yoklarız.

public class WorkerRole : RoleEntryPoint
{
    public override void Run()
    {
        Task task = RunAsync(tokenSource.Token);
        try
        {
            task.Wait();
        }
        catch (Exception ex)
        {
            logger.Error(ex, "Unhandled exception in FixIt worker role.");
        }
    }

    private async Task RunAsync(CancellationToken token)
    {
        using (var scope = container.BeginLifetimeScope())
        {
            IFixItQueueManager queueManager = scope.Resolve<IFixItQueueManager>();
            while (!token.IsCancellationRequested)
            {
                try
                {
                    await queueManager.ProcessMessagesAsync();
                }
                catch (Exception ex)
                {
                    logger.Error(ex, "Exception in worker role Run loop.");
                }
                await Task.Delay(1000);
            }
        }
    }
    // Other code not shown.
}

ProcessMessagesAsync yöntemi, bekleyen bir ileti olup olmadığını denetler. Varsa, iletiyi bir FixItTask varlığa seri durumdan çıkartır ve varlığı veritabanına kaydeder. Kuyruk boş olana kadar döngüye alır.

public async Task ProcessMessagesAsync()
{
    CloudQueue queue = _queueClient.GetQueueReference(fixitQueueName);
    await queue.CreateIfNotExistsAsync();
    while (true)
    {
        CloudQueueMessage message = await queue.GetMessageAsync();
        if (message == null)
        {
            break;
        }
        FixItTask fixit = JsonConvert.DeserializeObject<FixItTask>(message.AsString);
        await _repository.CreateAsync(fixit);
        await queue.DeleteMessageAsync(message);
    }
}

Kuyruk iletilerinin yoklanması küçük bir işlem ücretine neden olur, bu nedenle işlenmeyi bekleyen bir ileti olmadığında, çalışan rolünün RunAsync yöntemi çağırarak Task.Delay(1000)yeniden yoklamadan önce bir saniye bekler.

Bir web projesinde, IIS sınırlı bir iş parçacığı havuzunu yönettiği için zaman uyumsuz kod eklemek performansı otomatik olarak geliştirebilir. Çalışan rolü projesinde böyle bir durum söz konusu değildir. Çalışan rolünün ölçeklenebilirliğini geliştirmek için çok iş parçacıklı kod yazabilir veya paralel programlama uygulamak için zaman uyumsuz kod kullanabilirsiniz. Örnek paralel programlama uygulamaz, ancak paralel programlama uygulayabilmeniz için kodun zaman uyumsuz hale nasıl getirebileceğinizi gösterir.

Özet

Bu bölümde, kuyruk merkezli iş desenini uygulayarak uygulama yanıt hızını, güvenilirliği ve ölçeklenebilirliği nasıl artırabileceğinizi gördünüz.

Bu, bu e-kitapta ele alınan 13 desenin sonuncusudur, ancak elbette başarılı bulut uygulamaları oluşturmanıza yardımcı olabilecek birçok farklı desen ve uygulama vardır. Son bölümde, bu 13 desende ele alınmayan konular için kaynaklara bağlantılar sağlanır.

Kaynaklar

Kuyruklar hakkında daha fazla bilgi için aşağıdaki kaynaklara bakın.

Belgeler:

Video:

  • FailSafe: Ölçeklenebilir, Dayanıklı Cloud Services oluşturma. Ulrich Homann, Marc Mercuri ve Mark Simms tarafından 9 bölümlü video serisi. Microsoft Müşteri Danışmanlık Ekibi (CAT) deneyiminin gerçek müşterilerle olan hikayeleriyle üst düzey kavramları ve mimari ilkeleri çok erişilebilir ve ilginç bir şekilde sunar. Azure Depolama hizmetine ve kuyruklarına giriş için bkz. 35:13'te başlayan bölüm 5.