Dağıtık Dağıtımlar

Bir belgeyi birden fazla düğümden sunun

Birden fazla düğüm aynı belgeleri sunduğunda, bir belgeyi işleyen düğüm, tarayıcının sayfa isteklerine yanıt veren düğüm olmak zorunda değildir. Bu sürüm bu işi iki açık yarıya ayırır — bir yazma tarafı belge artefaktlarını paylaşılan depolamaya yayınlar ve bir okuma tarafı bunları herhangi bir düğümden sunar.

Uygulamanız şu anda UseDoconutWebFarm(...) çağrısı yapıyorsa, bu sayfa sizin yerinize geçer. Ne UseDoconutWebFarm ne de WebFarmOptions bu sürümde bulunmaz.

Topolojiniz değişmez. Paylaşılan kökü bugün kullandığınız aynı UNC yoluna işaret edin ve her düğüm şu anda olduğu gibi çalışmaya devam eder. Değişen şey, yayınlamanın bir yan etki yerine sizinin çağırdığınız bir işlem olmasıdır.

Web-farm ara katmanının yerine ne geldi

Önceden tek bir ara katman her şeyi yapıyordu: önceden işlenmiş görüntüleri paylaşılan bir klasörden sunuyor ve başka bir düğüm hâlâ onları yazarken sorguluyordu. Bekleme, kör bir bütçeydi — “sayfanın görünmesini umarak üç dakikaya kadar blokla”.

Şimdi aynı iş iki çağrı haline geldi ve görebilir ve mantık yürütebilirsiniz:

text
node A            OpenDocument request
                      -> PublishAsync(...)   writes pages, document info,
                                             search index and metadata
                                             into  RootPath/{token}/
                      -> returns the token

node B            ?token=...&page=7
                      -> UseDoconutCloud<FileShareCloudHandler>
                      -> reads RootPath/{token}/ and serves the page

Her iki yarının da ihtiyaç duyduğu paylaşılan yapılandırma

Yayıncı, bir FileShareConfig ile yazar ve okuma işleyicisi de bir tanesiyle sunar. Eğer RootPath ya da UsePerTokenSubfolders bunlar arasında farklıysa, diğer düğüm 404 yanıt verir. Yapılandırmayı tam olarak bir yerde oluşturun ve her iki taraftan da çağırın — referans uygulama bu nedenle tek bir SharedStore.Config(...) yardımcı işlevi tutar:

csharp
internal static class SharedStore
{
    public static FileShareConfig Config(string rootPath, bool asyncPublish) => new()
    {
        Location              = CloudLocation.FileShare,
        RootPath              = rootPath,               // e.g. \\fileserver\doconut
        UsePerTokenSubfolders = true,
        ReadReadyPollMs       = asyncPublish ? 250 : 0,
    };
}

FileShareConfig, Doconut.Clouds içinde bulunur; aynı zamanda AzureConfig, AmazonConfig, GoogleCloudConfig, DropBoxConfig, RedisConfig, CDNConfig ve FTPConfig ile birlikte yer alır. Önceki kütüphanede bunlar Doconut.Configs.Cloud içindeydi; sınıf adları değişmedi.

ÖzellikAmaç
LocationCloudLocation.FileShare için bir UNC/yerel paylaşım
RootPathHer düğümün ulaşabileceği paylaşılan klasör
UsePerTokenSubfoldersHer belgenin artefaktlarını kendi {token} klasöründe tutun
ReadReadyPollMsOkuma tarafının hâlâ yazılan bir sayfa için ne kadar süre beklediği; 0 anketi devre dışı bırakır

Yazma tarafı — belgeyi yayınlayın

DistributedDocumentPublisher enjekte edin ve yerel bir oturum açmak yerine yayınlayın. Tek bir çağrı, tam artefakt setini — sayfalar, belge bilgisi, arama indeksi ve meta verileri — oluşturur ve yazar:

csharp
var shareConfig = SharedStore.Config(rootPath, asyncPublish: false);

var documentOptions = new DocOptions { TimeOut = 60 };
var config          = new PdfConfig { AllowSearch = true };

