Miroslav Holec
Premium

Jak vyzrát na Azure SQL database is not currently available

Miroslav Holec   29. listopadu 2017

Tento článek je již zastaralý. Článek nemusí popisovat aktuální stav technologie, ideální řešení a můj současný pohled na dané téma.

Čas od času se na mě obrací vývojáří, kteří objevili v logu informaci o neúspěšných pokusech o připojení k Azure SQL databázi. V tomto článku popíšu proč se tak nejčastěji děje a jak tomuto problému předcházet.

Case study

Dovolím si použít přímo úryvek od zákazníka:

... A ještě jedna věc, z automatu na importy občas (tak jednou týdně) přijde chyba "Database 'XXX' on server 'XXX' is not currently available.", někdy to přijde za noc několikrát, ale ráno jsou všechny importy normálně zpracované, takže to znamená, že se to pak zase samo rozběhne. Mám se tím znepokojovat? My stejně chceme po novém roce přenést tu XXX databázi z USA do EU a spojit je všechny do toho elastického poolu, jak jsi navrhoval, takže tohle možná nemá cenu teď vůbec řešit...

K situaci jen doplňuji, že zákazník používá stejně jako většina vývojářských týmů na .NET platformě Entity Framework 6 a databázi má nasazenou v prostředí Azure (služba Azure SQL).

Trocha teorie k Azure SQL

Služba Azure SQL patří do kategorie PaaS služeb a tudíž jako vývojář mám tu výhodu, že se nemusím starat o platformu. Neřeším aktualizace OS, nemusím řešit záplatování SQL serveru a plno dalších věcí. To všechno za mě obstarává poskytovatel. Ale ani poskytovatel není kouzelník a pokud potřebuje aktualizace provádět, musí udělat maximum pro to, abych to jako klient nepoznal nebo co hůře, aby to nepoznali uživatelé mojí aplikace.

Některé rekonfigurace SQL Serveru se bohužel krátkou nedostupností projeví. Zpravidla se tak děje při plánovaném upgradu software nebo výjimečně neplánovaně (selhání procesu nebo load balancingu). Většina výpadků je velmi krátkých a horním stropem je víceméně 60 sekund. Drtivá většina vývojářů o tom vůbec neví, hrstka vývojářů pak problém občas vysleduje, ale jelikož je natolik výjimečný, vůbec to neřeší.

Řešení

Pokud vás toto chování trápí, je potřeba s databázovým serverem komunikovat tak, že v případě této výjimečné události se opakovaně pokusíte o stejnou operaci. Používáte-li Entity Framework 6 nebo Entity Framework Core, je řešení velmi jednoduché, protože vývojáři v Microsoftu s tímto chováním počítají.

Connection Resiliency / Retry Logic (EF 6)

V případě EF 6 stačí povolit tzv. Execution Strategy a nastavit ji na SqlAzureExecutionStrategy. Kompletní konfigurace je vidět na kódu níže:

public class MyConfiguration : DbConfiguration 
{ 
    public MyConfiguration() 
    { 
        SetExecutionStrategy( 
            "System.Data.SqlClient", 
            () => new SqlAzureExecutionStrategy(1, TimeSpan.FromSeconds(30))); 
    } 
}

Zdroj a další informace naleznete v článku:

Connection Resiliency (EF Core)

Pracujete-li s novým Entity Framework Core, pak je možné provést analogicky konfiguraci na místě, kde se registrují služby (například) do ASP.NET Core aplikace:

// Startup.cs from any ASP.NET Core Web API
public class Startup
{
    // Other code ...
    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        // ...
        services.AddDbContext<OrderingContext>(options =>
        {
            options.UseSqlServer(Configuration["ConnectionString"],
            sqlServerOptionsAction: sqlOptions =>
            {
                sqlOptions.EnableRetryOnFailure(
                maxRetryCount: 5,
                maxRetryDelay: TimeSpan.FromSeconds(30),
                errorNumbersToAdd: null);
            });
        });
    }
//...
}

Zdroj a další informace naleznete v článku:

Jak je vidět z příkladů, implementace je otázkou několika řádků.