﻿
{"id":21210,"date":"2021-06-20T14:49:13","date_gmt":"2021-06-20T14:49:13","guid":{"rendered":"https:\/\/www.gencayyildiz.com\/blog\/?p=21210"},"modified":"2021-06-20T14:49:13","modified_gmt":"2021-06-20T14:49:13","slug":"grpc-ile-client-factory-integration","status":"publish","type":"post","link":"https:\/\/www.gencayyildiz.com\/blog\/grpc-ile-client-factory-integration\/","title":{"rendered":"gRPC \u0130le Client Factory Integration"},"content":{"rendered":"<div id=\"fb-root\"><\/div>\n<p>Merhaba,<\/p>\n<p>gRPC k\u00fct\u00fcphanesi, client yap\u0131lanmas\u0131n\u0131 merkezi hale getirip tasar\u0131m\u0131 kolayla\u015ft\u0131rabilmek ve geleneksel gRPC client tasar\u0131mlar\u0131na alternatif olarak daha efektif geli\u015ftirmeler yapabilmek i\u00e7in <em>gRPC Factory Integration<\/em> \u00f6zelli\u011fi sunmaktad\u0131r.<br \/>\n<div id=\"attachment_21211\" style=\"width: 635px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/03\/gRPC-Ile-Client-Factory-Integration.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-21211\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/03\/gRPC-Ile-Client-Factory-Integration.png\" alt=\"gRPC \u0130le Client Factory Integration\" width=\"625\" height=\"22\" class=\"size-full wp-image-21211\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/03\/gRPC-Ile-Client-Factory-Integration.png 625w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/03\/gRPC-Ile-Client-Factory-Integration-300x11.png 300w\" sizes=\"auto, (max-width: 625px) 100vw, 625px\" \/><\/a><p id=\"caption-attachment-21211\" class=\"wp-caption-text\">Geleneksel client yap\u0131lanmas\u0131&#8230;<\/p><\/div><br \/>\nYukar\u0131daki geleneksel yap\u0131lanma, gRPC client tasar\u0131mlar\u0131nda y\u00f6netilebilirlik a\u00e7\u0131s\u0131ndan pek tercih edilebilir bir d\u00fczenleme de\u011fildir. Haliyle bizlere merkezi bir konum \u00fczerinden client tasar\u0131m\u0131n\u0131 sa\u011flayacak olan Factory entegrasyonunu tercih edebiliriz.<\/p>\n<p>Factory Integration&#8217;\u0131 kullanabilmek i\u00e7in temel gRPC k\u00fct\u00fcphanelerinin yan\u0131nda <a href=\"https:\/\/www.nuget.org\/packages\/Grpc.Net.ClientFactory\" rel=\"noopener\" target=\"_blank\">Grpc.Net.ClientFactory<\/a> k\u00fct\u00fcphanesinin uygulamaya y\u00fcklenmesi yeterlidir. \u0130lgili entegrasyonu yapabilmek i\u00e7in &#8216;Startup.cs&#8217; dosyas\u0131nda a\u015fa\u011f\u0131daki gibi <code style=\"color:red;font-size:12px;\">AddGrpcClient<\/code> servisinin \u00e7a\u011fr\u0131lmas\u0131 ve temel konfig\u00fcrasyonlar\u0131n yap\u0131lmas\u0131 gerekmektedir.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class Startup\r\n    {\r\n        public void ConfigureServices(IServiceCollection services)\r\n        {\r\n            services.AddGrpcClient&lt;PersonClient&gt;(o =&gt;\r\n            {\r\n                o.Address = new Uri(&quot;https:\/\/localhost:5001&quot;);\r\n            });\r\n            .\r\n            .\r\n            .\r\n        }\r\n        .\r\n        .\r\n        .\r\n    }\r\n<\/pre>\n<p>Bu i\u015flemden sonra gRPC client s\u0131n\u0131f\u0131 ilgili uygulaman\u0131n IoC container&#8217;\u0131na eklenecektir. Haliyle client ilgili s\u0131n\u0131fa do\u011frudan dependency injection ile eri\u015febilecek ve t\u00fcketebilecektir.<br \/>\nMisal controller&#8217;dan direkt talep edilebilmektedir :<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    &#x5B;Route(&quot;api\/&#x5B;controller]&quot;)]\r\n    &#x5B;ApiController]\r\n    public class PersonController : ControllerBase\r\n    {\r\n        readonly PersonClient _personClient;\r\n        public PersonController(PersonClient personClient)\r\n        {\r\n            _personClient = personClient;\r\n        }\r\n        public async Task&lt;IActionResult&gt; Get()\r\n        {\r\n            var response = _personClient.GetPersons(new());\r\n            while (await response.ResponseStream.MoveNext(new()))\r\n            {\r\n                Console.WriteLine(response.ResponseStream.Current.Name);\r\n            }\r\n            return Ok();\r\n        }\r\n    }\r\n<\/pre>\n<p>Ya da custom bir servis taraf\u0131ndan da \u00e7a\u011fr\u0131labilmektedir :<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class PersonService \r\n    {\r\n        readonly PersonClient _personClient;\r\n        public PersonService(PersonClient personClient)\r\n        {\r\n            _personClient = personClient;\r\n        }\r\n        public async Task GetPersons()\r\n        {\r\n            var response = _personClient.GetPersons(new());\r\n            while (await response.ResponseStream.MoveNext(new()))\r\n            {\r\n                Console.WriteLine(response.ResponseStream.Current.Name);\r\n            }\r\n        }\r\n    }\r\n<\/pre>\n<h6>Interceptor Konfig\u00fcrasyonu<\/h6>\n<p>Client&#8217;tan gelen \u00e7a\u011fr\u0131lara kar\u015f\u0131l\u0131k interceptor&#8217;lar\u0131 a\u015fa\u011f\u0131daki gibi devreye sokabilirsiniz.<br \/>\nInterceptor :<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class CustomInterceptor : Interceptor\r\n    {\r\n        public override AsyncServerStreamingCall&lt;TResponse&gt; AsyncServerStreamingCall&lt;TRequest, TResponse&gt;(TRequest request, ClientInterceptorContext&lt;TRequest, TResponse&gt; context, AsyncServerStreamingCallContinuation&lt;TRequest, TResponse&gt; continuation)\r\n        {\r\n            Console.WriteLine(&quot;Merhaba d\u00fcnya...&quot;);\r\n            return base.AsyncServerStreamingCall(request, context, continuation);\r\n        }\r\n    }\r\n<\/pre>\n<p>Konfig\u00fcrasyon :<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n            services.AddGrpcClient&lt;PersonClient&gt;(o =&gt;\r\n            {\r\n                o.Address = new Uri(&quot;https:\/\/localhost:5001&quot;);\r\n            })\r\n                .AddInterceptor(() =&gt; new CustomInterceptor())\r\n                .AddInterceptor(() =&gt; new CustomInterceptor2());\r\n<\/pre>\n<h6>Channel Konfig\u00fcrasyonu<\/h6>\n<p>Client&#8217;tan gelen \u00e7a\u011fr\u0131lara istinaden basic d\u00fczeyde bir kimlik do\u011frulama i\u015flemi ger\u00e7ekle\u015ftirebilmek i\u00e7in channel konfig\u00fcrasyonunu a\u015fa\u011f\u0131daki gibi devreye sokabilirsiniz.<\/p>\n<p>\u00d6rne\u011fin, gRPC Server&#8217;da base olarak kullan\u0131lan &#8216;PersonService&#8217;in &#8216;Authorize&#8217; edildi\u011fini varsayal\u0131m.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    &#x5B;Authorize]\r\n    public class PersonService : PersonBase\r\n    {\r\n        public async override Task&lt;PersonResponse&gt; GetPerson(Empty request, ServerCallContext context)\r\n        {\r\n            .\r\n            .\r\n            .\r\n        }\r\n        public async override Task GetPersons(Empty request, IServerStreamWriter&lt;PersonResponse&gt; responseStream, ServerCallContext context)\r\n        {\r\n            .\r\n            .\r\n            .\r\n        }\r\n    }\r\n<\/pre>\n<p>Bu servise eri\u015febilmek i\u00e7in JWT ile istek yap\u0131lacaksa e\u011fer bu iste\u011fi client&#8217;ta a\u015fa\u011f\u0131daki gibi &#8216;ConfigureChannel&#8217; metodu ile yap\u0131land\u0131rmak gerekmektedir.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n            services.AddGrpcClient&lt;PersonClient&gt;(o =&gt;\r\n            {\r\n                o.Address = new Uri(&quot;https:\/\/localhost:5001&quot;);\r\n            })\r\n                .AddInterceptor(() =&gt; new CustomInterceptor())\r\n                .AddInterceptor(() =&gt; new CustomInterceptor())\r\n                .ConfigureChannel(option =&gt;\r\n                {\r\n                    option.Credentials = ChannelCredentials.Create(new SslCredentials(), CallCredentials.FromInterceptor((context, metadata) =&gt;\r\n                    {\r\n                        string jwt = &quot;...&quot;;\r\n                        metadata.Add(&quot;Authorization&quot;, $&quot;Bearer {jwt}&quot;);\r\n                        return Task.CompletedTask;\r\n                    }));\r\n                });\r\n<\/pre>\n<h6>Named Clients\/\u0130simlendirilmi\u015f Client&#8217;lar<\/h6>\n<p>Tipik olarak bir gRPC client&#8217;\u0131 bir kez IoC&#8217;ye kaydedilir ve ard\u0131ndan her ihtiya\u00e7 oldu\u011funda dependency injection ile bu nesne talep edilir. Ancak bazen bir istemcinin ayn\u0131 client nesnesine birden fazla konfig\u00fcre edilmi\u015f \u015fekilde sahip olmas\u0131 gerekece\u011fi senaryolar olabilir. Misal olarak bir istemci x client&#8217;\u0131na hem normal olarak sahiptir hem de ilgili client&#8217;\u0131n Credentials bilgileri girilmi\u015f versiyonuna da ihtiyac\u0131 olabilir. \u0130\u015fte b\u00f6yle durumlara istinaden Named Clients \u00f6zelli\u011fi olduk\u00e7a efektif bir \u00e7\u00f6z\u00fcm sunmaktad\u0131r.<\/p>\n<p>Misal :<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n            \/\/Kimlik Do\u011frulamas\u0131z Client\r\n            services.AddGrpcClient&lt;PersonClient&gt;(&quot;PersonClient&quot;, o =&gt;\r\n            {\r\n                o.Address = new Uri(&quot;https:\/\/localhost:5001&quot;);\r\n            });\r\n            \/\/Kimlik Do\u011frulamal\u0131 Client\r\n            services.AddGrpcClient&lt;PersonClient&gt;(&quot;PersonClientAuthenticated&quot;, o =&gt;\r\n            {\r\n                o.Address = new Uri(&quot;https:\/\/localhost:5001&quot;);\r\n            })\r\n            .ConfigureChannel(option =&gt;\r\n            {\r\n                option.Credentials = ChannelCredentials.Create(new SslCredentials(), CallCredentials.FromInterceptor((context, metadata) =&gt;\r\n                {\r\n                    string jwt = &quot;...&quot;;\r\n                    metadata.Add(&quot;Authorization&quot;, $&quot;Bearer {jwt}&quot;);\r\n                    return Task.CompletedTask;\r\n                }));\r\n            });\r\n<\/pre>\n<p>Yukar\u0131daki kod blo\u011funa g\u00f6z atarsan\u0131z e\u011fer &#8216;PersonClient&#8217;\u0131n hem kimlik do\u011frulamal\u0131 hem de kimlik do\u011frulamas\u0131z olmak \u00fczere iki farkl\u0131 konfig\u00fcre edilmi\u015f hali IoC&#8217;ye verilmi\u015ftir ve bu nesneler aras\u0131ndaki fark ilk parametrelerdeki isimlendirmelerle sa\u011flanm\u0131\u015ft\u0131r. Bu ad\u0131mdan sonra ihtiyaca binaen bir nesneyi dependency injection ile elde etmek istiyorsan\u0131z a\u015fa\u011f\u0131daki gibi &#8216;GrpcClientFactory&#8217; nesnesi \u00fczerinden talep etmeniz yeterli olacakt\u0131r.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class PersonService\r\n    {\r\n        readonly PersonClient _personClient;\r\n        readonly PersonClient _personClientAuthenticated;\r\n        public PersonService(GrpcClientFactory grpcClientFactory)\r\n        {\r\n            _personClientAuthenticated = grpcClientFactory.CreateClient&lt;PersonClient&gt;(&quot;PersonClientAuthenticated&quot;);\r\n            _personClient = grpcClientFactory.CreateClient&lt;PersonClient&gt;(&quot;PersonClient&quot;);\r\n        }\r\n        .\r\n        .\r\n        .\r\n    }\r\n<\/pre>\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<!-- AddThis Advanced Settings generic via filter on the_content --><!-- AddThis Share Buttons generic via filter on the_content -->","protected":false},"excerpt":{"rendered":"<p>Merhaba, gRPC k\u00fct\u00fcphanesi, client yap\u0131lanmas\u0131n\u0131 merkezi hale getirip tasar\u0131m\u0131 kolayla\u015ft\u0131rabilmek ve geleneksel gRPC client tasar\u0131mlar\u0131na alternatif olarak daha efektif geli\u015ftirmeler yapabilmek i\u00e7in gRPC Factory Integration \u00f6zelli\u011fi sunmaktad\u0131r. Yukar\u0131daki geleneksel yap\u0131lanma, gRPC client tasar\u0131mlar\u0131nda y\u00f6netilebilirlik&#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":20414,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4032],"tags":[4164,4065,4322,4165,4127,4321,4324,4323],"class_list":["post-21210","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-grpc","tag-factory-integration","tag-grpc","tag-grpc-channel","tag-grpc-factory","tag-grpc-factory-integration","tag-grpc-interceptor","tag-grpc-name-clients","tag-named-clients"],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/21210","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=21210"}],"version-history":[{"count":8,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/21210\/revisions"}],"predecessor-version":[{"id":22100,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/21210\/revisions\/22100"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media\/20414"}],"wp:attachment":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media?parent=21210"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/categories?post=21210"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/tags?post=21210"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}