var publishOptions = new DistributedDocumentPublishOptions
{
    CleanUpStagingDirectory = true,
    FirstPagePriority       = true,
};

DistributedDocumentPublishResult result = await _publisher.PublishAsync(
    pathToFile, shareConfig, config, documentOptions, publishOptions, ct);

return Content(result.Token);

DistributedDocumentPublishResult Token, ArtifactPath, TotalPages ve Format değerlerini taşır. Token, normal bir görüntüleyici tokeni gibi tarayıcıya tam olarak gönderilir.

Bu tek çağrı, önceki çifti — belgeyi yerel bir oturuma açmak ve ardından ExportToPng(sharedPath) ile görüntüleri paylaşıma dökmek — yerine geçer. ExportToPng ve ExportToCloud burada eşdeğeri olmayan işlevlerdir.

Okuma tarafı — paylaşımdan hizmet ver

FileShare işleyicisini, istemcinin zaten çağırdığı aynı dalda monte edin:

csharp
app.UseDoconutResources();

app.MapWhen(
    ctx => ctx.Request.Path.Value?.EndsWith("DocImage.axd", StringComparison.OrdinalIgnoreCase) == true,
    branch => branch.UseDoconutCloud<FileShareCloudHandler>(options =>
    {
        options.Location          = CloudLocation.FileShare;
        options.CloudUploadConfig = SharedStore.Config(rootPath, asyncPublish: false);
    }, "/"));

UseDoconutCloud bu sürümde jeneriktir: sağlayıcı, ara katmanda Location değerine göre değiştirilen bir tip argümanıdır. İşleyicilerin adı <Provider>CloudHandler biçimindedir — FileShareCloudHandler, AzureCloudHandler, AmazonS3CloudHandler, GoogleCloudHandler, DropBoxCloudHandler, RedisCloudHandler, FTPCloudHandler ve CDNCloudHandler.

CDN işleyicisi yalnızca okuma amaçlıdır — CDN’de zaten bulunanları sunar; yükleme yapmaz.

İlk sayfa önceliği ve HTTP 202

FirstPagePriority = true ayarı, 1. sayfanın hemen hizmet verilebilir olmasını sağlar. Sonraki sayfalar, yazılana kadar HTTP 202 Accepted yanıtı verir, isteği engellemez.

Bu, beklemeyi istemciye taşır; burada sınırlı ve görülebilir olur. Widget üzerinde yeniden denemeyi etkinleştirin:

javascript
const objViewer = $('#div_ctlDoc').docViewer({
    BasePath:   '/',
    ResPath:    'doconut-res/images',
    retryOn409: true      // retries 202 (and legacy 409) readiness responses
});

Yeniden denemeyen bir istemci, hâlâ işlenmekte olan sayfalar için kırık kareler gösterir. Yeniden deneme bütçesi ve varsayılanları (retryInitialDelayMs, retryBackoffFactor, retryMaxDelayMs, retryMaxAttempts, retryMaxTotalMs) GörüntüleyiciYapılandırması içinde belgelenmiştir.

Bu çift — FirstPagePriority ve okuma‑tarafı anketi — önceki PageWaitTimeSeconds ve StartWaitFromPage ayarlarının yerini alır. Artık hiçbiri mevcut değildir.

İsteğe bağlı: arka planda yayınlama

Varsayılan olarak PublishAsync dönüş yapmadan önce render eder. Token oluşturulur oluşturulmaz dönmek ve barındırılan bir işçinin aynı klasöre render etmesine izin vermek için isteğe bağlı kuyruğu kaydedin:

csharp
builder.Services.AddDoconut(options => { /* … */ });
builder.Services.AddDoconutDistributedAsyncPublish();

Ardından satır içi yayınlamak yerine kuyruğa ekleyin ve yayın seçeneklerinde Async = true ayarlayın. Kuyruk sınırlıdır: dolduğunda EnqueueAsync DistributedPublishQueueFullException fırlatır. Bunu bir 503 ve Retry-After başlığıyla yanıtlayın, böylece istemciler durmak yerine geri çekilir:

