2017-09-11 70 views
5

Çok basit Azure işlevleri oluşturdum. Couchbase'den (bir VM'de Azure'da çalışan) veri okuyor ve yazıyorlar.Azure İşlevleri: Pahalı nesne için tekil

Azure İşlevinde Couchbase'e yaptığım bağlantı (lar) ile ilgili endişelerim var. Her seferinde Cluster nesnesi oluşturuyorum. Bu pahalı bir işlemdir ve normalde sadece bir kez normal bir web uygulamasında yapardım. Ancak Azure İşlevi'nde, her seferinde new kullanıyorum.

Böyle Couchbase'in ötesindeki nesnelere benzetilmesi çok pahalı. Azure İşlevlerinin aramalar arasında yeniden kullanabileceği bir tek kişilik veya bir çeşit paylaşılan nesne oluşturmanın yolu var mı?

cevap

3

Normal singleton kullanabilirsiniz, yani statik bir özellik: Burada https://blog.couchbase.com/azure-functions-couchbase-server/

  • tam kaynak kodu bir şeyin tek örneği. Her zaman olduğu gibi, iplik güvenliği konusunda dikkatli olun, örneğin @Jesse tarafından önerildiği gibi Lazy<T> kullanın.

    Ayrıca, İşlevinizin ilk çağrısından önce başlatmayı yapmak için statik bir kurucu kullanabilirsiniz. Statik kurucu tanım gereği iplik güvenlidir.

    Her iki durumda da, aynı şeyi (sunucu) çalıştıran tüm çağrılar arasında pahalı olan şeyleri yeniden kullanabileceksiniz.

  • +2

    Lazy <> veya AsyncLazy <> kullanarak statik özellikleri ile birlikte herhangi bir potansiyel iş parçacığı sorunlarının azaltılmasına yardımcı olur –

    4

    Pahalı bağlantı nesneleriniz için statik özellikler iyi çalışır, ancak bunların Lazy<> içine sarılmasını öneriyorum, böylece kutunun dışında garanti edilmiş iplik güvenliği elde edersiniz. Böyle bir şey görünebilir senin işlevi garantili iş parçacığı güvenli bir şekilde aramaları tamamında kova yeniden kullanılabilir hale örneği ile bağlantılı örnek blog yayınına dayanarak

    : inşaat halinde

    public class FunctionClass 
    { 
        private static Lazy<IBucket> LazyBucket = new Lazy<IBucket>(() => 
        { 
         var uri = ConfigurationManager.AppSettings["couchbaseUri"]; 
         var cluster = new Cluster(new ClientConfiguration 
         { 
          Servers = new List<Uri> { new Uri(uri) } 
         }); 
    
         var bucketName = ConfigurationManager.AppSettings["couchbaseBucketName"]; 
         var bucketPassword = ConfigurationManager.AppSettings["couchbaseBucketPassword"]; 
    
         return cluster.OpenBucket(bucketName, bucketPassword); 
        }); 
    
        // Your actual function implementation 
        public static async Task Run() 
        { 
         // Here you are guaranteed to get back a shared connection object to your bucket that has been 
         // initalized only once in a thread safe way 
         var initalizedOnceBucket = LazyBucket.Value; 
    
         // do something with the bucket 
        } 
    } 
    

    senin Paylaşılması gereken pahalı nesne, bazı async çağrılarına dayanır (Couchbase C# istemcisinin, yöntemlerinin eşzamansız sürümleri olduğundan şüpheleniyorum). Stephen Cleary tarafından yazılan harika Nito.AsyncEx Nuget paketinden AsyncLazy<>'u kullanabilirsiniz. Düzenli Lazy<>, .NET'e yerleşiktir, dolayısıyla herhangi bir dış bağımlılık gerektirmez.

    +0

    Size bir onay işareti verebilirdim keşke. Cevabınız için teşekkür ederim! –

    +1

    Sorun yok, Mikhail buradaydı ve cevabı tamamen doğruydu. Sadece kullanmak istediğim kalıpları kendi fonksiyonumda göstermek istedim –

    5

    Azure İşlevleri'nde singletonlarla çalışırken, bazı önemli noktalar vardır. Bunlardan biri, AF çağrıları arasında global durumunun paylaşılmasıdır. Bu nedenle, bir işlev bir kez ve daha sonra tekrar çağrılırsa (yakında ana makine kodunuzu boşaltmazsa yeterlidir), başlatma yalnızca bir kez gerçekleşir. Bir başka nokta da, AF'nin aynı anda birden fazla AF girişimi başlatmak için tamamen serbest olmasıdır - bu nedenle, herhangi bir tekillerin evrelere (başlatmaları dahil) gerek duyması gerekir.

    Bu, Lazy<T>/AsyncLazy<T>'u kullanmak isteyeceğiniz anlamına gelir. Ancak, AF (bu türlerle) başarısız olsa bile, bir sonraki başlatmanız için tekil durumunu (başlatma sonrası) koruyacağını unutmayın. Bu, özellikle bulut bilişiminde bir sorun olabilir, çünkü AF'niz başladığında bir ağ (veya yapılandırma) hatası varsa, bir sonraki AF çağrısında başlatmanın tekrar denenmesini istersiniz.

    Sonuç olarak, arızaları korumaz ÅŸan ve olduğu şekilde Lazy<T>/AsyncLazy<T> kullanmak istiyorum. Lazy<T> ile

    , bu you have to use the LazyThreadSafetyMode.PublicationOnly flagve yapıcı (sadece örtülü T için varsayılan yapıcısı kullanmayın) için bir işlev geçmesi anlamına gelir. Bu, başlatma işlevinizin kendisinin threadafe olduğundan emin olmanız gerektiği anlamına gelir, çünkü aynı anda birden fazla iş parçacığı tarafından çalıştırılabilir.

    AsyncLazy<T>, you have to use the AsyncLazyFlags.RetryOnFailure flag ile. AsyncLazy<T> esasen bir Lazy<Task<T>> olduğundan, eşzamanlama başlatma görevi tüm eşzamanlı arayanlar arasında "paylaşılır" ve daha sonra başarısız olursa, yeni bir Lazy<Task<T>> örneğiyle atomik olarak değiştirilir. Bu nedenle, async başlatma fonksiyonunun threadafe olması gerekmez.

    ziyade-ve-pasteish kopya edilir tamam (özellikle birden fazla tekil için) bu almak beri, the AF project I'm working on için bu dışarı soyutlanmış:

    Bu noktaya ulaşmak biraz zaman aldı, ama nasıl ortaya çıktığına çok memnun oldum. Bunun hakkında blog yazmak demek ...

    +2

    Stephen Harika cevap için teşekkürler. Bu konuda konuşmak ve işinizi tanıtmak için benim podcast geliyor :) –

    +0

    @MatthewGroves: Ben, isterim, teşekkürler! Web sitenizdeki e-posta formundan bir hata aldım, ancak bana e-posta göndermekten çekinmeyin - [adresim sitemde] (https://stephencleary.com/contact/). –

    +0

    Cevabınızdaki URL'ler şu anda 404 saniyedir; bunları düzeltmeniz veya kodu cevabınıza gönderebilmeniz için herhangi bir şansınız var mı? – Cocowalla