﻿
{"id":28850,"date":"2026-07-31T15:52:21","date_gmt":"2026-07-31T15:52:21","guid":{"rendered":"https:\/\/www.gencayyildiz.com\/blog\/?p=28850"},"modified":"2026-07-31T15:52:21","modified_gmt":"2026-07-31T15:52:21","slug":"uzun-suren-api-requestlerini-olceklendirme-yontemleri","status":"publish","type":"post","link":"https:\/\/www.gencayyildiz.com\/blog\/uzun-suren-api-requestlerini-olceklendirme-yontemleri\/","title":{"rendered":"Uzun S\u00fcren API Request&#8217;lerini \u00d6l\u00e7eklendirme Y\u00f6ntemleri"},"content":{"rendered":"<div id=\"fb-root\"><\/div>\n<p><a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2026\/07\/Uzun-Suren-API-Requestlerini-Olceklendirme-Yontemleri.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2026\/07\/Uzun-Suren-API-Requestlerini-Olceklendirme-Yontemleri.png\" alt=\"Uzun S\u00fcren API Request&#039;lerini \u00d6l\u00e7eklendirme Y\u00f6ntemleri\" width=\"1536\" height=\"1024\" class=\"aligncenter size-full wp-image-28859\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2026\/07\/Uzun-Suren-API-Requestlerini-Olceklendirme-Yontemleri.png 1536w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2026\/07\/Uzun-Suren-API-Requestlerini-Olceklendirme-Yontemleri-300x200.png 300w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2026\/07\/Uzun-Suren-API-Requestlerini-Olceklendirme-Yontemleri-1024x683.png 1024w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2026\/07\/Uzun-Suren-API-Requestlerini-Olceklendirme-Yontemleri-768x512.png 768w\" sizes=\"auto, (max-width: 1536px) 100vw, 1536px\" \/><\/a>Merhaba,<\/p>\n<p>Geli\u015ftirdi\u011fimiz uygulamalar\u0131m\u0131zda illa ki tamamlanmas\u0131 dakikalarca s\u00fcren bir endpoint&#8217;in ortaya \u00e7\u0131kmas\u0131 neredeyse ka\u00e7\u0131n\u0131lmazd\u0131r. Misal olarak; y\u0131llarca toplanan verilerin istatistiki olarak raporlanmas\u0131 gerekti\u011fi durumlarda, toplu veri aktar\u0131mlar\u0131nda veya response d\u00f6nd\u00fcr\u00fclmeden \u00f6nce birka\u00e7 servise ve veritaban\u0131na yay\u0131lan i\u015f ak\u0131\u015f\u0131 s\u00fcre\u00e7lerinde geli\u015ftirdi\u011fimiz endpoint&#8217;ler, ister istemez haddinden fazla tedirginlik yaratan bekleme s\u00fcreleri ile varl\u0131k g\u00f6sterebiliyorlar. Ki b\u00f6yle endpoint&#8217;lerin varl\u0131\u011f\u0131ndan ziyade ortaya \u00e7\u0131kard\u0131klar\u0131 sorunlar bizler i\u00e7in risk te\u015fkil ediyor. <em>Nedir bu sorunlar?<\/em> diye sorarsan\u0131z&#8230; Bu endpoint&#8217;lerden beslenen servislerin ya da bizzat kullan\u0131c\u0131lar\u0131n dakikalar boyunca bekletiliyor olmalar\u0131d\u0131r! E\u011fer bekleyen bir servisse timeout&#8217;a d\u00fc\u015fme ihtimali vard\u0131r, yok e\u011fer bir kullan\u0131c\u0131ysa en iyi ihtimalle bunalma ihtimali&#8230; Ve t\u00fcm bu s\u00fcre\u00e7 boyunca API&#8217;da bu request&#8217;i i\u015flem s\u00fcresi boyunca a\u00e7\u0131k tutacakt\u0131r ve bu durumda da sunucu a\u00e7\u0131s\u0131ndan bir thread&#8217;in ve concurrency b\u00fct\u00e7esi s\u00f6z konusu olacakt\u0131r. Hele hele b\u00f6yle bir durumda bu endpoint&#8217;te zuhur edecek olan k\u00fc\u00e7\u00fck bir trafik art\u0131\u015f\u0131, API&#8217;nin geri kalan\u0131n\u0131 da potansiyel olarak \u00e7\u00f6kertecektir. Bu i\u00e7eri\u011fimizde bu tarz sorunlara kar\u015f\u0131 nas\u0131l yakla\u015f\u0131mlar ve \u00e7\u00f6z\u00fcmler uygulamam\u0131z gerekti\u011fine dair isti\u015farede bulunacak ve \u00e7al\u0131\u015fmalar\u0131m\u0131z\u0131 daha idealize hale getirmeye \u00e7al\u0131\u015f\u0131yor olaca\u011f\u0131z. O halde buyurun ba\u015flayal\u0131m&#8230;<\/p>\n<p>\u00d6zellikle son zamanlarda bu konuda \u00e7ok fazla yanl\u0131\u015f uygulama g\u00f6zlemledi\u011fimi itiraf edebilirim. Muhtemelen insanlar, genellikle &#8220;API request&#8217;i 5 dakika s\u00fcr\u00fcyor ama sorun de\u011fil&#8221; diye d\u00fc\u015f\u00fcnmektedirler. Halbuki as\u0131l problem kodun uzun s\u00fcrmesi de\u011fil, HTTP&#8217;nin do\u011fas\u0131n\u0131n buna uygun olmamas\u0131d\u0131r!<\/p>\n<p>\u00d6nce \u015fu soruyu sormakta fayda vard\u0131r&#8230; <strong><em>Bir API request&#8217;inin uzun s\u00fcrmesi neden problemdir?<\/em><\/strong><\/p>\n<p>Uzun bir request bitene kadar TCP ba\u011flant\u0131s\u0131 ve HTTP connection a\u00e7\u0131k kalacak, Kestrel request context&#8217;i s\u00fcre boyunca ya\u015fayacak ve arada Nginx, IIS, API Gateway ve Load Balancer varsa onlar da iste\u011fin tamamlanmas\u0131n\u0131 timeout saya\u00e7lar\u0131 \u00e7al\u0131\u015f\u0131r vaziyette bekleyecektir. T\u00fcm bunlar\u0131n yan\u0131nda tabi ki de client&#8217;da request&#8217;in yan\u0131t\u0131n\u0131 (response) bekleyecektir. \u015eimdi d\u00fc\u015f\u00fcn\u00fcn&#8230; B\u00f6yle bir request&#8217;i 1000 kullan\u0131c\u0131 ayn\u0131 anda yaparsa ne olacak?<\/p>\n<p>Ayr\u0131ca uzun request s\u00fcre\u00e7lerinde bir\u00e7ok sistemin(Nginx, IIS, Azure App Service, API Gateway, Load Balancer ve Browser) timeout s\u00fcreleri birbirlerinden farkl\u0131 oldu\u011fu i\u00e7in ciddi bir risk s\u00f6z konusu olacakt\u0131r. \u015e\u00f6yle ki; diyelim ki client timeout ald\u0131 ve retry mekanizmas\u0131 ile tekrar request&#8217;te bulundu. Eee, bu durumda tekrar ayn\u0131 s\u00fcre\u00e7 ba\u015flat\u0131lacak ve netice olarak iki kez bu i\u015f y\u00fck\u00fc cereyan etmi\u015f olacakt\u0131r! (Bu tarz durumlara kar\u015f\u0131n <a href=\"https:\/\/www.gencayyildiz.com\/blog\/tag\/idempotency\/\" target=\"_blank\">idempotency<\/a> cidden \u00f6nem kazanmaktad\u0131r)<\/p>\n<p><strong><em>Peki \u00e7\u00f6z\u00fcm ne hoca?<\/em><\/strong> dedi\u011finizi duyar gibiyim&#8230; Do\u011frusunu s\u00f6ylemek gerekirse tek bir \u00e7\u00f6z\u00fcm yok! Duruma g\u00f6re uygulanmas\u0131 gereken farkl\u0131 desenler var&#8230; Ve bence bunlar\u0131 a\u015fa\u011f\u0131daki gibi s\u00fcrelere g\u00f6re kategorize edebiliriz:<\/p>\n<table style=\"width:60%; border-collapse:collapse; font-size:13px; color:#374151; border:1px solid #e5e7eb; background:#fff;\">\n<thead>\n<tr>\n<th style=\"padding:10px 14px; text-align:left; background:#f8fafc; border-bottom:1px solid #e5e7eb; font-weight:600; color:#111827;\">\u0130\u015f S\u00fcresi<\/th>\n<th style=\"padding:10px 14px; text-align:justify; background:#f8fafc; border-bottom:1px solid #e5e7eb; font-weight:600; color:#111827;\">Yakla\u015f\u0131m<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"padding:10px 14px; border-bottom:1px solid #f1f5f9;\">< 2 sn<\/td>\n<td style=\"padding:10px 14px; text-align:justify; border-bottom:1px solid #f1f5f9;\">Senkron HTTP<\/td>\n<\/tr>\n<tr>\n<td style=\"padding:10px 14px; border-bottom:1px solid #f1f5f9;\">2 &#8211; 10 sn<\/td>\n<td style=\"padding:10px 14px; text-align:justify; border-bottom:1px solid #f1f5f9;\">Duruma g\u00f6re senkron veya asenkron s\u00fcre\u00e7<\/td>\n<\/tr>\n<tr>\n<td style=\"padding:10px 14px;\">10 sn+<\/td>\n<td style=\"padding:10px 14px; text-align:justify;\">Background processing<\/td>\n<\/tr>\n<tr>\n<td style=\"padding:10px 14px;\">Dakikalar<\/td>\n<td style=\"padding:10px 14px; text-align:justify;\">Queue + Worker<\/td>\n<\/tr>\n<tr>\n<td style=\"padding:10px 14px;\">Saatler<\/td>\n<td style=\"padding:10px 14px; text-align:justify;\">Workflow \/ Job scheduler<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Hadi \u015fimdi gelin tek tek desenleri do\u011frusuyla ve yanl\u0131\u015f\u0131yla incelemeye ba\u015flayal\u0131m.<\/p>\n<ul style=\"font-size:14px;\">\n<li><strong><em>Fire-and-Forget<\/em><\/strong><br \/>\n\u0130lk olarak bu g\u00fcne kadar g\u00f6rd\u00fc\u011f\u00fcm en tehlikeli yakla\u015f\u0131m\u0131 ele alarak ba\u015flayal\u0131m istiyorum. <\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\napp.MapGet(&quot;\/fire-and-forget&quot;, () =&gt;\r\n{\r\n    _ = Task.Run(async () =&gt;\r\n    {\r\n        while (true)\r\n        {\r\n            await Task.Delay(1500);\r\n            Console.WriteLine(&quot;PDF generating...&quot;);\r\n        }\r\n    });\r\n\r\n    return TypedResults.Ok();\r\n});\r\n<\/pre>\n<\/div>\n<p>Bu yakla\u015f\u0131mda mant\u0131k; yap\u0131lacak i\u015flem ne kadar uzun olursa olsun istek an\u0131nda sonu\u00e7lansa da i\u015flemin arka planda s\u00fcrd\u00fcr\u00fclmesini sa\u011flamakt\u0131r. \u0130lk bak\u0131\u015fta her ne kadar pratik g\u00f6r\u00fclse de <code>Task.Run<\/code> komutu Asp.NET Core&#8217;da g\u00fcvenilir bir arka plan i\u015fleme mekanizmas\u0131 olmad\u0131\u011f\u0131ndan dolay\u0131 esas\u0131nda olduk\u00e7a s\u0131k\u0131nt\u0131l\u0131 bir yakla\u015f\u0131m sergilenmektedir! \u00d6zellikle uygulama yeniden ba\u015flat\u0131l\u0131rsa task yar\u0131da kalabilir yahut hata al\u0131n\u0131rsa kimse fark etmeksizin i\u015flem s\u00fcreci baltalanabilir. Ve t\u00fcm bu s\u00fcre\u00e7te retry gibi bir mekanizma olmayaca\u011f\u0131 i\u00e7in de ciddi kay\u0131plar s\u00f6z konusu olabilir.<\/p>\n<blockquote><p><em>Yan\u0131t s\u00fcresi ile \u00e7al\u0131\u015fma s\u00fcresi ayn\u0131 \u015fey olmak zorunda de\u011fildir! Haliyle request&#8217;lerin s\u00fcreleri bu mant\u0131\u011fa g\u00f6re yap\u0131land\u0131r\u0131lmak istenebilir. Ancak yanl\u0131\u015f y\u00f6ntemler ciddi maliyetlere sebebiyet verebilece\u011fi i\u00e7in dikkat edilmelidir&#8230;<\/em><\/p><\/blockquote>\n<\/li>\n<li><strong><em>Background Queue<\/em><\/strong><br \/>\nS\u0131rada Microsoft&#8217;un \u00f6nerdi\u011fi yakla\u015f\u0131mdan bahsedelim&#8230;<\/p>\n<p>Bu yakla\u015f\u0131mda ise yo\u011fun i\u015flem hacmine sahip endpoint&#8217;e gelen iste\u011fin direkt i\u015flevsellikten \u00f6nce bir queue&#8217;ya aktar\u0131lmas\u0131 esas te\u015fkil etmektedir. \u015e\u00f6yle ki;<\/p>\n<div style=\"display:flex;align-items:center;justify-content:center;gap:8px;margin:25px 0;font-family:Arial,sans-serif;flex-wrap:nowrap;\">\n<div style=\"background:#2563eb;color:#fff;padding:10px 14px;border-radius:12px;font-size:14px;font-weight:bold;white-space:nowrap;\">\n        Request\n    <\/div>\n<div style=\"color:#22c55e;font-size:22px;font-weight:bold;\">\u279c<\/div>\n<div style=\"border:2px solid #f59e0b;border-radius:12px;padding:10px 12px;background:#fafafa;text-align:center;width:130px;box-sizing:border-box;\">\n<div style=\"font-size:15px;font-weight:bold;color:#444;\">API<\/div>\n<div style=\"margin-top:5px;font-size:11px;color:#666;line-height:1.3;\">\n            \u0130\u015f kuyru\u011fa eklenir\n        <\/div>\n<\/p><\/div>\n<div style=\"color:#22c55e;font-size:22px;font-weight:bold;\">\u279c<\/div>\n<div style=\"background:#10b981;color:#fff;padding:10px 14px;border-radius:12px;font-size:14px;font-weight:bold;white-space:nowrap;\">\n        Response\n    <\/div>\n<div style=\"color:#22c55e;font-size:22px;font-weight:bold;\">\u279c<\/div>\n<div style=\"border:2px solid #7c3aed;border-radius:12px;padding:10px 12px;background:#fafafa;text-align:center;width:180px;box-sizing:border-box;\">\n<div style=\"font-size:15px;font-weight:bold;color:#444;\">Background Service<\/div>\n<div style=\"margin-top:5px;font-size:11px;color:#666;line-height:1.3;\">\n            Kuyruktan i\u015f al\u0131n\u0131r ve i\u015flenir\n        <\/div>\n<\/p><\/div>\n<\/div>\n<p>Burada g\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere yine gelen request an\u0131nda response d\u00f6nd\u00fcrecektir. Ancak i\u015f bir \u00f6nceki yakla\u015f\u0131ma nazaran daha g\u00fcvenli bir \u015fekilde queue \u00fczerinden background service ile y\u00fcr\u00fct\u00fcl\u00fcyor olacakt\u0131r. Bunun i\u00e7in uygulaman\u0131n belle\u011finde (in-memory) \u00e7al\u0131\u015fan bir queue&#8217;dan yararlan\u0131lmaktad\u0131r. Bak\u0131n dikkat ederseniz hen\u00fcz <a href=\"https:\/\/www.gencayyildiz.com\/blog\/category\/rabbitmq\/\" target=\"_blank\">RabbitMQ<\/a>, <a href=\"https:\/\/www.gencayyildiz.com\/blog\/nette-nats-jetstream-ile-calismak\/\" target=\"_blank\">NATS<\/a> vs. gibi harici bir message broker altyap\u0131s\u0131na gitmiyoruz! Daha yap\u0131lacak i\u015f hacmi o derece a\u011f\u0131r ve \u00f6l\u00e7eklendirme gerektirmedi\u011fi i\u00e7in i\u015fi in-memory&#8217;de \u00e7\u00f6z\u00fcyoruz \ud83d\ude09<\/p>\n<p>Bu yakla\u015f\u0131m sayesinde HTTP request hem uzun s\u00fcre a\u00e7\u0131k kalmayacak hem de kullan\u0131c\u0131 ve client bekletilmeyecektir. Gelen taleplere kar\u015f\u0131n i\u015fler, s\u0131ras\u0131yla veya belirlendi\u011fi say\u0131da paralel bir \u015fekilde i\u015fleniyor olacakt\u0131r. <code>Task.Run<\/code> yakla\u015f\u0131m\u0131na g\u00f6re \u00e7ok daha kontroll\u00fc ve emniyetlidir! Ancak \u00f6nemli bir dezavantaj\u0131 vard\u0131r ki, o da, queue&#8217;nun uygulaman\u0131n belle\u011finde olmas\u0131d\u0131r. Uygulama yeniden ba\u015flat\u0131ld\u0131\u011f\u0131 taktirde queue&#8217;daki i\u015fler kaybolacakt\u0131r. Bu nedenle kritik sistemlerde kesinlikle harici message broker kullan\u0131lmas\u0131 elzem olacakt\u0131r.<\/p>\n<p>\u00d6rnek \u00e7al\u0131\u015fma;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\napp.MapGet(&quot;\/background-queue&quot;, async () =&gt;\r\n{\r\n    await BackgroundTaskQueue.EnqueueAsync(async cancellationToken =&gt;\r\n      {\r\n          for (int i = 0; i &lt; 10; i++)\r\n          {\r\n              await Task.Delay(1500, cancellationToken);\r\n              Console.WriteLine($&quot;PDF generating... {i}&quot;);\r\n          }\r\n      });\r\n\r\n    return TypedResults.Ok();\r\n});\r\n<\/pre>\n<\/div>\n<p>Burada gelen istek neticesinde yap\u0131lacak i\u015f (her ne kadar for d\u00f6ng\u00fcs\u00fc de olsa) in-memory&#8217;de arka planda i\u015flenir halde queue&#8217;ya al\u0131nmaktad\u0131r.<\/p>\n<div style=\"background:#fff8e5; border-left:4px solid #f4b400; padding:15px 18px; margin:20px 0; border-radius:6px; color:#444; font-size:15px; line-height:1.6;\">\n    <strong>\u26a0\ufe0f<\/strong> Bu yakla\u015f\u0131m\u0131n kod b\u00fct\u00fcnl\u00fc\u011f\u00fcn\u00fc g\u00f6rebilmek i\u00e7in <a href=\"https:\/\/github.com\/gncyyldz\/AspNetCore.ApiScalingPatterns\/tree\/master\/AspNetCore.ApiScalingPatterns\/BackgroundQueuePattern\" target=\"_blank\">\u015furadaki<\/a> \u00e7al\u0131\u015fmaya g\u00f6z atabilirsiniz.\n<\/div>\n<\/li>\n<li><strong><em>Message Broker<\/em><\/strong><br \/>\n\u0130\u015f b\u00fcy\u00fcd\u00fc\u011f\u00fcnde, queue art\u0131k process i\u00e7erisinden \u00e7\u0131kar\u0131lmal\u0131d\u0131r. Bu art\u0131k ger\u00e7ek anlamda \u00f6l\u00e7eklenebilir bir yap\u0131 sunacakt\u0131r.<\/p>\n<p>Bu yakla\u015f\u0131ma dair \u00f6nceden klavyeye ald\u0131\u011f\u0131m a\u015fa\u011f\u0131daki i\u00e7eriklere g\u00f6z atman\u0131z\u0131 tavsiye ederim:<\/p>\n<ul>\n<li><a href=\"https:\/\/www.gencayyildiz.com\/blog\/nette-nats-jetstream-ile-calismak\/\" target=\"_blank\">.NET\u2019te NATS JetStream \u0130le \u00c7al\u0131\u015fmak<\/a><\/li>\n<li><a href=\"https:\/\/www.gencayyildiz.com\/blog\/asp-net-core-masstransit-rabbitmq-ile-birlikte-messaging-uygulamasi\/\" target=\"_blank\">Asp.NET Core \u2013 MassTransit &#038; RabbitMQ \u0130le Birlikte Messaging Uygulamas\u0131<\/a><\/li>\n<\/ul>\n<\/li>\n<li><strong><em>Polling Pattern<\/em><\/strong><br \/>\nBu y\u00f6ntem de y\u0131llard\u0131r kullan\u0131lan en g\u00fcvenilir yakla\u015f\u0131mlardan biridir. \u0130\u015fin ba\u015flat\u0131lmas\u0131, ama sonucunun beklenmemesi \u00fczerine kurulmu\u015f bir davran\u0131\u015fa sahiptir. Sonucu daha sonra gelip sorulmal\u0131d\u0131r.<\/p>\n<p>Tabi gelip neticenin sorulabilmesi i\u00e7in bir <em>jobId<\/em> de\u011ferine ihtiya\u00e7 olacakt\u0131r. Bunun i\u00e7in API, gelen request neticesinde an\u0131nda <\/p>\n<div style=\"background:#0d0d0d;color:#e6e6e6;font-family:Consolas,'Courier New',monospace;white-space:pre;line-height:0.8;padding:12px;width:150px;font-size:12px;\">{<br \/>\n    &#8220;jobId&#8221;: &#8220;a8f3d1&#8221;<br \/>\n}\n<\/div>\n<p>tarz\u0131 bir <em>jobId<\/em> de\u011feri d\u00f6nd\u00fcrecektir.<\/p>\n<p><strong><em>Neden buna polling denmektedir?<\/em><\/strong><br \/>\n\u00c7\u00fcnk\u00fc client belirli aral\u0131klarla sunucuya &#8216;Bitti mi?&#8217; diye soru sormaktad\u0131r. Yani ileti\u015fim client taraf\u0131ndad\u0131r. Sunucu, i\u015f bitince kullan\u0131c\u0131ya kendili\u011finden haber vermemektedir!<\/p>\n<div style=\"background:#0d0d0d;color:#e6e6e6;font-family:Consolas,'Courier New',monospace;white-space:pre;line-height:0.8;padding:12px;width:150px;font-size:12px;\">\nClient<br \/>\n   \u2502<br \/>\nPOST \/reports<br \/>\n   \u2502<br \/>\n\u25c4\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 JobId<br \/>\n   \u2502<br \/>\nGET \/reports\/{id}<br \/>\n   \u2502<br \/>\n\u25c4\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 Running<br \/>\n   \u2502<br \/>\nGET \/reports\/{id}<br \/>\n   \u2502<br \/>\n\u25c4\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 Running<br \/>\n   \u2502<br \/>\nGET \/reports\/{id}<br \/>\n   \u2502<br \/>\n\u25c4\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 Completed\n<\/div>\n<p>Bu yakla\u015f\u0131m\u0131 \u015f\u00f6yle bir \u00e7al\u0131\u015fma \u00fczerinden \u00f6rneklendirebiliriz;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\napp.MapPost(&quot;\/polling-pattern&quot;, async (JobStore jobStore) =&gt;\r\n{\r\n    var jobInfo = jobStore.Create();\r\n    await AspNetCore.ApiScalingPatterns.PollingPattern.BackgroundTaskQueue.EnqueueAsync(async cancellationToken =&gt;\r\n    {\r\n        jobInfo.Status = JobStatus.Running;\r\n        jobStore.Update(jobInfo);\r\n\r\n        \/\/\u0130\u015eLEM YAPILIYOR\r\n        try\r\n        {\r\n            for (int i = 0; i &lt; 10; i++)\r\n            {\r\n                await Task.Delay(1500, cancellationToken);\r\n                Console.WriteLine($&quot;PDF generating... {i}&quot;);\r\n            }\r\n            jobInfo.Status = JobStatus.Completed;\r\n            jobInfo.ResultUrl = &quot;https:\/\/example.com\/result.pdf&quot;;\r\n        }\r\n        catch (Exception ex)\r\n        {\r\n            jobInfo.Status = JobStatus.Failed;\r\n            jobInfo.Error = ex.Message;\r\n        }\r\n        \/\/\u0130\u015eLEM YAPILIYOR\r\n\r\n        jobStore.Update(jobInfo);\r\n    });\r\n\r\n    return TypedResults.Ok(new\r\n    {\r\n        jobId = jobInfo.Id\r\n    });\r\n});\r\n<\/pre>\n<\/div>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\napp.MapGet(&quot;\/polling-pattern\/{jobId}&quot;, async (JobStore jobStore, Guid jobId) =&gt;\r\n{\r\n    var jobInfo = jobStore.Get(jobId);\r\n\r\n    return TypedResults.Ok(jobInfo);\r\n});\r\n<\/pre>\n<\/div>\n<p>Evet, burada g\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere ikinci olu\u015fturdu\u011fumuz GET t\u00fcr\u00fcnden endpoint sayesinde job&#8217;a dair durum sorgulamas\u0131n\u0131 yapabilir ve yap\u0131lacak i\u015fe dair kontrolleri sa\u011flayabiliriz. <\/p>\n<div style=\"background:#fff8e5; border-left:4px solid #f4b400; padding:15px 18px; margin:20px 0; border-radius:6px; color:#444; font-size:15px; line-height:1.6;\">\n    <strong>\u26a0\ufe0f<\/strong> Bu yakla\u015f\u0131m\u0131n kod b\u00fct\u00fcnl\u00fc\u011f\u00fcn\u00fc g\u00f6rebilmek i\u00e7in <a href=\"https:\/\/github.com\/gncyyldz\/AspNetCore.ApiScalingPatterns\/tree\/master\/AspNetCore.ApiScalingPatterns\/PollingPattern\" target=\"_blank\">\u015furadaki<\/a> \u00e7al\u0131\u015fmaya g\u00f6z atabilirsiniz.\n<\/div>\n<\/li>\n<li><strong><em>Callback \/ Webhook<\/em><\/strong><br \/>\n<blockquote><p><em>Sen beni bekleme, i\u015fim bitince ben seri arar\u0131m&#8230;<\/em><\/p><\/blockquote>\n<p>Polling&#8217;de client s\u00fcrekli sunucuya sorarken, Webhook&#8217;ta sunucu i\u015flem bittikten sonra client&#8217;a haber vermektedir. Yap\u0131land\u0131rmas\u0131 olduk\u00e7a basit mant\u0131\u011fa dayanmaktad\u0131r. Hemen \u00f6rneklendirirsek e\u011fer;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\napp.MapPost(&quot;\/callback-webhook\/{*callbackUrl}&quot;, async (string callbackUrl, JobStore jobStore, IHttpClientFactory httpClientFactory) =&gt;\r\n{\r\n    var jobId = Guid.NewGuid();\r\n\r\n    await AspNetCore.ApiScalingPatterns.Callback_Webhook.BackgroundTaskQueue.EnqueueAsync(async cancellationToken =&gt;\r\n    {\r\n        for (int i = 0; i &lt; 10; i++)\r\n        {\r\n            await Task.Delay(1500, cancellationToken);\r\n            Console.WriteLine($&quot;PDF generating... {i}&quot;);\r\n        }\r\n\r\n        var httpClient = httpClientFactory.CreateClient();\r\n        await httpClient.PostAsJsonAsync(\r\n            requestUri: callbackUrl,\r\n            value: new\r\n            {\r\n                JobId = jobId,\r\n                Status = &quot;Completed&quot;,\r\n                DownloadUrl = &quot;https:\/\/example.com\/result.pdf&quot;\r\n            }\r\n        );\r\n    });\r\n\r\n    return TypedResults.Ok(new\r\n    {\r\n        jobId = jobId\r\n    });\r\n});\r\n<\/pre>\n<\/div>\n<p>Yukar\u0131daki \u00e7al\u0131\u015fmay\u0131 incelerseniz e\u011fer uzun s\u00fcre vakit alacak olan request&#8217;in i\u015flemini <em>JobStore<\/em>&#8216;a yazmak yerine bir callback i\u015flemi e\u015fli\u011finde yine bir queue&#8217;ya almaktay\u0131z. \u0130\u015flem bitti\u011fi taktirde g\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere callback tetiklenecektir. Bu callback endpoint&#8217;ini de a\u015fa\u011f\u0131daki gibi tasarlayabiliriz:<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\napp.MapPost(&quot;\/api\/report-completed&quot;, (ReportCompletedRequest request, ILogger&lt;Program&gt; logger) =&gt;\r\n{\r\n    Console.WriteLine($&quot;{request.JobId} | {request.Status} | {request.DownloadUrl}&quot;);\r\n    return Results.Ok();\r\n});\r\n<\/pre>\n<\/div>\n<\/li>\n<li><strong><em>Workflow Engine<\/em><\/strong><br \/>\nBaz\u0131 i\u015fler ise tek bir metottan ibaret olmamaktad\u0131r. Haliyle gelen request neticesinde birden fazla metot, hatta d\u0131\u015f servis ve hatta distributed bir sistem tetiklenmeye ba\u015flayabilir. \u0130\u015fte b\u00f6yle durumlar i\u00e7in queue tek ba\u015f\u0131na yeterli olmayacakt\u0131r. Burada devreye workflow yakla\u015f\u0131m\u0131 girebilir. Bunun i\u00e7in sizlere \u00f6nerebilece\u011fim en \u00e7a\u011fda\u015f ve etkin workflow teknolojisi <a href=\"https:\/\/www.gencayyildiz.com\/blog\/aspire-ile-nette-dapr-workflows-olusturma\/\" target=\"_blank\">Dapr Workflow<\/a>&#8216;dur. Bu yakla\u015f\u0131m sayesinde sistemin state&#8217;ini rahatl\u0131kla tutabilir, retry&#8217;\u0131 kolayca yap\u0131land\u0131rabilirsiniz. Ayr\u0131ca ihtiya\u00e7 do\u011frultusunda compensation uygulayabilir, timeout y\u00f6netimi sa\u011flayabilir ve t\u00fcm bu s\u00fcreci durable execution ile sa\u011fl\u0131kl\u0131 bir \u015fekilde y\u00f6netebilirsiniz.\n<\/li>\n<li><strong><em>Streaming<\/em><\/strong><br \/>\nYo\u011fun ve uzun da olsa baz\u0131 request&#8217;lerin neticelerini beklemek i\u015f mant\u0131\u011f\u0131 gere\u011fi zaruri olabilmektedir. B\u00f6yle durumlarda gelen request&#8217;in neticesini stream bir \u015fekilde response edebiliriz. Bunun i\u00e7in <a href=\"https:\/\/www.gencayyildiz.com\/blog\/net-10-asp-net-core-ile-server-sent-events-sse-gercek-zamanli-iletisimin-yeni-yuzu\/\" target=\"_blank\">Server-Sent Events (SSE)<\/a> veya <a href=\"https:\/\/www.gencayyildiz.com\/blog\/category\/grpc\/\" target=\"_blank\">gRPC Streaming<\/a> gibi \u00e7\u00f6z\u00fcmlere gidilebilir. Bu \u00e7\u00f6z\u00fcmlerde connection s\u00fcrekli a\u00e7\u0131k kalacak ancak client veya kullan\u0131c\u0131 verisel i\u015fleyi\u015f bak\u0131m\u0131ndan ilerlemeyi hissediyor olacakt\u0131r.\n<\/li>\n<\/ul>\n<p>Burada inceledi\u011fimiz y\u00f6ntemlerde ele ald\u0131\u011f\u0131m\u0131z bellek i\u00e7i (in-memory) kuyruk (queue) yakla\u015f\u0131m\u0131na ek olarak, bir veritaban\u0131 tabanl\u0131 \u00e7\u00f6z\u00fcmden de yararlan\u0131labilir. Esas olan, belirlenen amaca ula\u015fmakt\u0131r. Bu yakla\u015f\u0131mlar\u0131n temel hedefi, \u00f6zellikle endpoint&#8217;lerde meydana gelebilecek ani y\u00fck art\u0131\u015flar\u0131 kar\u015f\u0131s\u0131nda sistemi daha dayan\u0131kl\u0131 ve g\u00fcvenilir h\u00e2le getirmektir.<\/p>\n<p>K\u0131saca \u00f6zetlersek;<\/p>\n<ul>\n<li>Gelen request&#8217;ler i\u00e7erisinde yava\u015f ya da uzun vadeli i\u015flerin optimize edilmesi gerekmektedir. Bir \u015fekilde bunlar\u0131n arka planda ya da farkl\u0131 bir ba\u011flamda \u00e7\u00f6z\u00fclmesi gerekmektedir.<\/li>\n<li>Endpoint i\u00e7erisinde <code>Task.Run<\/code> gibi ka\u00e7\u0131\u015f y\u00f6ntemlerinden uzak durulmal\u0131d\u0131r. Gerekirse i\u015flem bir queue&#8217;ya al\u0131nmal\u0131d\u0131r ama ekstradan bir thread olu\u015fturmaktan ka\u00e7\u0131n\u0131lmal\u0131d\u0131r!<\/li>\n<li>\u0130\u015flem tamamland\u0131\u011f\u0131nda ise kullan\u0131c\u0131 yahut client bilgilendirilmelidir! Evet, belirli periyotta i\u015flemin durumunu yoklama y\u00f6ntemiyle kontrol etmek iyi olabilir, ancak anl\u0131k bildirim daha iyidir!<\/li>\n<\/ul>\n<p>\u0130lgilenenlerin faydalanmas\u0131 dile\u011fiyle&#8230;<br \/>\nSonraki yaz\u0131lar\u0131mda g\u00f6r\u00fc\u015fmek \u00fczere&#8230;<br \/>\n\u0130yi \u00e7al\u0131\u015fmalar&#8230;<\/p>\n<div style=\"max-width:720px;margin:24px auto;padding:18px 20px;border-radius:12px;background:linear-gradient(135deg,#0d1117,#161b22);border:1px solid #30363d;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Arial,sans-serif;color:#e6edf3;box-shadow:0 10px 30px rgba(0,0,0,.35);\">\n<div style=\"display:flex;align-items:center;gap:14px;margin-bottom:12px;\">\n    <svg style=\"width:34px;height:34px;fill:#58a6ff;flex-shrink:0;\" viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n      <path d=\"M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82a7.65 7.65 0 012-.27c.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z\"><\/path>\n    <\/svg><\/p>\n<div>\n<div style=\"font-size:18px;font-weight:600;line-height:1.2;\">\u00d6rnek \u00e7al\u0131\u015fmaya a\u015fa\u011f\u0131daki GitHub reposundan eri\u015febilirsiniz.<\/div>\n<div style=\"font-size:13px;color:#8b949e;\">https:\/\/github.com\/gncyyldz\/AspNetCore.ApiScalingPatterns<\/div>\n<\/p><\/div>\n<\/p><\/div>\n<div style=\"font-size:14px;line-height:1.6;color:#c9d1d9;margin-bottom:14px;\">\n    Bu repository, ilgili konuya dair \u00f6rnek \u00e7al\u0131\u015fman\u0131n kaynak kodlar\u0131n\u0131 ve mimari yap\u0131s\u0131n\u0131 i\u00e7ermektedir. Detaylar i\u00e7in GitHub \u00fczerinden incelemede bulunabilirsiniz.\n  <\/div>\n<p>  <a href=\"https:\/\/github.com\/gncyyldz\/AspNetCore.ApiScalingPatterns\" target=\"_blank\" rel=\"noopener noreferrer\"\n     style=\"display:inline-block;padding:10px 16px;border-radius:8px;background:#238636;color:#ffffff;text-decoration:none;font-size:14px;font-weight:600;transition:all .2s ease;\"><br \/>\n    GitHub\u2019da G\u00f6r\u00fcnt\u00fcle \u2192<br \/>\n  <\/a><\/p>\n<\/div>\n<!-- AddThis Advanced Settings generic via filter on the_content --><!-- AddThis Share Buttons generic via filter on the_content -->","protected":false},"excerpt":{"rendered":"<p>Merhaba, Geli\u015ftirdi\u011fimiz uygulamalar\u0131m\u0131zda illa ki tamamlanmas\u0131 dakikalarca s\u00fcren bir endpoint&#8217;in ortaya \u00e7\u0131kmas\u0131 neredeyse ka\u00e7\u0131n\u0131lmazd\u0131r. Misal olarak; y\u0131llarca toplanan verilerin istatistiki olarak raporlanmas\u0131 gerekti\u011fi durumlarda, toplu veri aktar\u0131mlar\u0131nda veya response d\u00f6nd\u00fcr\u00fclmeden \u00f6nce birka\u00e7 servise ve&#46;&#46;&#46;<!-- AddThis Advanced Settings generic via filter on get_the_excerpt --><!-- AddThis Share Buttons generic via filter on get_the_excerpt --><\/p>\n","protected":false},"author":1,"featured_media":28859,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5206,10,3102],"tags":[2679],"class_list":["post-28850","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-net","category-asp-net","category-asp-net-core","tag-asp-net-core"],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/28850","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/comments?post=28850"}],"version-history":[{"count":9,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/28850\/revisions"}],"predecessor-version":[{"id":28861,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/28850\/revisions\/28861"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media\/28859"}],"wp:attachment":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media?parent=28850"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/categories?post=28850"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/tags?post=28850"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}