csharp
try
{
    var token = await _publishQueue.EnqueueAsync(
        pathToFile, shareConfig, config, documentOptions, publishOptions, ct);
    return Content(token);
}
catch (DistributedPublishQueueFullException)
{
    Response.Headers.RetryAfter = "5";
    Response.StatusCode = 503;
    return Content("The publish queue is full. Please retry.");
}

Bu kayıt yapılmadan hiçbir şey kaydedilmez ve yayınlama senkron kalır — varsayılan yol bayt‑bayt aynı kalır.

Arka plan yayınlaması açık olduğunda, okuma tarafına sıfır olmayan bir ReadReadyPollMs verin; böylece işçi henüz yazmamış bir sayfa için kısa bir süre bekler.

Düğümler arasında güvenlik

Oturuma bağlı tokenlar, hizmet veren düğümün açılış isteğini gördüğünü varsayar. Bir çiftlikte bu gerçekleşmez, bu yüzden oturum‑başına kontrol geçerli istekleri reddeder. Bu yüzden dağıtık referans uygulaması UnsafeMode = true ayarını yapar.

UnsafeMode = true güvenlik modeli değildir — artık geçerli olmayan bir modeli kaldırmaktır. Bunu, her düğümün bağımsız olarak doğrulayabileceği imzalı erişim biletleriyle değiştirin:

csharp
builder.Services.AddDoconutDistributedDocumentSecurity(options => { /* … */ });

UnsafeMode = true ayarını tek düğümlü bir dağıtıma geri getirmeyin ve bir düğümde başarısız oturum kontrolünün kısayolu olarak kullanmayın — burada doğru çözüm AddSession() / UseSession()’dır. Oturumlar ve Güvenlik bölümüne bakın.

Yayınlanmış bir belgeyi kapatma

CloseDocument(token) enjekte edilen Viewer üzerinde yerel bir oturumu sonlandırır. Paylaşımdan bir belgenin yayınlanmış eserlerini kaldırmak için yayıncı şunu sunar:

text
bool CloseDistributedDocument(FileShareConfig fileShareConfig, string token)

Belgenin yayınlandığı aynı FileShareConfig'i geçin.

Ayar‑ayar eşlemesi

ÖncekiŞimdi
UseDoconutWebFarm(new WebFarmOptions { … })PublishAsync(...) yazma tarafında ve UseDoconutCloud<FileShareCloudHandler>(...) okuma tarafında
WebFarmOptions.PathFileShareConfig.RootPath
PageWaitTimeSeconds / StartWaitFromPageDistributedDocumentPublishOptions.FirstPagePriority ve FileShareConfig.ReadReadyPollMs
viewer.OpenDocument(...) then viewer.ExportToPng(share)tek bir PublishAsync(...) çağrısı
viewer.ExportToCloud(cloudConfig)sağlayıcının yapılandırmasıyla PublishAsync(...)
UseDoconutCloud(new CloudOptions { Location = … })UseDoconutCloud<THandler>(options => …, pathPrefix)
DocOptions.IsWebfarm / WebfarmPathHâlâ mevcut, IsWebFarm / WebFarmPath olarak yazılıyor — yayın yolunda gerek yok
Doconut.Configs.CloudDoconut.Clouds

Kontrol Listesi

  1. FileShareConfig'i tek bir yardımcıda oluşturun ve her iki yarıdan da çağırın.
  2. RootPath'i zaten kullandığınız paylaşıma yönlendirin.
  3. PublishAsync(...) ile yayınlayın; tüm ExportToPng / ExportToCloud çağrılarını silin.
  4. İstemcinin çağırdığı dalda UseDoconutCloud<FileShareCloudHandler>(...) ile hizmet verin.
  5. FirstPagePriority ve retryOn409'i birlikte etkinleştirin, ya da ikisini de kapalı bırakın.
  6. Oturum başına kontrolü imzalı erişim biletleriyle değiştirin — yalnızca UnsafeMode = true göndermeyin.
  7. Bir düğümde belge açıp diğerinden geç bir sayfa talep ederek doğrulayın.

Bu sayfa yardımcı oldu mu?