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:
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 pageHer 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:
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.
| Özellik | Amaç |
|---|---|
Location | CloudLocation.FileShare için bir UNC/yerel paylaşım |
RootPath | Her düğümün ulaşabileceği paylaşılan klasör |
UsePerTokenSubfolders | Her belgenin artefaktlarını kendi {token} klasöründe tutun |
ReadReadyPollMs | Okuma 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:
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:
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:
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:
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:
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:
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:
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.Path | FileShareConfig.RootPath |
PageWaitTimeSeconds / StartWaitFromPage | DistributedDocumentPublishOptions.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 / WebfarmPath | Hâlâ mevcut, IsWebFarm / WebFarmPath olarak yazılıyor — yayın yolunda gerek yok |
Doconut.Configs.Cloud | Doconut.Clouds |
Kontrol Listesi
FileShareConfig'i tek bir yardımcıda oluşturun ve her iki yarıdan da çağırın.RootPath'i zaten kullandığınız paylaşıma yönlendirin.PublishAsync(...)ile yayınlayın; tümExportToPng/ExportToCloudçağrılarını silin.- İstemcinin çağırdığı dalda
UseDoconutCloud<FileShareCloudHandler>(...)ile hizmet verin. FirstPagePriorityveretryOn409'i birlikte etkinleştirin, ya da ikisini de kapalı bırakın.- Oturum başına kontrolü imzalı erişim biletleriyle değiştirin — yalnızca
UnsafeMode = truegöndermeyin. - Bir düğümde belge açıp diğerinden geç bir sayfa talep ederek doğrulayın.
Bu sayfa yardımcı oldu mu?