Ders 08 / 14
Bağlantı Durumu Yönetimi
Bağlantı durumu yönetimi, bağlantıyı izlemeyi, zayıf bağlantıya uyum sağlamayı, yeniden denemeyi ve durumu kullanıcıya göstermeyi anlatır. Ders görsel galerisinin zayıf bağlantıda kısıtlı, mesajlaşmanın ertelenen kaldığını ölçer.
Yayın Güncelleme
Bu derste
- Bağlantının var ya da yok olmaktan fazlası olduğunu ve izleme düzeneklerinin ne söylediğini açıklar
- Zayıf bağlantıda bir özelliğin düşük kaliteli yedeğe geçmesini ölçer
- Sabit aralıklı yeniden deneme ile üstel geri çekilmeyi karşılaştırır
- Bağlantı durumunun kullanıcıya özellik bazında gösterilmesini işlerlik kayıtlarından türetir
İçindekiler
Önceki derste arka plan yeteneği vardı ya da yoktu, bağlantı ise hep vardı. Gerçekte bağlantı da kesilir, yavaşlar, geri gelir. Metroda sinyal gidip gelir, kalabalık bir salonda bağlantı görünür ama veri akmaz, bir tünelden çıkınca ağ bir anda döner. Bu ders bağlantıyı izlemeyi, zayıf bağlantıya uyum sağlamayı, başarısız bir isteği yeniden denemeyi ve durumu kullanıcıya göstermeyi anlatır.
Kursun sorusu aynı kalır: bu koşulda bu özellik ne kadar çalışıyor? Bu ders soruyu üç bağlantı durumunda üç özellik için sorar.
Bağlantıyı İzlemek
Her iki platform da bağlantıdaki değişimi uygulamaya bildirir. Uygulama bir izleyici kaydeder ve sistem bağlantı kurulduğunda, koptuğunda ya da niteliği değiştiğinde izleyiciyi çağırır. Aşağıdaki iOS parçası bunu gösterir. Parça ölçülmez.
// Platform kodu: iOS baglanti izleme
let monitor = NWPathMonitor()
monitor.pathUpdateHandler = { path in
let isOnline = path.status == .satisfied
let isWeak = path.isConstrained || path.isExpensive
connectionState.update(online: isOnline, weak: isWeak)
}
monitor.start(queue: DispatchQueue(label: "connectivity"))
Android’de aynı iş, sistem hizmetinden alınan bir yöneticiye geri çağrı kaydederek yapılır. Parça ölçülmez.
// Platform kodu: Android baglanti izleme
val manager = context.getSystemService(ConnectivityManager::class.java)
manager.registerDefaultNetworkCallback(object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) = connectionState.update(online = true)
override fun onLost(network: Network) = connectionState.update(online = false)
})
İzleyicinin söylediği şey sınırlıdır. Sistem “bir ağ yolu var” der; “sunucuya istek ulaşır” demez. Bir ağa bağlı olup internete çıkamayan, giriş sayfası bekleyen ya da çok yavaş bir bağlantı izleyicide “bağlı” görünebilir. İzleyici bu yüzden bir ipucudur, kesinlik değil: gerçek bir isteğin başarısı ya da başarısızlığı son sözü söyler.
Zayıf Bağlantı
Bağlantının iki ucu, tam bağlı ve hiç bağlı değil, kolaydır. Zor olan aradır: bağlantı vardır ama veri yavaş akar, sık kesilir ya da kullanıcı veri tasarrufu açmıştır. Bu durumda uygulamanın iki seçeneği vardır: büyük içeriği istemeye devam edip beklemek ya da daha küçük bir içerikle yetinmek. İyi bir uygulama ikincisini seçer; görsel yüksek çözünürlük yerine düşük çözünürlükle gelir, büyük bir liste kısa bir listeye iner, canlı güncelleme yerine kullanıcının isteğiyle yenileme gelir.
Model zayıf bağlantıyı bir yetenek eksiği olarak kurar: ağ vardır ama bandwidth yoktur. bandwidth, büyük içeriği makul bir sürede almak için yeterli veri hızı anlamına gelir. Eksik olduğunda özellik tanımlı yedeğine geçer.
Özellikleri Kurmak
Ölçüm için kursun çekirdeği gerekir. Çekirdek ilk dersten tanıdıktır ve her derste aynı biçimde yeniden verilir; ders ona dokunmaz.
// operability.mjs — bir ozelligin bir kosulda ne kadar calistigini siniflandirir export const LEVELS = ["tam", "kisitli", "ertelenen", "kapali"]; const FALLBACKS = ["kisitli", "ertelenen"]; export function feature(name, needs, fallback = {}) { return { name, needs, fallback }; } export function condition(name, has) { return { name, has }; } function judge(item, cond) { const missing = item.needs.filter((need) => !cond.has.includes(need)).sort(); let level = "tam"; for (const need of missing) { const given = FALLBACKS.includes(item.fallback[need]) ? item.fallback[need] : "kapali"; if (LEVELS.indexOf(given) > LEVELS.indexOf(level)) level = given; } return { level, feature: item.name, condition: cond.name, missing }; } export function assess(features, conditions) { const records = []; for (const cond of conditions) { for (const item of features) records.push(judge(item, cond)); } return records; } export function printLevels(records) { for (const r of records) { const missing = r.missing.length === 0 ? "-" : r.missing.join(","); console.log(`${r.level}: ${r.feature} @ ${r.condition} eksik=${missing}`); } } export function countLevels(records) { for (const name of LEVELS) { console.log(`${name}: ${records.filter((r) => r.level === name).length}`); } console.log(`etkilenen: ${records.filter((r) => r.level !== "tam").length}`); }
Dersin yardımcı dosyası üç özellik kurar. Gallery görsel galerisidir; network ve bandwidth ister, bandwidth eksikse düşük çözünürlüklü önizlemeye düşer, yani yedeği kisitlidir. network için yedeği yoktur. Chat mesajlaşmadır; aynı iki yeteneği ister ve her ikisi eksik olduğunda mesajı sıraya alır, yani iki yedeği de ertelenendir. Settings ayarlardır ve yalnız storage ister. conditionsFor(link) bir bağlantı durumunu koşula çevirir: iyi bağlantıda online, zayıf bağlantıda weak-network, bağlantı yokken offline.
// connectivity.mjs — baglanti ozelliklerini ve baglanti kosullarini kurar import { feature, condition } from "./operability.mjs"; export const gallery = feature("Gallery", ["network", "bandwidth"], { bandwidth: "kisitli" }); export const chat = feature("Chat", ["network", "bandwidth"], { network: "ertelenen", bandwidth: "ertelenen" }); export const settings = feature("Settings", ["storage"]); export function conditionsFor(link) { if (link.quality === "good") return condition("online", ["network", "bandwidth", "storage"]); if (link.quality === "weak") return condition("weak-network", ["network", "storage"]); return condition("offline", ["storage"]); }
İlk ölçüm üç bağlantı durumunu koşula çevirir, her koşulun yeteneklerini basar ve iki özelliği üç koşulda sınıflar.
// main.mjs import { assess, printLevels } from "./operability.mjs"; import { gallery, settings, conditionsFor } from "./connectivity.mjs"; const links = [{ quality: "good" }, { quality: "weak" }, { quality: "none" }]; const conds = links.map(conditionsFor); for (const c of conds) console.log(`${c.name}: ${c.has.join(",")}`); printLevels(assess([gallery, settings], conds));
online: network,bandwidth,storage weak-network: network,storage offline: storage tam: Gallery @ online eksik=- tam: Settings @ online eksik=- kisitli: Gallery @ weak-network eksik=bandwidth tam: Settings @ weak-network eksik=- kapali: Gallery @ offline eksik=bandwidth,network tam: Settings @ offline eksik=-
Zayıf bağlantıda Gallery kısıtlıdır: ağ vardır, ama bandwidth yoktur ve galeri düşük çözünürlüklü önizlemeye düşer. Bağlantı yokken aynı galeri kapalıdır, çünkü network eksiğinin yedeği yoktur ve galeri bir önbellek tutmaz. Settings yalnız yerel depoya dayandığı için üç koşulda da tamdır.
CE4. Model, bağlantıyı üç kesin duruma indirir: iyi, zayıf, yok. Gerçek bir bağlantı bu üç durum arasında sürekli kayar ve izleyici bu kaymayı gecikmeyle bildirir. Zayıflığın nerede başladığı modelde bir eşik olarak değil, bandwidth yeteneğinin yokluğu olarak kurulur. Kural yeteneği ve yedeği görür; veri hızını, kaybolan paketleri ve kullanıcının sabrını görmez. Model, bu işlerliğin kuralını kurar; model çerçevenin kendisi değildir.
Yeniden Deneme ve Üstel Geri Çekilme
Bağlantı yokken ya da zayıfken gönderilen bir mesaj başarısız olabilir. Uygulama isteği yeniden dener. Sorun, ne zaman deneyeceğidir. Sabit aralıklı yeniden denemede her deneme bir öncekinden aynı aralıkla sonra gelir. Bağlantı kısa süre sonra dönecekse ilk fırsatta yakalar, ama dönmeyecekse boşuna pil ve ağ harcar; binlerce istemci aynı anda aynı sunucuya yüklenirse sunucuyu da yorar.
Üstel geri çekilmede her başarısız denemeden sonra bekleme iki katına çıkar ve bir üst sınırda durur. İlk denemeler hızlıdır, sonrakiler seyrekleşir. Gerçek uygulamalarda bekleme süresine küçük bir rastgele pay da eklenir ki binlerce istemci aynı anda denemesin; model rastgelelik içermediği için bu payı kurmaz. Yeniden denemenin güvenle yapılabilmesi, önceki dersteki yinelemeye dayanıklı gönderime bağlıdır: aynı mesajın iki kez ulaşması sonucu bozmaz.
Modelde zaman gerçek süreyle değil, tur ile ifade edilir. Tur bir sıra birimidir; bir saniyeyi ya da bir dakikayı temsil etmez. Aşağıdaki işlev bağlantının belli bir turda döndüğü bir senaryoda her stratejinin kaç deneme yaptığını ve işin hangi turda ulaştığını hesaplar.
// retry.mjs — yeniden deneme stratejilerini tur sayisiyla kurar export function attemptsUntil(strategy, returnTurn) { let turn = 0; let wait = 1; let attempts = 0; while (true) { attempts += 1; if (turn >= returnTurn) return { attempts, turn }; turn += wait; if (strategy === "ustel") wait = Math.min(wait * 2, 8); } }
İkinci ölçüm bağlantı yokken Chat’in kaydını ve iki stratejinin sonucunu basar. Bağlantı onuncu turda döner.
// main.mjs import { assess, printLevels } from "./operability.mjs"; import { chat, settings, conditionsFor } from "./connectivity.mjs"; import { attemptsUntil } from "./retry.mjs"; const conds = [{ quality: "none" }, { quality: "good" }].map(conditionsFor); printLevels(assess([chat, settings], conds).filter((r) => r.feature === "Chat")); for (const strategy of ["sabit", "ustel"]) { const result = attemptsUntil(strategy, 10); console.log(`${strategy}: ${result.attempts} deneme, ${result.turn}. turda ulasti`); }
ertelenen: Chat @ offline eksik=bandwidth,network tam: Chat @ online eksik=- sabit: 11 deneme, 10. turda ulasti ustel: 5 deneme, 15. turda ulasti
Sabit aralıklı strateji işi onuncu turda, bağlantı döner dönmez ulaştırdı, ama on bir deneme yaptı. Üstel strateji beş deneme yaptı ve işi on beşinci turda ulaştırdı: bağlantı dönmüştü, ama bir sonraki deneme henüz gelmemişti. Seyrek denemenin bedeli gecikmedir, sıkı denemenin bedeli boşa giden denemelerdir. Hangisinin seçileceği ürünün neyi önemsediğine bağlıdır. İkisinde de Chat @ offline ertelenendir, çünkü mesaj kaybolmaz; sıraya alınır ve bağlantı dönünce gönderilir.
Durumu Kullanıcıya Göstermek
Bağlantı yok ya da zayıf olduğunda kullanıcıya tek bir “çevrimdışısınız” bildirimi göstermek kolaydır ve yanıltıcıdır. Aynı anda galeri düşük çözünürlüğe düşmüş, mesajlar sıraya girmiş, ayarlar normal çalışıyordur. Kullanıcı için anlamlı olan, her özelliğin durumudur. İşlerlik kaydı bu mesajı doğrudan taşır: kısıtlı özellik “sınırlı”, ertelenen özellik “sırada”, kapalı özellik “kullanılamıyor” der; tam özellik hiçbir şey demez.
// banner.mjs — bir kayittan kullaniciya gosterilecek durumu uretir const LABELS = { tam: "-", kisitli: "sinirli", ertelenen: "sirada", kapali: "kullanilamiyor" }; export function labelFor(record) { return LABELS[record.level]; } export function printBanners(records) { for (const r of records) console.log(`${r.feature} @ ${r.condition}: ${labelFor(r)}`); }
// main.mjs import { assess } from "./operability.mjs"; import { gallery, chat, settings, conditionsFor } from "./connectivity.mjs"; import { printBanners } from "./banner.mjs"; const conds = [{ quality: "weak" }, { quality: "none" }].map(conditionsFor); printBanners(assess([gallery, chat, settings], conds));
Gallery @ weak-network: sinirli Chat @ weak-network: sirada Settings @ weak-network: - Gallery @ offline: kullanilamiyor Chat @ offline: sirada Settings @ offline: -
Zayıf bağlantıda ve bağlantı yokken Settings hiçbir bildirim taşımaz. Chat iki koşulda da “sırada” der: mesaj gönderilmedi, ama kaybolmadı. Gallery zayıf bağlantıda “sınırlı”, bağlantı yokken “kullanılamıyor” der. Aynı bağlantı durumu üç özellikte üç ayrı mesaj üretti.
Sınırlayıcı Ölçüm
Bu dersin odak kaydı Gallery @ weak-network’tür. Son ölçüm üç özelliği üç bağlantı durumunda koşar, zayıf bağlantının kayıtlarını ve sayımı basar.
// main.mjs import { assess, printLevels, countLevels } from "./operability.mjs"; import { gallery, chat, settings, conditionsFor } from "./connectivity.mjs"; const features = [gallery, chat, settings]; const links = [{ quality: "good" }, { quality: "weak" }, { quality: "none" }]; const records = assess(features, links.map(conditionsFor)); printLevels(records.filter((r) => r.condition === "weak-network")); countLevels(records); const withCopies = (copies) => assess(features, [{ quality: "weak", copies }].map(conditionsFor)); const same = JSON.stringify(withCopies(1)) === JSON.stringify(withCopies(3)); console.log(`kopya sayisi kayda girmez: ${same ? "evet" : "hayir"}`);
kisitli: Gallery @ weak-network eksik=bandwidth ertelenen: Chat @ weak-network eksik=bandwidth tam: Settings @ weak-network eksik=- tam: 5 kisitli: 1 ertelenen: 2 kapali: 1 etkilenen: 4 kopya sayisi kayda girmez: evet
İlk satır dersin işlerliğini taşır: zayıf bağlantıda galeri kısıtlı çıktı. Aynı koşulda Chat ertelenen, Settings tamdır. Dokuz kaydın beşi tam, biri kısıtlı, ikisi ertelenen, biri kapalıdır; etkilenen dört.
Son satır M31/K05’in sorusundan farkı gösterir. O ders gönderilen bir olayın alıcıya kaç kopya olarak ulaştığını sordu. Bağlantı dönünce sıradaki mesajlar teslim edilir ve yeniden denemeler yüzünden aynı mesaj birden çok kez ulaşabilir. İşlerlik bunu sınıflamaz: bir kopya da üç kopya da aynı kaydı üretir. Bu bir gözlem değil, modelin tanımıdır; koşulu kuran conditionsFor işlevi copies alanını hiç okumaz. İşlerlik teslimin kaç kopya olduğunu değil, zayıf bağlantıda özelliğin ne yaptığını sınıflar. Mesaj sıraya girer ve bu, kaç kez gönderildiğinden bağımsız olarak ertelenendir.
Özet
- Bu dersin işlerliği: kısıtlı.
Gallery @ weak-network,bandwidtheksik olduğu vekisitliyedeği tanımlandığı için kısıtlı çıktı; aynı koşuldaChatertelenen,Settingstam kaldı. - Platform izleyicileri bir ağ yolunun varlığını bildirir, isteğin ulaşacağını değil; gerçek isteğin sonucu son sözü söyler.
- Zayıf bağlantıda ağ vardır ama
bandwidthyoktur; özellik tanımlı yedeğe, düşük çözünürlüklü önizlemeye ya da sıraya geçer. - Aynı senaryoda sabit aralıklı strateji on bir deneme yaptı ve onuncu turda, üstel strateji beş deneme yaptı ve on beşinci turda ulaştı; seyrek denemenin bedeli gecikmedir.
- Kullanıcıya özellik bazında durum gösterilir: sınırlı, sırada, kullanılamıyor.
Sonraki Adım
Bu konuda bir özelliğin kapalı ya da kısıtlı kalma nedeni hep koşuldu: ağ, depolama alanı, arka plan, veri hızı. Üretimde bir özelliğin kapalı kalması için koşulun bozulması gerekmez; aşamanın yapılandırması özelliği kapalı tutabilir. Sıradaki ders, Mobil Sürekli Teslimat, uygulamanın derlenip imzalanarak mağazaya ve test kullanıcılarına ulaştığı hattı ele alır. Sonra hazırlık aşamasında açık, üretim aşamasında kapalı bir özelliğin işlerliğini ölçer.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.