{"id":33198,"date":"2025-10-31T01:31:29","date_gmt":"2025-10-30T22:31:29","guid":{"rendered":"https:\/\/fatihsoysal.com\/blog\/ballerina-ile-gercek-zamanli-veri-akisi-server-sent-events-sse\/"},"modified":"2025-10-31T01:31:29","modified_gmt":"2025-10-30T22:31:29","slug":"ballerina-ile-gercek-zamanli-veri-akisi-server-sent-events-sse","status":"publish","type":"post","link":"https:\/\/fatihsoysal.com\/blog\/ballerina-ile-gercek-zamanli-veri-akisi-server-sent-events-sse\/","title":{"rendered":"Ballerina ile Ger\u00e7ek Zamanl\u0131 Veri Ak\u0131\u015f\u0131: Server-Sent Events (SSE)"},"content":{"rendered":"<p><body><\/p>\n<p>Modern web uygulamalar\u0131, kullan\u0131c\u0131lar\u0131na anl\u0131k ve dinamik deneyimler sunmak zorundad\u0131r. Peki, taray\u0131c\u0131lar\u0131n\u0131z\u0131n sunucudan s\u00fcrekli g\u00fcncel verileri, karma\u015f\u0131k altyap\u0131lar kurmadan, basit\u00e7e almas\u0131n\u0131 nas\u0131l sa\u011flar\u0131z? Server-Sent Events (SSE) ve Ballerina ile ger\u00e7ek zamanl\u0131 veri ak\u0131\u015f\u0131n\u0131 kolayca hayata ge\u00e7irebilirsiniz.<\/p>\n<p>G\u00fcn\u00fcm\u00fcz\u00fcn dijital d\u00fcnyas\u0131nda kullan\u0131c\u0131 beklentileri hi\u00e7 olmad\u0131\u011f\u0131 kadar y\u00fcksek. Statik web sayfalar\u0131n\u0131n yerini, anl\u0131k bildirimler, canl\u0131 skorlar, borsa verileri, sohbet uygulamalar\u0131 ve s\u00fcrekli g\u00fcncellenen g\u00f6sterge panolar\u0131 ald\u0131. Bir kullan\u0131c\u0131, favori tak\u0131m\u0131n\u0131n gol att\u0131\u011f\u0131n\u0131 veya bir hisse senedinin fiyat\u0131n\u0131n de\u011fi\u015fti\u011fini saniyeler i\u00e7inde \u00f6\u011frenmek ister. Geleneksel HTTP istek-cevap d\u00f6ng\u00fcs\u00fc, bu t\u00fcr ger\u00e7ek zamanl\u0131 senaryolar i\u00e7in yetersiz kal\u0131r. S\u00fcrekli sorgulama (polling) yapmak sunucu kaynaklar\u0131n\u0131 yorarken, karma\u015f\u0131k WebSockets ba\u011flant\u0131lar\u0131 her zaman gerekli olmayabilir. \u0130\u015fte bu noktada, tek y\u00f6nl\u00fc, verimli ve kullan\u0131m\u0131 kolay bir alternatif olan Server-Sent Events (SSE) devreye girer. Ballerina gibi a\u011f odakl\u0131 dillerle birle\u015fti\u011finde, SSE&#8217;nin sundu\u011fu basitlik ve g\u00fc\u00e7, ger\u00e7ek zamanl\u0131 uygulamalar geli\u015ftirmeyi hi\u00e7 olmad\u0131\u011f\u0131 kadar eri\u015filebilir k\u0131lar. Bu makalede, SSE&#8217;nin temel prensiplerinden, Ballerina ile nas\u0131l ad\u0131m ad\u0131m uygulanaca\u011f\u0131na kadar t\u00fcm detaylar\u0131 ele alacak, ger\u00e7ek d\u00fcnya senaryolar\u0131yla bu teknolojinin potansiyelini ke\u015ffedece\u011fiz. Amac\u0131m\u0131z, karma\u015f\u0131k altyap\u0131lar kurmadan, Ballerina&#8217;n\u0131n do\u011fal e\u015fzamanl\u0131l\u0131k \u00f6zelliklerini kullanarak nas\u0131l g\u00fc\u00e7l\u00fc ve \u00f6l\u00e7eklenebilir ger\u00e7ek zamanl\u0131 veri ak\u0131\u015f\u0131 \u00e7\u00f6z\u00fcmleri olu\u015fturabilece\u011finizi g\u00f6stermektir. Bu sayede, kullan\u0131c\u0131lar\u0131n\u0131za daha zengin ve etkile\u015fimli deneyimler sunabilirsiniz.<\/p>\n<h2>Server-Sent Events (SSE) Nedir? Tek Y\u00f6nl\u00fc \u0130leti\u015fimin G\u00fcc\u00fc<\/h2>\n<p>Server-Sent Events (SSE), ad\u0131ndan da anla\u015f\u0131laca\u011f\u0131 gibi, sunucunun istemciye (genellikle bir web taray\u0131c\u0131s\u0131) olay tabanl\u0131 veri ak\u0131\u015f\u0131 g\u00f6ndermesini sa\u011flayan bir web teknolojisidir. Temel fark\u0131, geleneksel HTTP&#8217;deki istek-cevap modelinin aksine, SSE&#8217;nin tek y\u00f6nl\u00fc bir ileti\u015fim kanal\u0131 kurmas\u0131d\u0131r. Yani, istemci bir ba\u011flant\u0131 ba\u015flat\u0131r ve sunucu bu ba\u011flant\u0131 \u00fczerinden istemciye s\u00fcrekli olarak veri &#8220;iter&#8221;. Bu, \u00f6zellikle bir kaynaktan s\u00fcrekli bilgi ak\u0131\u015f\u0131 bekledi\u011finiz, ancak istemcinin sunucuya veri g\u00f6ndermesine gerek duymad\u0131\u011f\u0131n\u0131z senaryolar i\u00e7in m\u00fckemmel bir \u00e7\u00f6z\u00fcmd\u00fcr. \u00d6rne\u011fin, canl\u0131 spor skorlar\u0131, borsa fiyat g\u00fcncellemeleri, haber ak\u0131\u015flar\u0131 veya bir IoT cihaz\u0131ndan gelen sens\u00f6r verileri gibi durumlar SSE i\u00e7in idealdir.<\/p>\n<p>SSE, HTTP\/1.1 protokol\u00fc \u00fczerinden \u00e7al\u0131\u015f\u0131r ve bu da onu mevcut web altyap\u0131lar\u0131yla son derece uyumlu hale getirir. Di\u011fer bir deyi\u015fle, \u00f6zel bir protokol veya karma\u015f\u0131k bir el s\u0131k\u0131\u015fma mekanizmas\u0131na ihtiya\u00e7 duymazs\u0131n\u0131z; basit bir HTTP ba\u011flant\u0131s\u0131 yeterlidir. Sunucu, <code>Content-Type: text\/event-stream<\/code> ba\u015fl\u0131\u011f\u0131 ile yan\u0131t vererek istemciye bir olay ak\u0131\u015f\u0131 g\u00f6nderdi\u011fini belirtir. \u0130stemci taraf\u0131nda ise, JavaScript&#8217;in yerle\u015fik <code>EventSource<\/code> API&#8217;si bu ak\u0131\u015f\u0131 kolayca t\u00fcketebilir. SSE&#8217;nin sundu\u011fu otomatik yeniden ba\u011flanma (reconnection) mekanizmas\u0131, a\u011f kesintileri veya sunucu yeniden ba\u015flatmalar\u0131 gibi durumlarda istemcinin ba\u011flant\u0131y\u0131 otomatik olarak yeniden kurmas\u0131n\u0131 sa\u011flar, b\u00f6ylece veri ak\u0131\u015f\u0131n\u0131n s\u00fcreklili\u011fi garanti alt\u0131na al\u0131n\u0131r. Bu \u00f6zellik, geli\u015ftiricilerin hata y\u00f6netimi ve ba\u011flant\u0131 istikrar\u0131 konusunda daha az endi\u015felenmesini sa\u011flar.<\/p>\n<p>Peki, SSE&#8217;yi WebSockets veya d\u00fczenli polling ile kar\u015f\u0131la\u015ft\u0131rd\u0131\u011f\u0131m\u0131zda farklar nelerdir?<\/p>\n<ul>\n<li><strong>Polling (S\u00fcrekli Sorgulama):<\/strong> \u0130stemci, belirli aral\u0131klarla sunucuya yeni veri olup olmad\u0131\u011f\u0131n\u0131 sorar. Bu, sunucu \u00fczerinde gereksiz y\u00fck olu\u015fturur ve verinin an\u0131nda de\u011fil, bir sonraki sorgulama an\u0131nda gelmesine neden olur. Gecikme ya\u015fanabilir ve kaynak t\u00fcketimi y\u00fcksektir.<\/li>\n<li><strong>WebSockets:<\/strong> \u0130stemci ve sunucu aras\u0131nda \u00e7ift y\u00f6nl\u00fc, tam dubleks bir ileti\u015fim kanal\u0131 kurar. Hem istemci hem de sunucu birbirine istedi\u011fi zaman veri g\u00f6nderebilir. Sohbet uygulamalar\u0131 veya \u00e7evrimi\u00e7i oyunlar gibi s\u00fcrekli iki y\u00f6nl\u00fc ileti\u015fimin gerekli oldu\u011fu durumlarda idealdir. Ancak, daha karma\u015f\u0131k bir protokol ve sunucu taraf\u0131nda daha fazla kaynak y\u00f6netimi gerektirebilir.<\/li>\n<li><strong>Server-Sent Events (SSE):<\/strong> Tek y\u00f6nl\u00fc bir ileti\u015fim kanal\u0131d\u0131r; sunucudan istemciye veri ak\u0131\u015f\u0131 sa\u011flar. WebSockets kadar karma\u015f\u0131k de\u011fildir, HTTP \u00fczerinden \u00e7al\u0131\u015f\u0131r ve otomatik yeniden ba\u011flanma \u00f6zelliklerine sahiptir. \u0130stemcinin sunucuya s\u0131k s\u0131k veri g\u00f6ndermesine gerek olmayan durumlarda WebSockets&#8217;a g\u00f6re daha hafif ve basit bir \u00e7\u00f6z\u00fcmd\u00fcr.<\/li>\n<\/ul>\n<p>  \u00d6zetle, SSE, ger\u00e7ek zamanl\u0131 veri ak\u0131\u015f\u0131n\u0131 basitlik, verimlilik ve mevcut web teknolojileriyle uyum i\u00e7inde sunarak, bir\u00e7ok yayg\u0131n senaryo i\u00e7in m\u00fckemmel bir denge noktas\u0131 sa\u011flar. \u00d6zellikle, bir borsa takip uygulamas\u0131 d\u00fc\u015f\u00fcn\u00fcn; hisse senedi fiyatlar\u0131 s\u00fcrekli de\u011fi\u015fir ve kullan\u0131c\u0131n\u0131n bu de\u011fi\u015fimleri an\u0131nda g\u00f6rmesi gerekir. Kullan\u0131c\u0131lar\u0131n fiyatlar\u0131 sunucuya g\u00f6ndermesine gerek olmad\u0131\u011f\u0131 i\u00e7in, SSE bu t\u00fcr bir uygulama i\u00e7in WebSockets&#8217;tan daha uygun ve daha az kaynak t\u00fcketen bir \u00e7\u00f6z\u00fcm olacakt\u0131r. Ballerina&#8217;n\u0131n e\u015fzamanl\u0131l\u0131k yetenekleriyle birle\u015fti\u011finde, SSE&#8217;nin sundu\u011fu bu avantajlar daha da belirginle\u015fir ve ger\u00e7ek zamanl\u0131 sistemler geli\u015ftirmek i\u00e7in g\u00fc\u00e7l\u00fc bir ara\u00e7 haline gelir.<\/p>\n<h2>Ballerina ve Ger\u00e7ek Zamanl\u0131 Ak\u0131\u015f: Neden Ballerina SSE \u0130\u00e7in \u0130deal?<\/h2>\n<p>Ballerina, da\u011f\u0131t\u0131k sistemler ve a\u011f odakl\u0131 uygulamalar geli\u015ftirmek i\u00e7in tasarlanm\u0131\u015f modern bir programlama dilidir. Konkurenslik (e\u015fzamanl\u0131l\u0131k) ve a\u011f ileti\u015fimi, dilin \u00e7ekirde\u011finde yer al\u0131r, bu da onu ger\u00e7ek zamanl\u0131 veri ak\u0131\u015f\u0131 ve \u00f6zellikle Server-Sent Events (SSE) gibi teknolojiler i\u00e7in son derece uygun hale getirir. Ballerina&#8217;n\u0131n ak\u0131\u015fkan s\u00f6zdizimi ve yerle\u015fik a\u011f yap\u0131lar\u0131, karma\u015f\u0131k ger\u00e7ek zamanl\u0131 senaryolar\u0131 bile \u015fa\u015f\u0131rt\u0131c\u0131 derecede basit ve okunabilir bir \u015fekilde ifade etmenize olanak tan\u0131r. Dilin temelinde yer alan <code>service<\/code> ve <code>resource<\/code> kavramlar\u0131, HTTP servislerini tan\u0131mlamay\u0131 do\u011fal ve sezgisel bir s\u00fcre\u00e7 haline getirir. Bu yap\u0131sal yakla\u015f\u0131m, bir SSE sunucusunun nas\u0131l davranaca\u011f\u0131n\u0131 a\u00e7\u0131k\u00e7a belirtmeye yard\u0131mc\u0131 olurken, ayn\u0131 zamanda hata denetimi ve kaynak y\u00f6netimini de basitle\u015ftirir. Ayr\u0131ca, Ballerina&#8217;n\u0131n yerle\u015fik destekledi\u011fi konkurens modelleri (\u00f6rne\u011fin, <code>worker<\/code>&#8216;lar ve <code>strand<\/code>&#8216;lar), birden fazla istemciye ayn\u0131 anda veri ak\u0131\u015f\u0131 sa\u011flarken bile performans sorunlar\u0131 ya\u015famaman\u0131z\u0131 temin eder. Her bir istemci ba\u011flant\u0131s\u0131, kendi hafif i\u015f par\u00e7ac\u0131\u011f\u0131nda ele al\u0131nabilir, b\u00f6ylece sunucunun \u00f6l\u00e7eklenebilirli\u011fi art\u0131r\u0131l\u0131r. Bu \u00f6zellikler, \u00f6zellikle \u00e7ok say\u0131da e\u015fzamanl\u0131 ba\u011flant\u0131n\u0131n y\u00f6netilmesi gereken ger\u00e7ek zamanl\u0131 veri ak\u0131\u015f\u0131 uygulamalar\u0131 i\u00e7in kritik \u00f6neme sahiptir.<\/p>\n<p>Ballerina&#8217;n\u0131n a\u011f ileti\u015fimi konusundaki do\u011fal yetenekleri, SSE gibi HTTP tabanl\u0131 ak\u0131\u015f protokollerini uygulamay\u0131 \u00e7ok daha kolayla\u015ft\u0131r\u0131r. Ballerina&#8217;da bir HTTP servisi tan\u0131mlamak ve bir <code>resource<\/code> \u00fczerinden veri ak\u0131\u015f\u0131 sa\u011flamak i\u00e7in \u00f6zel k\u00fct\u00fcphanelere veya karma\u015f\u0131k konfig\u00fcrasyonlara ihtiya\u00e7 duymazs\u0131n\u0131z. Dilin kendisi, bu t\u00fcr senaryolar i\u00e7in gerekli yap\u0131 ta\u015flar\u0131n\u0131 zaten sunar. \u00d6rne\u011fin, bir IoT projesinde ak\u0131ll\u0131 ev sens\u00f6rlerinden gelen s\u0131cakl\u0131k, nem veya hareket verilerini anl\u0131k olarak bir mobil uygulamaya veya web aray\u00fcz\u00fcne aktard\u0131\u011f\u0131n\u0131z\u0131 d\u00fc\u015f\u00fcn\u00fcn. Her sens\u00f6r verisi geldi\u011finde, sunucunuz bu veriyi ba\u011fl\u0131 istemcilere SSE arac\u0131l\u0131\u011f\u0131yla iletebilir. Ballerina&#8217;n\u0131n e\u015fzamanl\u0131l\u0131k ve olay odakl\u0131 yap\u0131s\u0131 sayesinde, sens\u00f6rlerden gelen birden fazla veri ak\u0131\u015f\u0131n\u0131 ayn\u0131 anda i\u015fleyebilir ve bunlar\u0131 ba\u011fl\u0131 t\u00fcm istemcilere verimli bir \u015fekilde da\u011f\u0131tabilirsiniz. Bu, Ballerina&#8217;n\u0131n hem geli\u015ftirme kolayl\u0131\u011f\u0131 hem de \u00e7al\u0131\u015fma zaman\u0131 verimlili\u011fi a\u00e7\u0131s\u0131ndan SSE i\u00e7in neden ideal bir se\u00e7im oldu\u011funu g\u00f6sterir.<\/p>\n<p>Dilin sa\u011flad\u0131\u011f\u0131 basitlik, geli\u015ftiricilerin i\u015f mant\u0131\u011f\u0131na odaklanmas\u0131na ve a\u011f katman\u0131n\u0131n karma\u015f\u0131kl\u0131\u011f\u0131yla bo\u011fu\u015fmak yerine ger\u00e7ek zamanl\u0131 veri ak\u0131\u015f\u0131 senaryolar\u0131n\u0131 h\u0131zla hayata ge\u00e7irmesine olanak tan\u0131r. Ayr\u0131ca, Ballerina&#8217;n\u0131n g\u00fc\u00e7l\u00fc t\u00fcr sistemi, derleme zaman\u0131nda olas\u0131 hatalar\u0131 yakalamaya yard\u0131mc\u0131 olur, bu da daha g\u00fcvenilir ve bak\u0131m\u0131 kolay kod yazman\u0131z\u0131 sa\u011flar. \u00d6zetle, Ballerina&#8217;n\u0131n tasarlanm\u0131\u015f oldu\u011fu temel prensipler \u2013 a\u011f odakl\u0131l\u0131k, e\u015fzamanl\u0131l\u0131k ve basitlik \u2013 onu Server-Sent Events kullanarak ger\u00e7ek zamanl\u0131 uygulamalar olu\u015fturmak i\u00e7in m\u00fckemmel bir ara\u00e7 haline getirir. Geli\u015ftiriciler, daha az kod yazarak ve daha az karma\u015f\u0131kl\u0131kla, y\u00fcksek performansl\u0131 ve \u00f6l\u00e7eklenebilir veri ak\u0131\u015f\u0131 servisleri geli\u015ftirebilirler.<\/p>\n<h2>Ballerina ile \u0130lk SSE Sunucusu Nas\u0131l Yaz\u0131l\u0131r? Ad\u0131m Ad\u0131m Rehber<\/h2>\n<p>Ballerina ile bir Server-Sent Events (SSE) sunucusu olu\u015fturmak olduk\u00e7a basittir. \u0130\u015fin \u00f6z\u00fc, bir HTTP servisi tan\u0131mlamak ve belirli bir kayna\u011fa yap\u0131lan istekleri <code>text\/event-stream<\/code> i\u00e7erik t\u00fcr\u00fcyle yan\u0131tlayarak olay ak\u0131\u015f\u0131 sa\u011flamakt\u0131r. Bu b\u00f6l\u00fcmde, ad\u0131m ad\u0131m bir Ballerina SSE sunucusu olu\u015fturacak ve temel \u00e7al\u0131\u015fma prensiplerini inceleyece\u011fiz. \u0130lk olarak, Ballerina projemizi olu\u015fturarak ba\u015flayal\u0131m. Ard\u0131ndan, bir HTTP servisi i\u00e7inde SSE ak\u0131\u015f\u0131 sa\u011flayacak bir kaynak (resource) fonksiyonu tan\u0131mlayaca\u011f\u0131z. Bu fonksiyon, istemciye s\u00fcrekli olarak veri g\u00f6nderecek \u015fekilde tasarlanacakt\u0131r. Verileri g\u00f6ndermek i\u00e7in <code>http:Caller<\/code> nesnesini kullanaca\u011f\u0131z, bu nesne Ballerina&#8217;n\u0131n HTTP servisleriyle etkile\u015fim kurmak i\u00e7in sa\u011flad\u0131\u011f\u0131 bir ara\u00e7t\u0131r. Ayr\u0131ca, Ballerina&#8217;n\u0131n ak\u0131\u015f (stream) yetenekleri sayesinde, olaylar\u0131n istemciye nas\u0131l g\u00f6nderilece\u011fini kontrol etmek de olduk\u00e7a kolayd\u0131r. Veri ak\u0131\u015f\u0131n\u0131n do\u011fru \u015fekilde \u00e7al\u0131\u015fmas\u0131 i\u00e7in, HTTP yan\u0131t ba\u015fl\u0131klar\u0131nda <code>Content-Type<\/code> olarak <code>text\/event-stream<\/code> ayarland\u0131\u011f\u0131ndan emin olmal\u0131y\u0131z.<\/p>\n<p>A\u015fa\u011f\u0131da, Ballerina ile basit bir SSE sunucusu \u00f6rne\u011fi bulunmaktad\u0131r. Bu \u00f6rnek, her saniye artan bir say\u0131 g\u00f6nderen bir ak\u0131\u015f olu\u015fturur.<\/p>\n<pre><code>\nimport ballerina\/http;\nimport ballerina\/io;\nimport ballerina\/time;\n\n\/\/ HTTP servisimizi tan\u0131ml\u0131yoruz. Bu servis, 9090 portundan gelen istekleri dinleyecek.\nservice \/events on new http:Listener(9090) {\n\n    \/\/ '\/stream' yoluna gelen GET isteklerini kar\u015f\u0131layan bir kaynak fonksiyonu.\n    resource function get stream(http:Caller caller) returns error? {\n        \/\/ SSE i\u00e7in Content-Type ba\u015fl\u0131\u011f\u0131n\u0131 ayarl\u0131yoruz.\n        check caller->addHeader(\"Content-Type\", \"text\/event-stream\");\n        check caller->addHeader(\"Cache-Control\", \"no-cache\");\n        check caller->addHeader(\"Connection\", \"keep-alive\");\n\n        io:println(\"Yeni bir SSE istemcisi ba\u011fland\u0131.\");\n\n        \/\/ Olay ID'si i\u00e7in bir saya\u00e7 ba\u015flat\u0131yoruz.\n        int eventId = 0;\n\n        \/\/ S\u00fcrekli olarak veri g\u00f6nderecek bir d\u00f6ng\u00fc ba\u015flat\u0131yoruz.\n        \/\/ Bu d\u00f6ng\u00fc, istemci ba\u011flant\u0131s\u0131 kesilene kadar devam eder.\n        while (true) {\n            \/\/ Bir mesaj olu\u015fturuyoruz. SSE format\u0131nda event, id ve data alanlar\u0131n\u0131 kullan\u0131yoruz.\n            string data = string <code>data: {\"message\": \"Merhaba, bu ${eventId}. olay!\", \"timestamp\": \"${time:utcNow().toString()}\"}\\n<\/code>;\n            string eventType = <code>event: message\\n<\/code>;\n            string id = <code>id: ${eventId}\\n<\/code>;\n            string retry = <code>retry: 1000\\n<\/code>; \/\/ \u0130stemcinin ba\u011flant\u0131 koptu\u011funda ne kadar s\u00fcre sonra yeniden deneyece\u011fini belirtir (ms).\n\n            \/\/ Olu\u015fturulan mesaj\u0131 istemciye g\u00f6nderiyoruz.\n            error? result = caller->writeStream({\n                content: eventType + id + retry + data + \"\\n\" \/\/ Her olaydan sonra bir bo\u015f sat\u0131r olmas\u0131 \u00f6nemlidir.\n            });\n\n            \/\/ E\u011fer bir hata olu\u015fursa (\u00f6rne\u011fin istemci ba\u011flant\u0131y\u0131 kapat\u0131rsa), d\u00f6ng\u00fcden \u00e7\u0131k\u0131yoruz.\n            if (result is error) {\n                io:println(\"\u0130stemci ba\u011flant\u0131s\u0131 kesildi veya bir hata olu\u015ftu: \" + result.message());\n                break;\n            }\n\n            eventId += 1; \/\/ Olay ID'sini art\u0131r\u0131yoruz.\n            time:sleep(1); \/\/ 1 saniye bekliyoruz.\n        }\n        io:println(\"SSE ak\u0131\u015f\u0131 sona erdi.\");\n        return;\n    }\n}\n  <\/pre>\n<p><\/code><\/p>\n<p>Yukar\u0131daki kod blo\u011funda g\u00f6rd\u00fc\u011f\u00fcn\u00fcz gibi, Ballerina'da bir SSE ak\u0131\u015f\u0131 olu\u015fturmak i\u00e7in:<\/p>\n<ol>\n<li><code>http:Listener<\/code> kullanarak bir HTTP servisi ba\u015flat\u0131yoruz.<\/li>\n<li><code>resource function get stream(http:Caller caller)<\/code> ile <code>\/stream<\/code> yoluna gelen GET isteklerini dinleyen bir kaynak tan\u0131ml\u0131yoruz. Bu fonksiyona gelen <code>caller<\/code> nesnesi, istemciyle ileti\u015fim kurmak i\u00e7in kullan\u0131l\u0131r.<\/li>\n<li><code>caller->addHeader(...)<\/code> metoduyla SSE i\u00e7in gerekli olan <code>Content-Type: text\/event-stream<\/code> ve di\u011fer ilgili HTTP ba\u015fl\u0131klar\u0131n\u0131 (<code>Cache-Control<\/code>, <code>Connection<\/code>) ekliyoruz. Bu ba\u015fl\u0131klar, taray\u0131c\u0131ya bu ba\u011flant\u0131n\u0131n bir olay ak\u0131\u015f\u0131 oldu\u011funu bildirir.<\/li>\n<li>Bir <code>while(true)<\/code> d\u00f6ng\u00fcs\u00fc i\u00e7inde, belirli aral\u0131klarla (bu \u00f6rnekte 1 saniye) yeni olaylar olu\u015fturuyoruz.<\/li>\n<li>Her olay i\u00e7in, SSE'nin standart format\u0131na uygun olarak <code>event:<\/code>, <code>id:<\/code>, <code>data:<\/code> ve iste\u011fe ba\u011fl\u0131 olarak <code>retry:<\/code> alanlar\u0131n\u0131 i\u00e7eren bir string olu\u015fturuyoruz. Unutmay\u0131n, her olay blo\u011fu bir veya daha fazla bo\u015f sat\u0131rla bitmelidir.<\/li>\n<li><code>caller->writeStream(...)<\/code> metodunu kullanarak olu\u015fturulan bu string'i istemciye g\u00f6nderiyoruz. Bu metod, ba\u011flant\u0131 a\u00e7\u0131k oldu\u011fu s\u00fcrece veriyi ak\u0131\u015f halinde g\u00f6ndermeye devam eder.<\/li>\n<li><code>writeStream<\/code>'den gelen hata kontrol\u00fc, istemcinin ba\u011flant\u0131y\u0131 kapatmas\u0131 gibi durumlar\u0131 yakalamak ve sunucu taraf\u0131nda temiz bir \u015fekilde \u00e7\u0131k\u0131\u015f yapmak i\u00e7in \u00f6nemlidir.<\/li>\n<\/ol>\n<p>  Bu basit yap\u0131, Ballerina'n\u0131n SSE ak\u0131\u015flar\u0131n\u0131 ne kadar kolay y\u00f6netebildi\u011fini g\u00f6stermektedir. Geli\u015ftiriciler, bu temeli alarak karma\u015f\u0131k ger\u00e7ek zamanl\u0131 veri yay\u0131nlama senaryolar\u0131n\u0131 kolayca in\u015fa edebilirler. Ballerina'n\u0131n g\u00fc\u00e7l\u00fc konkurensi ve a\u011f soyutlamalar\u0131 sayesinde, ayn\u0131 anda binlerce istemciye hizmet verebilen robust SSE servisleri olu\u015fturmak m\u00fcmk\u00fcnd\u00fcr.<\/p>\n<h3>Bir SSE \u0130stemcisi Nas\u0131l Olu\u015fturulur? Taray\u0131c\u0131 ve JavaScript Kullan\u0131m\u0131<\/h3>\n<p>Ballerina ile bir SSE sunucusu olu\u015fturdu\u011fumuza g\u00f6re, bu sunucudan gelen verileri t\u00fcketmek i\u00e7in bir istemciye ihtiyac\u0131m\u0131z var. Web taray\u0131c\u0131lar\u0131, JavaScript'in yerle\u015fik <code>EventSource<\/code> API'si sayesinde SSE ak\u0131\u015flar\u0131n\u0131 kolayca dinleyebilir. <code>EventSource<\/code>, tek y\u00f6nl\u00fc bir ba\u011flant\u0131 kurar, gelen olaylar\u0131 otomatik olarak ayr\u0131\u015ft\u0131r\u0131r ve a\u011f kesintilerinde yeniden ba\u011flanma (reconnection) denemeleri yapar. Bu b\u00f6l\u00fcm, basit bir HTML ve JavaScript istemcisi ile Ballerina SSE sunucumuzdan gelen verileri nas\u0131l alaca\u011f\u0131m\u0131z\u0131 g\u00f6sterecektir.<\/p>\n<pre><code>\n<!DOCTYPE html>\n<html lang=\"tr\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>Ballerina SSE \u0130stemcisi<\/title>\n    <style>\n        body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 20px; background-color: #f4f7f6; color: #333; }\n        .container { max-width: 800px; margin: 0 auto; background-color: #fff; padding: 25px; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.08); }\n        h1 { color: #007bff; text-align: center; margin-bottom: 30px; }\n        #messages { border: 1px solid #ddd; padding: 15px; min-height: 200px; max-height: 400px; overflow-y: auto; background-color: #e9ecef; border-radius: 5px; }\n        .message-item { background-color: #ffffff; margin-bottom: 8px; padding: 10px; border-radius: 4px; box-shadow: 0 2px 4px rgba(0,0,0,0.05); }\n        .message-item strong { color: #28a745; }\n        .status { text-align: center; margin-top: 20px; font-weight: bold; color: #6c757d; }\n        .status.connected { color: #28a745; }\n        .status.disconnected { color: #dc3545; }\n\n        \/* Mobil uyumluluk i\u00e7in medya sorgular\u0131 *\/\n        @media (max-width: 768px) {\n            .container {\n                margin: 10px;\n                padding: 15px;\n            }\n            h1 {\n                font-size: 1.8em;\n            }\n            #messages {\n                min-height: 150px;\n            }\n        }\n        @media (max-width: 480px) {\n            body {\n                margin: 10px;\n            }\n            h1 {\n                font-size: 1.5em;\n            }\n        }\n    <\/style>\n<\/head>\n<body>\n    <div class=\"container\">\n        <h1>Ballerina SSE Canl\u0131 Veri Ak\u0131\u015f\u0131<\/h1>\n        <div id=\"status\" class=\"status disconnected\">Durum: Ba\u011flant\u0131 Kesik<\/div>\n        <div id=\"messages\">\n            <!-- Gelen mesajlar buraya eklenecek -->\n        <\/div>\n    <\/div>\n\n    <script>\n        const eventSource = new EventSource('http:\/\/localhost:9090\/events\/stream');\n        const messagesDiv = document.getElementById('messages');\n        const statusDiv = document.getElementById('status');\n\n        eventSource.onopen = function() {\n            console.log('SSE ba\u011flant\u0131s\u0131 a\u00e7\u0131ld\u0131.');\n            statusDiv.textContent = 'Durum: Ba\u011fl\u0131';\n            statusDiv.classList.remove('disconnected');\n            statusDiv.classList.add('connected');\n        };\n\n        \/\/ 'message' event'ini dinliyoruz (varsay\u0131lan event tipi)\n        eventSource.onmessage = function(event) {\n            console.log('Gelen mesaj:', event);\n            try {\n                const data = JSON.parse(event.data);\n                const messageElement = document.createElement('div');\n                messageElement.classList.add('message-item');\n                messageElement.innerHTML = <code><strong>ID: ${event.lastEventId}<\/strong> <br> Mesaj: ${data.message} <br> Zaman: ${data.timestamp}<\/code>;\n                messagesDiv.prepend(messageElement); \/\/ En yeni mesaj\u0131 en \u00fcste ekle\n                if (messagesDiv.children.length > 50) { \/\/ Eski mesajlar\u0131 temizle\n                    messagesDiv.removeChild(messagesDiv.lastChild);\n                }\n            } catch (e) {\n                console.error('Mesaj ayr\u0131\u015ft\u0131rma hatas\u0131:', e);\n                const messageElement = document.createElement('div');\n                messageElement.classList.add('message-item');\n                messageElement.textContent = <code>Hata: ${event.data}<\/code>;\n                messagesDiv.prepend(messageElement);\n            }\n        };\n\n        \/\/ Ba\u011flant\u0131 hatalar\u0131n\u0131 dinliyoruz\n        eventSource.onerror = function(event) {\n            console.error('SSE ba\u011flant\u0131 hatas\u0131:', event);\n            statusDiv.textContent = 'Durum: Ba\u011flant\u0131 Kesik (Yeniden Deneniyor...)';\n            statusDiv.classList.remove('connected');\n            statusDiv.classList.add('disconnected');\n            \/\/ EventSource otomatik olarak yeniden ba\u011flanmaya \u00e7al\u0131\u015f\u0131r, bu y\u00fczden manuel bir \u015fey yapmaya gerek yok.\n        };\n\n        \/\/ \u00d6zel bir event tipi tan\u0131mlad\u0131ysak (\u00f6rne\u011fin 'customEvent'), onu dinlemek i\u00e7in:\n        \/\/ eventSource.addEventListener('customEvent', function(event) {\n        \/\/     console.log('Gelen \u00f6zel olay:', event.data);\n        \/\/ });\n    <\/script>\n<\/body>\n<\/html>\n  <\/pre>\n<p><\/code><\/p>\n<p>Bu istemci kodunda \u00f6nemli noktalar \u015funlard\u0131r:<\/p>\n<ul>\n<li><code>new EventSource('http:\/\/localhost:9090\/events\/stream')<\/code>: Bu sat\u0131r, Ballerina sunucumuzun yay\u0131n yapt\u0131\u011f\u0131 SSE ak\u0131\u015f\u0131na bir ba\u011flant\u0131 kurar. URL'nin do\u011fru oldu\u011fundan emin olun.<\/li>\n<li><code>eventSource.onopen<\/code>: Ba\u011flant\u0131 ba\u015far\u0131yla kuruldu\u011funda tetiklenir. Burada ba\u011flant\u0131 durumunu g\u00fcncelleyebiliriz.<\/li>\n<li><code>eventSource.onmessage<\/code>: Sunucudan yeni bir 'message' olay\u0131 geldi\u011finde tetiklenir. <code>event.data<\/code> \u00f6zelli\u011fi, sunucudan g\u00f6nderilen veriyi i\u00e7erir. Bizim \u00f6rne\u011fimizde JSON format\u0131nda bir string g\u00f6nderdi\u011fimiz i\u00e7in <code>JSON.parse()<\/code> kullanarak veriyi ayr\u0131\u015ft\u0131r\u0131yoruz. <code>event.lastEventId<\/code> ise, sunucudan gelen son olay\u0131n kimli\u011fini i\u00e7erir; bu, yeniden ba\u011flanma senaryolar\u0131nda kay\u0131p olaylar\u0131 talep etmek i\u00e7in kullan\u0131labilir.<\/li>\n<li><code>eventSource.onerror<\/code>: Ba\u011flant\u0131 hatas\u0131 olu\u015ftu\u011funda tetiklenir. <code>EventSource<\/code> otomatik olarak yeniden ba\u011flanmaya \u00e7al\u0131\u015ft\u0131\u011f\u0131 i\u00e7in, bu olay genellikle bilgi ama\u00e7l\u0131d\u0131r ve kullan\u0131c\u0131n\u0131n durumdan haberdar olmas\u0131n\u0131 sa\u011flar. Sunucu taraf\u0131nda <code>retry:<\/code> alan\u0131n\u0131 ayarlayarak istemcinin yeniden ba\u011flanma aral\u0131\u011f\u0131n\u0131 belirleyebilirsiniz.<\/li>\n<li><code>eventSource.addEventListener('customEvent', ...)<\/code>: E\u011fer sunucunuz varsay\u0131lan 'message' eventi d\u0131\u015f\u0131nda \u00f6zel event tipleri (<code>event: customEvent\\n<\/code> gibi) g\u00f6nderiyorsa, bunlar\u0131 <code>addEventListener<\/code> ile dinleyebilirsiniz.<\/li>\n<\/ul>\n<p>  Bu istemci, Ballerina sunucunuzla sorunsuz bir \u015fekilde entegre olur ve ger\u00e7ek zamanl\u0131 veri ak\u0131\u015f\u0131n\u0131z\u0131 web taray\u0131c\u0131n\u0131zda g\u00f6r\u00fcnt\u00fclemenizi sa\u011flar. CSS kodlar\u0131ndaki medya sorgular\u0131, istemci uygulamas\u0131n\u0131n farkl\u0131 ekran boyutlar\u0131na uyum sa\u011flayarak mobil cihazlarda da kullan\u0131labilir olmas\u0131n\u0131 sa\u011flar. Bu sayede, hem masa\u00fcst\u00fc hem de mobil kullan\u0131c\u0131lar i\u00e7in tutarl\u0131 bir deneyim sunulabilir. Bu, geli\u015ftirme s\u00fcrecini basitle\u015ftirirken, ayn\u0131 zamanda kullan\u0131c\u0131 deneyimini de \u00f6nemli \u00f6l\u00e7\u00fcde iyile\u015ftirir.<\/p>\n<h2>Geli\u015fmi\u015f SSE Kullan\u0131m\u0131 ve En \u0130yi Uygulamalar: Performans ve G\u00fcvenlik<\/h2>\n<p>Server-Sent Events (SSE) temellerini anlad\u0131ktan sonra, daha sa\u011flam, performansl\u0131 ve g\u00fcvenli uygulamalar geli\u015ftirmek i\u00e7in baz\u0131 ileri d\u00fczey konulara ve en iyi uygulamalara de\u011finmek \u00f6nemlidir. Bu b\u00f6l\u00fcmde, Ballerina ile SSE kullan\u0131rken dikkat etmeniz gereken baz\u0131 kritik noktalar\u0131 ele alaca\u011f\u0131z: ba\u011flant\u0131 y\u00f6netimi, yeniden ba\u011flanma stratejileri, olay kimliklerinin (ID) kullan\u0131m\u0131, g\u00fcvenlik hususlar\u0131 ve hata y\u00f6netimi.<\/p>\n<h3>Ba\u011flant\u0131 Y\u00f6netimi ve Yeniden Ba\u011flanma<\/h3>\n<p>SSE'nin otomatik yeniden ba\u011flanma \u00f6zelli\u011fi b\u00fcy\u00fck bir avantajd\u0131r, ancak sunucu taraf\u0131nda bu ba\u011flant\u0131lar\u0131 y\u00f6netmek de \u00f6nemlidir. Ballerina taraf\u0131nda, her bir SSE ba\u011flant\u0131s\u0131 bir HTTP ak\u0131\u015f\u0131 olarak ele al\u0131n\u0131r ve <code>http:Caller<\/code> objesi \u00fczerinden y\u00f6netilir. Sunucunuzda, ba\u011fl\u0131 istemcileri izlemek ve gerekti\u011finde ba\u011flant\u0131lar\u0131 kapatmak i\u00e7in bir mekanizma olu\u015fturman\u0131z gerekebilir. \u00d6rne\u011fin, bir kullan\u0131c\u0131n\u0131n oturumu sona erdi\u011finde veya belirli bir olaya art\u0131k abone olmak istemedi\u011finde, sunucu bu ba\u011flant\u0131y\u0131 kapatabilmelidir. \u0130stemci taraf\u0131nda, <code>EventSource<\/code> API'si, sunucudan gelen <code>retry:<\/code> alan\u0131 ile otomatik yeniden ba\u011flanma aral\u0131\u011f\u0131n\u0131 yap\u0131land\u0131rman\u0131za olanak tan\u0131r. Sunucu olarak bu de\u011feri mant\u0131kl\u0131 bir \u015fekilde ayarlamak, a\u011f kesintilerinde istemcinin \u00e7ok s\u0131k veya \u00e7ok seyrek yeniden ba\u011flanmaya \u00e7al\u0131\u015fmas\u0131n\u0131 \u00f6nler.<\/p>\n<pre><code>\n\/\/ Ballerina sunucusunda aktif SSE ba\u011flant\u0131lar\u0131n\u0131 tutan bir Map veya Queue d\u00fc\u015f\u00fcnebiliriz.\n\/\/ \u00d6rnek: map<http:Caller> activeSseConnections = {};\n\/\/ Bir istemci ba\u011fland\u0131\u011f\u0131nda activeSseConnections[clientId] = caller; olarak ekleyebiliriz.\n\/\/ \u0130stemci ayr\u0131ld\u0131\u011f\u0131nda veya bir hata olu\u015ftu\u011funda map'ten kald\u0131rabiliriz.\n\/\/ Bu sayede belirli bir istemciye \u00f6zel mesaj g\u00f6nderme veya t\u00fcm ba\u011flant\u0131lar\u0131 y\u00f6netme esnekli\u011fi sa\u011flan\u0131r.\n  <\/pre>\n<p><\/code><\/p>\n<h3>Olay Kimliklerinin (ID) ve Kay\u0131p Olaylar\u0131n Telafisi<\/h3>\n<p>SSE protokol\u00fc, her olaya bir <code>id:<\/code> alan\u0131 eklemenize olanak tan\u0131r. Bu kimlikler, istemcinin bir ba\u011flant\u0131 kesintisi sonras\u0131 hangi olaydan kald\u0131\u011f\u0131n\u0131 bilmesini sa\u011flar. Yeniden ba\u011fland\u0131\u011f\u0131nda, <code>EventSource<\/code> nesnesi son al\u0131nan olay\u0131n ID'sini HTTP iste\u011finin <code>Last-Event-ID<\/code> ba\u015fl\u0131\u011f\u0131nda sunucuya g\u00f6nderir. Ballerina sunucunuz, bu ba\u015fl\u0131\u011f\u0131 kontrol ederek ve buna g\u00f6re uygun olaylar\u0131 (yani, istemcinin ka\u00e7\u0131rd\u0131\u011f\u0131 olaylar\u0131) g\u00f6ndererek kay\u0131p olaylar\u0131 telafi edebilir. Bu, veri b\u00fct\u00fcnl\u00fc\u011f\u00fcn\u00fc sa\u011flamak ve kullan\u0131c\u0131n\u0131n hi\u00e7bir \u00f6nemli g\u00fcncellemeyi ka\u00e7\u0131rmamas\u0131n\u0131 sa\u011flamak i\u00e7in kritik bir \u00f6zelliktir. Bu \u00f6zellik, \u00f6zellikle finansal uygulamalar veya kritik bildirim sistemleri gibi verinin anl\u0131k ve eksiksiz olmas\u0131n\u0131n zorunlu oldu\u011fu senaryolarda hayat kurtar\u0131c\u0131d\u0131r.<\/p>\n<pre><code>\n\/\/ Ballerina resource fonksiyonunda 'Last-Event-ID' ba\u015fl\u0131\u011f\u0131n\u0131 kontrol etme \u00f6rne\u011fi\nresource function get stream(http:Caller caller, http:Request request) returns error? {\n    \/\/ ... di\u011fer ba\u015fl\u0131k ayarlar\u0131 ...\n\n    string? lastEventId = request.getHeader(\"Last-Event-ID\");\n    int startId = 0;\n    if lastEventId is string {\n        \/\/ Son olay ID'sini bir int'e d\u00f6n\u00fc\u015ft\u00fcr ve ondan sonraki olaylar\u0131 g\u00f6ndermeye ba\u015fla.\n        \/\/ Hata durumunda (ge\u00e7ersiz ID) 0'dan ba\u015fla.\n        startId = lastEventId.toInt().orElse(0) + 1; \n        io:println(\"\u0130stemci Last-Event-ID: \" + lastEventId + \", \" + startId + \" id'den devam edecek.\");\n    }\n\n    \/\/ ... ak\u0131\u015f d\u00f6ng\u00fcs\u00fcnde 'eventId' yerine 'startId'den ba\u015fla ...\n    int currentEventId = startId;\n    while (true) {\n        \/\/ ... olaylar\u0131 currentEventId ile olu\u015ftur ve g\u00f6nder ...\n        currentEventId += 1;\n        \/\/ ...\n    }\n}\n  <\/pre>\n<p><\/code><\/p>\n<h3>G\u00fcvenlik: Kimlik Do\u011frulama ve Yetkilendirme<\/h3>\n<p>SSE ak\u0131\u015flar\u0131 da di\u011fer HTTP kaynaklar\u0131 gibi g\u00fcvenlik alt\u0131na al\u0131nmal\u0131d\u0131r. Public olmayan veriler i\u00e7in, istemcinin SSE ak\u0131\u015f\u0131na abone olmadan \u00f6nce kimlik do\u011frulamadan ge\u00e7mesi ve yetkilendirilmesi gerekir. Bu, genellikle ilk HTTP iste\u011fi s\u0131ras\u0131nda bir oturum \u00e7erezi (session cookie) veya JWT (JSON Web Token) tabanl\u0131 bir <code>Authorization<\/code> ba\u015fl\u0131\u011f\u0131 kullan\u0131larak yap\u0131l\u0131r. Ballerina, HTTP servisleri i\u00e7in yerle\u015fik kimlik do\u011frulama ve yetkilendirme mekanizmalar\u0131 sunar. Kaynak fonksiyonunuzun ba\u015f\u0131na bir kimlik do\u011frulama veya yetkilendirme <code>interceptor<\/code> ekleyerek, sadece yetkili kullan\u0131c\u0131lar\u0131n ak\u0131\u015fa eri\u015fmesini sa\u011flayabilirsiniz.<\/p>\n<div class=\"expert-tip\">\n    Uzman \u0130pucu: SSE ak\u0131\u015flar\u0131 i\u00e7in kimlik do\u011frulama ve yetkilendirme, genellikle ilk ba\u011flant\u0131 iste\u011fi s\u0131ras\u0131nda kontrol edilir. Bu nedenle, <code>EventSource<\/code> objesini olu\u015ftururken URL'ye sorgu parametreleri olarak bir token eklemek veya sunucunun ilk ba\u011flant\u0131 iste\u011finde \u00e7erezleri\/ba\u015fl\u0131klar\u0131 kontrol etmesini sa\u011flamak yayg\u0131n bir y\u00f6ntemdir. Ancak, query parametreleri g\u00fcvenlik a\u00e7\u0131s\u0131ndan daha az tercih edilebilir, \u00e7\u00fcnk\u00fc loglarda g\u00f6r\u00fcnebilirler. JWT token'\u0131n\u0131 <code>Authorization<\/code> ba\u015fl\u0131\u011f\u0131 ile g\u00f6ndermek veya g\u00fcvenli \u00e7erezler kullanmak daha iyi bir yakla\u015f\u0131md\u0131r.\n  <\/div>\n<h3>Hata Y\u00f6netimi ve Loglama<\/h3>\n<p>Sunucu taraf\u0131nda, SSE ak\u0131\u015flar\u0131n\u0131 y\u00f6netirken olu\u015fabilecek hatalar\u0131 (\u00f6rne\u011fin, a\u011f hatalar\u0131, kaynak verisi hatalar\u0131) do\u011fru bir \u015fekilde loglamak ve ele almak \u00e7ok \u00f6nemlidir. Ballerina'n\u0131n hata yakalama mekanizmalar\u0131 (<code>try-catch-finally<\/code> veya <code>check<\/code> anahtar kelimesi) bu s\u00fcre\u00e7te size yard\u0131mc\u0131 olacakt\u0131r. \u0130stemciye de hata durumlar\u0131n\u0131 bildiren \u00f6zel olaylar (<code>event: error\\n data: ...\\n<\/code>) g\u00f6ndermek, istemcinin kullan\u0131c\u0131ya anlaml\u0131 geri bildirimler sunmas\u0131n\u0131 sa\u011flayabilir.<\/p>\n<p>Bu en iyi uygulamalar\u0131 Ballerina SSE uygulamalar\u0131n\u0131za dahil ederek, sadece i\u015flevsel de\u011fil, ayn\u0131 zamanda g\u00fcvenilir, \u00f6l\u00e7eklenebilir ve g\u00fcvenli ger\u00e7ek zamanl\u0131 \u00e7\u00f6z\u00fcmler olu\u015fturabilirsiniz. Ballerina'n\u0131n sa\u011flam altyap\u0131s\u0131 ve dil \u00f6zellikleri, bu ileri d\u00fczey konular\u0131n \u00e7o\u011funu kolayca ele alman\u0131z\u0131 sa\u011flar.<\/p>\n<h2>Vaka Analizi: Canl\u0131 Bir Dashboard Uygulamas\u0131 - Ballerina ile Monit\u00f6rizasyon<\/h2>\n<p>Ger\u00e7ek zamanl\u0131 veri ak\u0131\u015f\u0131n\u0131n en pratik kullan\u0131m alanlar\u0131ndan biri, canl\u0131 bir dashboard veya g\u00f6sterge panosu olu\u015fturmakt\u0131r. Bu t\u00fcr bir dashboard, sunucu kaynaklar\u0131n\u0131n durumunu, uygulama performans metriklerini, IoT cihazlar\u0131ndan gelen verileri veya finansal piyasa hareketlerini anl\u0131k olarak g\u00f6rselle\u015ftirebilir. Bu vaka analizinde, Ballerina ve Server-Sent Events (SSE) kullanarak basit bir sistem monit\u00f6rizasyon dashboard'unun nas\u0131l olu\u015fturulabilece\u011fini inceleyece\u011fiz.<\/p>\n<p><strong>Senaryo:<\/strong> Bir \u015firket, kritik sunucular\u0131n\u0131n CPU ve bellek kullan\u0131m\u0131n\u0131 anl\u0131k olarak izlemek istiyor. Bu verilerin bir web aray\u00fcz\u00fcnde, saniyeler i\u00e7inde g\u00fcncellenen grafikler ve metinlerle g\u00f6sterilmesi gerekiyor. Veri ak\u0131\u015f\u0131, sunucudan taray\u0131c\u0131ya tek y\u00f6nl\u00fc olmal\u0131 ve istemcinin sunucuya veri g\u00f6ndermesi gereksiz. Bu senaryo, SSE i\u00e7in bi\u00e7ilmi\u015f kaftan. Ballerina sunucumuz, d\u00fczenli aral\u0131klarla sahte sistem metrikleri (CPU kullan\u0131m\u0131 %0-100 aras\u0131, bellek kullan\u0131m\u0131 %0-100 aras\u0131) \u00fcretecek ve bunlar\u0131 ba\u011fl\u0131 t\u00fcm istemcilere SSE ak\u0131\u015f\u0131 olarak g\u00f6nderecektir. \u0130stemci taraf\u0131ndaki bir web uygulamas\u0131 (HTML\/JavaScript), bu verileri alacak ve basit grafikler veya metinlerle g\u00f6r\u00fcnt\u00fcleyecektir.<\/p>\n<h3>Ballerina Sunucu Taraf\u0131 Uygulamas\u0131<\/h3>\n<p>Ballerina sunucusu, her saniye yeni metrikler \u00fcretir ve bunlar\u0131 JSON format\u0131nda bir SSE olay\u0131 olarak yay\u0131nlar. Her olay\u0131n, metrik t\u00fcr\u00fcn\u00fc belirten bir <code>event:<\/code> alan\u0131 ve ger\u00e7ek veri olarak CPU ve bellek kullan\u0131m\u0131n\u0131 i\u00e7eren bir <code>data:<\/code> alan\u0131 olacakt\u0131r. Bu sayede istemci, gelen verinin ne t\u00fcr bir metrik oldu\u011funu kolayca anlayabilir.<\/p>\n<pre><code>\nimport ballerina\/http;\nimport ballerina\/io;\nimport ballerina\/time;\nimport ballerina\/random;\nimport ballerina\/json;\n\n\/\/ HTTP servisimizi tan\u0131ml\u0131yoruz.\nservice \/dashboard on new http:Listener(9090) {\n\n    \/\/ '\/metrics' yoluna gelen GET isteklerini kar\u015f\u0131layan kaynak fonksiyonu.\n    resource function get metrics(http:Caller caller) returns error? {\n        check caller->addHeader(\"Content-Type\", \"text\/event-stream\");\n        check caller->addHeader(\"Cache-Control\", \"no-cache\");\n        check caller->addHeader(\"Connection\", \"keep-alive\");\n\n        io:println(\"Dashboard metrik ak\u0131\u015f\u0131na yeni bir istemci ba\u011fland\u0131.\");\n\n        int eventId = 0;\n        while (true) {\n            \/\/ Rastgele CPU ve bellek kullan\u0131m verileri olu\u015ftur.\n            float cpuUsage = random:createRandom().nextFloat() * 100.0;\n            float memoryUsage = random:createRandom().nextFloat() * 100.0;\n\n            \/\/ JSON format\u0131nda veri objesi olu\u015ftur.\n            json payload = {\n                \"cpu\": cpuUsage.round(), \/\/ Ondal\u0131k k\u0131sm\u0131 kald\u0131r\n                \"memory\": memoryUsage.round(),\n                \"timestamp\": time:utcNow().toString()\n            };\n\n            \/\/ SSE olay format\u0131n\u0131 olu\u015ftur.\n            string data = string <code>data: ${payload.toJsonString()}\\n<\/code>;\n            string eventType = <code>event: systemMetrics\\n<\/code>; \/\/ \u00d6zel bir event tipi kullan\u0131yoruz\n            string id = <code>id: ${eventId}\\n<\/code>;\n            string retry = <code>retry: 3000\\n<\/code>; \/\/ \u0130stemci 3 saniyede bir yeniden denesin\n\n            error? result = caller->writeStream({\n                content: eventType + id + retry + data + \"\\n\"\n            });\n\n            if (result is error) {\n                io:println(\"Dashboard istemci ba\u011flant\u0131s\u0131 kesildi: \" + result.message());\n                break;\n            }\n\n            eventId += 1;\n            time:sleep(1); \/\/ Her saniye yeni metrik g\u00f6nder.\n        }\n        io:println(\"Dashboard metrik ak\u0131\u015f\u0131 sona erdi.\");\n        return;\n    }\n}\n  <\/pre>\n<p><\/code><\/p>\n<h3>\u0130stemci Taraf\u0131 Uygulamas\u0131 (HTML\/JavaScript)<\/h3>\n<p>\u0130stemci taraf\u0131, <code>EventSource<\/code> kullanarak Ballerina sunucusundan gelen <code>systemMetrics<\/code> olaylar\u0131n\u0131 dinleyecektir. Gelen CPU ve bellek verileri, basit bir HTML sayfas\u0131nda metin olarak veya daha geli\u015fmi\u015f bir senaryoda grafik k\u00fct\u00fcphaneleri (\u00f6rne\u011fin Chart.js) ile g\u00f6rselle\u015ftirilebilir. Bu \u00f6rnekte, verileri bir liste olarak g\u00f6sterece\u011fiz ve bir mobil cihazda da d\u00fczg\u00fcn g\u00f6r\u00fcnmesi i\u00e7in temel CSS media query'leri kullanaca\u011f\u0131z.<\/p>\n<pre><code>\n<!DOCTYPE html>\n<html lang=\"tr\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>Canl\u0131 Dashboard: Sistem Metrikleri<\/title>\n    <style>\n        body { font-family: 'Arial', sans-serif; margin: 20px; background-color: #f0f2f5; color: #333; }\n        .dashboard-container { max-width: 900px; margin: 20px auto; background-color: #fff; padding: 30px; border-radius: 10px; box-shadow: 0 6px 20px rgba(0,0,0,0.1); }\n        h1 { color: #2c3e50; text-align: center; margin-bottom: 30px; font-size: 2.5em; }\n        .metric-card { background-color: #e8f0fe; border-left: 5px solid #3498db; margin-bottom: 20px; padding: 20px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.05); display: flex; justify-content: space-between; align-items: center; }\n        .metric-card.cpu { border-color: #e74c3c; background-color: #fdeded; }\n        .metric-card.memory { border-color: #27ae60; background-color: #edf7ed; }\n        .metric-card h2 { margin: 0; color: #34495e; font-size: 1.5em; }\n        .metric-card p { margin: 5px 0 0; font-size: 1.8em; font-weight: bold; color: #2c3e50; }\n        #status-indicator { text-align: center; margin-bottom: 20px; font-weight: bold; color: #e74c3c; }\n        #status-indicator.connected { color: #27ae60; }\n\n        \/* Responsive tasar\u0131m i\u00e7in medya sorgular\u0131 *\/\n        @media (max-width: 768px) {\n            .dashboard-container {\n                margin: 10px;\n                padding: 20px;\n            }\n            h1 {\n                font-size: 2em;\n            }\n            .metric-card {\n                flex-direction: column;\n                align-items: flex-start;\n            }\n            .metric-card p {\n                font-size: 1.5em;\n            }\n        }\n        @media (max-width: 480px) {\n            body {\n                margin: 10px;\n            }\n            h1 {\n                font-size: 1.8em;\n            }\n            .metric-card {\n                padding: 15px;\n            }\n        }\n    <\/style>\n<\/head>\n<body>\n    <div class=\"dashboard-container\">\n        <h1>Ballerina Canl\u0131 Sistem Metrikleri<\/h1>\n        <div id=\"status-indicator\">Ba\u011flant\u0131 Durumu: Kesik<\/div>\n\n        <div id=\"cpu-metric\" class=\"metric-card cpu\">\n            <h2>CPU Kullan\u0131m\u0131<\/h2>\n            <p><span id=\"cpu-value\">%0<\/span><\/p>\n        <\/div>\n\n        <div id=\"memory-metric\" class=\"metric-card memory\">\n            <h2>Bellek Kullan\u0131m\u0131<\/h2>\n            <p><span id=\"memory-value\">%0<\/span><\/p>\n        <\/div>\n\n        <div id=\"last-update\" class=\"metric-card\">\n            <h2>Son G\u00fcncelleme Zaman\u0131<\/h2>\n            <p><span id=\"timestamp-value\">Bekleniyor...<\/span><\/p>\n        <\/div>\n    <\/div>\n\n    <script>\n        const eventSource = new EventSource('http:\/\/localhost:9090\/dashboard\/metrics');\n        const cpuValue = document.getElementById('cpu-value');\n        const memoryValue = document.getElementById('memory-value');\n        const timestampValue = document.getElementById('timestamp-value');\n        const statusIndicator = document.getElementById('status-indicator');\n\n        eventSource.onopen = function() {\n            console.log('SSE ba\u011flant\u0131s\u0131 a\u00e7\u0131ld\u0131: Dashboard Metrikleri');\n            statusIndicator.textContent = 'Ba\u011flant\u0131 Durumu: Ba\u011fl\u0131';\n            statusIndicator.classList.add('connected');\n        };\n\n        \/\/ Sunucudan 'systemMetrics' olaylar\u0131n\u0131 dinle\n        eventSource.addEventListener('systemMetrics', function(event) {\n            try {\n                const data = JSON.parse(event.data);\n                cpuValue.textContent = <code>%${data.cpu}<\/code>;\n                memoryValue.textContent = <code>%${data.memory}<\/code>;\n                timestampValue.textContent = new Date(data.timestamp).toLocaleTimeString();\n            } catch (e) {\n                console.error('Metrik verisi ayr\u0131\u015ft\u0131rma hatas\u0131:', e);\n            }\n        });\n\n        eventSource.onerror = function(event) {\n            console.error('SSE ba\u011flant\u0131 hatas\u0131: Dashboard Metrikleri', event);\n            statusIndicator.textContent = 'Ba\u011flant\u0131 Durumu: Kesik (Yeniden Deneniyor...)';\n            statusIndicator.classList.remove('connected');\n        };\n    <\/script>\n<\/body>\n<\/html>\n  <\/pre>\n<p><\/code><\/p>\n<p>Bu vaka analizi, Ballerina ve SSE'nin ger\u00e7ek zamanl\u0131 bir dashboard uygulamas\u0131n\u0131 nas\u0131l basit ve etkili bir \u015fekilde g\u00fc\u00e7lendirebilece\u011fini g\u00f6stermektedir. Ballerina'n\u0131n kolay \u00f6\u011frenilebilir s\u00f6zdizimi ve yerle\u015fik a\u011f \u00f6zellikleri sayesinde, sunucu taraf\u0131nda veri \u00fcretimi ve ak\u0131\u015f\u0131 olduk\u00e7a basittir. \u0130stemci taraf\u0131nda ise <code>EventSource<\/code> API'si, gelen verileri sorunsuz bir \u015fekilde t\u00fcketmenizi sa\u011flar. Mobil uyumlu CSS media query'leri, bu dashboard'un tabletler ve ak\u0131ll\u0131 telefonlar dahil olmak \u00fczere \u00e7e\u015fitli cihazlarda iyi bir kullan\u0131c\u0131 deneyimi sunmas\u0131n\u0131 garanti eder. Bu yakla\u015f\u0131m, sadece sistem monit\u00f6rizasyonu i\u00e7in de\u011fil, ayn\u0131 zamanda finansal uygulamalar, IoT veri g\u00f6rselle\u015ftirmeleri ve sosyal medya ak\u0131\u015flar\u0131 gibi bir\u00e7ok ger\u00e7ek zamanl\u0131 senaryo i\u00e7in de uygulanabilir.<\/p>\n<h2>Sonu\u00e7: Ger\u00e7ek Zamanl\u0131 Gelece\u011fe Ad\u0131m At\u0131n<\/h2>\n<p>Ger\u00e7ek zamanl\u0131 veri ak\u0131\u015f\u0131, modern web uygulamalar\u0131n\u0131n vazge\u00e7ilmez bir par\u00e7as\u0131 haline gelmi\u015ftir ve Server-Sent Events (SSE), bu ihtiyac\u0131 kar\u015f\u0131lamak i\u00e7in olduk\u00e7a g\u00fc\u00e7l\u00fc ve basit bir \u00e7\u00f6z\u00fcm sunar. Bu makale boyunca, SSE'nin temel prensiplerini, WebSockets ve geleneksel polling gibi alternatiflerle kar\u015f\u0131la\u015ft\u0131rmas\u0131n\u0131 ve Ballerina'n\u0131n bu teknolojiyi uygulamak i\u00e7in neden ideal bir platform oldu\u011funu detayl\u0131ca inceledik. Ballerina'n\u0131n a\u011f odakl\u0131 yap\u0131s\u0131, e\u015fzamanl\u0131l\u0131k deste\u011fi ve temiz s\u00f6zdizimi sayesinde, karma\u015f\u0131k ger\u00e7ek zamanl\u0131 senaryolar\u0131 bile \u015fa\u015f\u0131rt\u0131c\u0131 derecede az kodla ve y\u00fcksek performansla hayata ge\u00e7irebilece\u011fimizi g\u00f6rd\u00fck. \u0130lk SSE sunucusundan, bir istemcinin nas\u0131l olu\u015fturulaca\u011f\u0131na ve geli\u015fmi\u015f kullan\u0131m tekniklerine kadar ad\u0131m ad\u0131m rehberlik ettik.<\/p>\n<p>Geli\u015fmi\u015f ba\u011flant\u0131 y\u00f6netimi, olay kimliklerinin kullan\u0131m\u0131yla kay\u0131p olaylar\u0131n telafisi, g\u00fc\u00e7l\u00fc kimlik do\u011frulama ve yetkilendirme mekanizmalar\u0131 ile g\u00fcvenlik ve kapsaml\u0131 hata y\u00f6netimi stratejileri, Ballerina ile olu\u015fturulan SSE uygulamalar\u0131n\u0131n sadece i\u015flevsel de\u011fil, ayn\u0131 zamanda sa\u011flam ve g\u00fcvenilir olmas\u0131n\u0131 sa\u011flar. Canl\u0131 bir dashboard uygulamas\u0131 \u00f6rne\u011fiyle, Ballerina ve SSE'nin birle\u015fimiyle ger\u00e7ek d\u00fcnya problemlerine nas\u0131l etkili \u00e7\u00f6z\u00fcmler \u00fcretilebilece\u011fini uygulamal\u0131 olarak g\u00f6sterdik. Bu vaka analizi, SSE'nin sadece teorik bir kavram olmad\u0131\u011f\u0131n\u0131, ayn\u0131 zamanda pratik ve \u00f6l\u00e7eklenebilir uygulamalar i\u00e7in g\u00fc\u00e7l\u00fc bir ara\u00e7 oldu\u011funu kan\u0131tlad\u0131. Ballerina'n\u0131n SSE deste\u011fi, geli\u015ftiricilere, kullan\u0131c\u0131lar\u0131na anl\u0131k, dinamik ve etkile\u015fimli deneyimler sunan uygulamalar yaratma konusunda e\u015fsiz bir kolayl\u0131k ve g\u00fc\u00e7 sa\u011flamaktad\u0131r. G\u00fcn\u00fcm\u00fczde veri odakl\u0131 uygulamalar\u0131n \u00f6nemini d\u00fc\u015f\u00fcnd\u00fc\u011f\u00fcm\u00fczde, Ballerina ile Server-Sent Events kullanmak, ger\u00e7ek zamanl\u0131 veri ak\u0131\u015f\u0131n\u0131n getirdi\u011fi t\u00fcm avantajlardan faydalanarak gelece\u011fin web uygulamalar\u0131n\u0131 in\u015fa etmek i\u00e7in at\u0131lacak en do\u011fru ad\u0131mlardan biridir.<\/p>\n<h3>S\u0131k\u00e7a Sorulan Sorular<\/h3>\n<dl>\n<dt>SSE ve WebSockets aras\u0131ndaki temel fark nedir?<\/dt>\n<dd>SSE (Server-Sent Events) tek y\u00f6nl\u00fc bir ileti\u015fim kanal\u0131d\u0131r; sunucudan istemciye veri ak\u0131\u015f\u0131 sa\u011flar. WebSockets ise \u00e7ift y\u00f6nl\u00fc, tam dubleks bir ileti\u015fim kanal\u0131 kurarak hem sunucunun hem de istemcinin birbirine istedi\u011fi zaman veri g\u00f6ndermesine olanak tan\u0131r. SSE, istemcinin sunucuya veri g\u00f6ndermesine gerek duymad\u0131\u011f\u0131 senaryolar (\u00f6rn. haber ak\u0131\u015flar\u0131) i\u00e7in daha basit ve hafif bir \u00e7\u00f6z\u00fcmd\u00fcr, WebSockets ise sohbet uygulamalar\u0131 gibi iki y\u00f6nl\u00fc ileti\u015fimin kritik oldu\u011fu yerlerde tercih edilir.<\/dd>\n<dt>Ballerina'da SSE ak\u0131\u015flar\u0131n\u0131 nas\u0131l g\u00fcvenli hale getirebilirim?<\/dt>\n<dd>Ballerina'da SSE ak\u0131\u015flar\u0131n\u0131 g\u00fcvenli hale getirmek i\u00e7in HTTP servislerine \u00f6zg\u00fc kimlik do\u011frulama (Authentication) ve yetkilendirme (Authorization) mekanizmalar\u0131n\u0131 kullanabilirsiniz. Bu, genellikle ilk SSE ba\u011flant\u0131s\u0131 iste\u011fi s\u0131ras\u0131nda bir JWT (JSON Web Token) veya oturum \u00e7erezi (session cookie) kullanarak yap\u0131l\u0131r. Ballerina'n\u0131n yerle\u015fik HTTP g\u00fcvenlik \u00f6zellikleri, kaynak fonksiyonunuza bir yetkilendirme katman\u0131 eklemenizi veya interceptor'lar kullanman\u0131z\u0131 sa\u011flar.<\/dd>\n<dt>SSE, t\u00fcm taray\u0131c\u0131lar taraf\u0131ndan destekleniyor mu?<\/dt>\n<dd>Evet, <code>EventSource<\/code> API'si modern taray\u0131c\u0131lar\u0131n \u00e7o\u011fu taraf\u0131ndan geni\u015f \u00e7apta desteklenmektedir (Chrome, Firefox, Safari, Edge vb.). Ancak, Internet Explorer gibi eski taray\u0131c\u0131larda do\u011frudan destek bulunmayabilir, bu durumda bir polyfill kullanmak gerekebilir.<\/dd>\n<dt>Bir SSE ba\u011flant\u0131s\u0131 kesildi\u011finde ne olur? Otomatik olarak yeniden ba\u011flan\u0131r m\u0131?<\/dt>\n<dd>Evet, Server-Sent Events'in en b\u00fcy\u00fck avantajlar\u0131ndan biri otomatik yeniden ba\u011flanma \u00f6zelli\u011fidir. \u0130stemci taraf\u0131ndaki <code>EventSource<\/code> API'si, a\u011f kesintileri veya sunucu hatalar\u0131 durumunda ba\u011flant\u0131y\u0131 belirli bir gecikmeyle otomatik olarak yeniden kurmaya \u00e7al\u0131\u015f\u0131r. Sunucu taraf\u0131nda <code>retry:<\/code> alan\u0131 g\u00f6nderilerek bu yeniden ba\u011flanma aral\u0131\u011f\u0131 ayarlanabilir.<\/dd>\n<dt>Ballerina ile birden fazla istemciye ayn\u0131 anda SSE ak\u0131\u015f\u0131 sa\u011flamak m\u00fcmk\u00fcn m\u00fcd\u00fcr?<\/dt>\n<dd>Kesinlikle evet. Ballerina'n\u0131n dilin i\u00e7ine yerle\u015fik e\u015fzamanl\u0131l\u0131k (concurrency) ve a\u011f soyutlamalar\u0131 sayesinde, ayn\u0131 anda binlerce istemciye Server-Sent Events ak\u0131\u015f\u0131 sa\u011flamak m\u00fcmk\u00fcnd\u00fcr. Ballerina, her istemci ba\u011flant\u0131s\u0131n\u0131 etkin bir \u015fekilde y\u00f6netmek i\u00e7in hafif i\u015f par\u00e7ac\u0131klar\u0131 (strand'lar) kullan\u0131r, bu da y\u00fcksek \u00f6l\u00e7eklenebilirlik sa\u011flar ve sunucu kaynaklar\u0131n\u0131 verimli bir \u015fekilde kullan\u0131r.<\/dd>\n<\/dl>\n<p><\/body><\/p>\n","protected":false},"excerpt":{"rendered":"Modern web uygulamalar\u0131, kullan\u0131c\u0131lar\u0131na anl\u0131k ve dinamik deneyimler sunmak zorundad\u0131r. Peki, taray\u0131c\u0131lar\u0131n\u0131z\u0131n sunucudan s\u00fcrekli g\u00fcncel verileri, karma\u015f\u0131k altyap\u0131lar&hellip;","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"csco_page_header_type":"","csco_page_load_nextpost":"","csco_page_subscribe_form":"","csco_page_contact_form":"","footnotes":""},"categories":[874],"tags":[],"class_list":{"0":"post-33198","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-server","7":"cs-entry","8":"cs-video-wrap"},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.5 (Yoast SEO v25.3.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Ballerina ile Ger\u00e7ek Zamanl\u0131 Veri Ak\u0131\u015f\u0131: Server-Sent Events (SSE)<\/title>\n<meta name=\"description\" content=\"Modern web uygulamalar\u0131, kullan\u0131c\u0131lar\u0131na anl\u0131k ve dinamik deneyimler sunmak zorundad\u0131r. Peki, taray\u0131c\u0131lar\u0131n\u0131z\u0131n sunucudan s\u00fcrekli g\u00fcncel verileri, karma\u015f\u0131k altyap\u0131lar kurmadan, basit\u00e7e almas\u0131n\u0131 nas\u0131l sa\u011flar\u0131z? Server-Sent Events (SSE) ve Ballerina ile ger\u00e7ek zamanl\u0131 veri ak\u0131\u015f\u0131n\u0131 kolayca hayata ge\u00e7irebilirsiniz.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/fatihsoysal.com\/blog\/ballerina-ile-gercek-zamanli-veri-akisi-server-sent-events-sse\/\" \/>\n<meta property=\"og:locale\" content=\"tr_TR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Ballerina ile Ger\u00e7ek Zamanl\u0131 Veri Ak\u0131\u015f\u0131: Server-Sent Events (SSE)\" \/>\n<meta property=\"og:description\" content=\"Modern web uygulamalar\u0131, kullan\u0131c\u0131lar\u0131na anl\u0131k ve dinamik deneyimler sunmak zorundad\u0131r. Peki, taray\u0131c\u0131lar\u0131n\u0131z\u0131n sunucudan s\u00fcrekli g\u00fcncel verileri, karma\u015f\u0131k altyap\u0131lar kurmadan, basit\u00e7e almas\u0131n\u0131 nas\u0131l sa\u011flar\u0131z? Server-Sent Events (SSE) ve Ballerina ile ger\u00e7ek zamanl\u0131 veri ak\u0131\u015f\u0131n\u0131 kolayca hayata ge\u00e7irebilirsiniz.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fatihsoysal.com\/blog\/ballerina-ile-gercek-zamanli-veri-akisi-server-sent-events-sse\/\" \/>\n<meta property=\"og:site_name\" content=\"Kodlar\u0131n Gizemli D\u00fcnyas\u0131\" \/>\n<meta property=\"article:published_time\" content=\"2025-10-30T22:31:29+00:00\" \/>\n<meta name=\"author\" content=\"Fatih Soysal\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Yazan:\" \/>\n\t<meta name=\"twitter:data1\" content=\"Fatih Soysal\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tahmini okuma s\u00fcresi\" \/>\n\t<meta name=\"twitter:data2\" content=\"24 dakika\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/ballerina-ile-gercek-zamanli-veri-akisi-server-sent-events-sse\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/ballerina-ile-gercek-zamanli-veri-akisi-server-sent-events-sse\/\"},\"author\":{\"name\":\"Fatih Soysal\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"headline\":\"Ballerina ile Ger\u00e7ek Zamanl\u0131 Veri Ak\u0131\u015f\u0131: Server-Sent Events (SSE)\",\"datePublished\":\"2025-10-30T22:31:29+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/ballerina-ile-gercek-zamanli-veri-akisi-server-sent-events-sse\/\"},\"wordCount\":4111,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"articleSection\":[\"Server\"],\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/ballerina-ile-gercek-zamanli-veri-akisi-server-sent-events-sse\/#respond\"]}],\"copyrightYear\":\"2025\",\"copyrightHolder\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/ballerina-ile-gercek-zamanli-veri-akisi-server-sent-events-sse\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/ballerina-ile-gercek-zamanli-veri-akisi-server-sent-events-sse\/\",\"name\":\"Ballerina ile Ger\u00e7ek Zamanl\u0131 Veri Ak\u0131\u015f\u0131: Server-Sent Events (SSE)\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\"},\"datePublished\":\"2025-10-30T22:31:29+00:00\",\"description\":\"Modern web uygulamalar\u0131, kullan\u0131c\u0131lar\u0131na anl\u0131k ve dinamik deneyimler sunmak zorundad\u0131r. Peki, taray\u0131c\u0131lar\u0131n\u0131z\u0131n sunucudan s\u00fcrekli g\u00fcncel verileri, karma\u015f\u0131k altyap\u0131lar kurmadan, basit\u00e7e almas\u0131n\u0131 nas\u0131l sa\u011flar\u0131z? Server-Sent Events (SSE) ve Ballerina ile ger\u00e7ek zamanl\u0131 veri ak\u0131\u015f\u0131n\u0131 kolayca hayata ge\u00e7irebilirsiniz.\",\"breadcrumb\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/ballerina-ile-gercek-zamanli-veri-akisi-server-sent-events-sse\/#breadcrumb\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/ballerina-ile-gercek-zamanli-veri-akisi-server-sent-events-sse\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/ballerina-ile-gercek-zamanli-veri-akisi-server-sent-events-sse\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Anasayfa\",\"item\":\"https:\/\/fatihsoysal.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Ballerina ile Ger\u00e7ek Zamanl\u0131 Veri Ak\u0131\u015f\u0131: Server-Sent Events (SSE)\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/\",\"name\":\"Fatihsoysal.com\",\"description\":\"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim\",\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"tr\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\",\"name\":\"Fatih Soysal\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"contentUrl\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"width\":512,\"height\":512,\"caption\":\"Fatih Soysal\"},\"logo\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\"},\"description\":\"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Ballerina ile Ger\u00e7ek Zamanl\u0131 Veri Ak\u0131\u015f\u0131: Server-Sent Events (SSE)","description":"Modern web uygulamalar\u0131, kullan\u0131c\u0131lar\u0131na anl\u0131k ve dinamik deneyimler sunmak zorundad\u0131r. Peki, taray\u0131c\u0131lar\u0131n\u0131z\u0131n sunucudan s\u00fcrekli g\u00fcncel verileri, karma\u015f\u0131k altyap\u0131lar kurmadan, basit\u00e7e almas\u0131n\u0131 nas\u0131l sa\u011flar\u0131z? Server-Sent Events (SSE) ve Ballerina ile ger\u00e7ek zamanl\u0131 veri ak\u0131\u015f\u0131n\u0131 kolayca hayata ge\u00e7irebilirsiniz.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/fatihsoysal.com\/blog\/ballerina-ile-gercek-zamanli-veri-akisi-server-sent-events-sse\/","og_locale":"tr_TR","og_type":"article","og_title":"Ballerina ile Ger\u00e7ek Zamanl\u0131 Veri Ak\u0131\u015f\u0131: Server-Sent Events (SSE)","og_description":"Modern web uygulamalar\u0131, kullan\u0131c\u0131lar\u0131na anl\u0131k ve dinamik deneyimler sunmak zorundad\u0131r. Peki, taray\u0131c\u0131lar\u0131n\u0131z\u0131n sunucudan s\u00fcrekli g\u00fcncel verileri, karma\u015f\u0131k altyap\u0131lar kurmadan, basit\u00e7e almas\u0131n\u0131 nas\u0131l sa\u011flar\u0131z? Server-Sent Events (SSE) ve Ballerina ile ger\u00e7ek zamanl\u0131 veri ak\u0131\u015f\u0131n\u0131 kolayca hayata ge\u00e7irebilirsiniz.","og_url":"https:\/\/fatihsoysal.com\/blog\/ballerina-ile-gercek-zamanli-veri-akisi-server-sent-events-sse\/","og_site_name":"Kodlar\u0131n Gizemli D\u00fcnyas\u0131","article_published_time":"2025-10-30T22:31:29+00:00","author":"Fatih Soysal","twitter_card":"summary_large_image","twitter_misc":{"Yazan:":"Fatih Soysal","Tahmini okuma s\u00fcresi":"24 dakika"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/fatihsoysal.com\/blog\/ballerina-ile-gercek-zamanli-veri-akisi-server-sent-events-sse\/#article","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/ballerina-ile-gercek-zamanli-veri-akisi-server-sent-events-sse\/"},"author":{"name":"Fatih Soysal","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"headline":"Ballerina ile Ger\u00e7ek Zamanl\u0131 Veri Ak\u0131\u015f\u0131: Server-Sent Events (SSE)","datePublished":"2025-10-30T22:31:29+00:00","mainEntityOfPage":{"@id":"https:\/\/fatihsoysal.com\/blog\/ballerina-ile-gercek-zamanli-veri-akisi-server-sent-events-sse\/"},"wordCount":4111,"commentCount":0,"publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"articleSection":["Server"],"inLanguage":"tr","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/fatihsoysal.com\/blog\/ballerina-ile-gercek-zamanli-veri-akisi-server-sent-events-sse\/#respond"]}],"copyrightYear":"2025","copyrightHolder":{"@id":"https:\/\/fatihsoysal.com\/blog\/#organization"}},{"@type":"WebPage","@id":"https:\/\/fatihsoysal.com\/blog\/ballerina-ile-gercek-zamanli-veri-akisi-server-sent-events-sse\/","url":"https:\/\/fatihsoysal.com\/blog\/ballerina-ile-gercek-zamanli-veri-akisi-server-sent-events-sse\/","name":"Ballerina ile Ger\u00e7ek Zamanl\u0131 Veri Ak\u0131\u015f\u0131: Server-Sent Events (SSE)","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/#website"},"datePublished":"2025-10-30T22:31:29+00:00","description":"Modern web uygulamalar\u0131, kullan\u0131c\u0131lar\u0131na anl\u0131k ve dinamik deneyimler sunmak zorundad\u0131r. Peki, taray\u0131c\u0131lar\u0131n\u0131z\u0131n sunucudan s\u00fcrekli g\u00fcncel verileri, karma\u015f\u0131k altyap\u0131lar kurmadan, basit\u00e7e almas\u0131n\u0131 nas\u0131l sa\u011flar\u0131z? Server-Sent Events (SSE) ve Ballerina ile ger\u00e7ek zamanl\u0131 veri ak\u0131\u015f\u0131n\u0131 kolayca hayata ge\u00e7irebilirsiniz.","breadcrumb":{"@id":"https:\/\/fatihsoysal.com\/blog\/ballerina-ile-gercek-zamanli-veri-akisi-server-sent-events-sse\/#breadcrumb"},"inLanguage":"tr","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fatihsoysal.com\/blog\/ballerina-ile-gercek-zamanli-veri-akisi-server-sent-events-sse\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/fatihsoysal.com\/blog\/ballerina-ile-gercek-zamanli-veri-akisi-server-sent-events-sse\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Anasayfa","item":"https:\/\/fatihsoysal.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Ballerina ile Ger\u00e7ek Zamanl\u0131 Veri Ak\u0131\u015f\u0131: Server-Sent Events (SSE)"}]},{"@type":"WebSite","@id":"https:\/\/fatihsoysal.com\/blog\/#website","url":"https:\/\/fatihsoysal.com\/blog\/","name":"Fatihsoysal.com","description":"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim","publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"tr"},{"@type":["Person","Organization"],"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1","name":"Fatih Soysal","image":{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","contentUrl":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","width":512,"height":512,"caption":"Fatih Soysal"},"logo":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/"},"description":"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.","url":"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/"}]}},"yoast_meta":{"yoast_wpseo_title":"","yoast_wpseo_metadesc":"","yoast_wpseo_canonical":""},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/33198","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/comments?post=33198"}],"version-history":[{"count":0,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/33198\/revisions"}],"wp:attachment":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/media?parent=33198"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/categories?post=33198"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/tags?post=33198"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}