সমস্ত অনুরোধের জন্য আমাদের কি এইচটিটিপিপ্লিনেন্টের একটি নতুন একক দৃষ্টান্ত তৈরি করা উচিত?


57

সম্প্রতি আমি এসপ নেট দানবদের এই ব্লগ পোস্টটি জুড়ে এসেছি যা HttpClientনিম্নলিখিত উপায়ে ব্যবহার করে সমস্যাগুলি সম্পর্কে আলোচনা করে :

using(var client = new HttpClient())
{
}

ব্লগ পোস্ট অনুসারে, আমরা HttpClientপ্রতিটি অনুরোধের পরে যদি তা নিষ্পত্তি করি তবে এটি টিসিপি সংযোগগুলি উন্মুক্ত রাখতে পারে। এটি সম্ভাব্যভাবে বাড়ে System.Net.Sockets.SocketException

পোস্ট অনুসারে সঠিক উপায় হ'ল HttpClientএটি সকেটের বর্জ্য হ্রাস করতে সাহায্য করার একটি একক উদাহরণ তৈরি করা ।

পোস্ট থেকে:

যদি আমরা এইচটিপিপ্লিয়েন্টের একক উদাহরণ ভাগ করে নিই তবে আমরা সকেটের অপব্যবহারগুলি পুনরায় ব্যবহার করে হ্রাস করতে পারি:

namespace ConsoleApplication
{
    public class Program
    {
        private static HttpClient Client = new HttpClient();
        public static void Main(string[] args)
        {
            Console.WriteLine("Starting connections");
            for(int i = 0; i<10; i++)
            {
                var result = Client.GetAsync("http://aspnetmonsters.com").Result;
                Console.WriteLine(result.StatusCode);
            }
            Console.WriteLine("Connections done");
            Console.ReadLine();
        }
    }
}

আমি HttpClientএটি ব্যবহার করার পরে অবজেক্টটিকে সর্বদা নিষ্পত্তি করেছি কারণ আমি অনুভব করেছি যে এটি ব্যবহারের সর্বোত্তম উপায়। তবে এই ব্লগ পোস্টটি এখন আমাকে অনুভব করে যে আমি এত দিন এটি ভুল করে চলেছি।

HttpClientসকল অনুরোধের জন্য আমাদের কি নতুন একক দৃষ্টান্ত তৈরি করা উচিত ? স্থির দৃষ্টান্ত ব্যবহারের কোনও ক্ষতি আছে কি?


আপনি যেভাবে এটি ব্যবহার করছেন তাতে আপনার দ্বারা দায়ী হওয়া কোনও সমস্যার মুখোমুখি হয়েছেন?
হোসনেম

হয়তো পরীক্ষা এই উত্তর এবং এই
জন উ

@ উটসিসনাম না, আমার কাছে নেই তবে ব্লগটি দেখে আমার মনে হয়েছে যে আমি এই ভুলটি সর্বদা ব্যবহার করতে পারি। সুতরাং, সহযোগী বিকাশকারীদের কাছ থেকে তারা উভয় পদ্ধতির কোনও সমস্যা দেখলে বুঝতে চেয়েছিলেন।
অঙ্কিত বিজয়

3
আমি নিজে চেষ্টা করে দেখিনি (তাই এটি উত্তর হিসাবে সরবরাহ করে না), কিন্তু নেট নেট ২.১ অনুযায়ী মাইক্রোসফ্টের মতে আপনি ডকুমেন্টস.মাইক্রোসফট.ইন.স. …
জোয়েরি সেব্রিচটস

(আমার উত্তরে যেমন বলা হয়েছে, কেবল এটি আরও দৃশ্যমান করে তুলতে চেয়েছিলাম, তাই আমি একটি ছোট মন্তব্য লিখছি)) স্ট্যাটিক উদাহরণটি টিসিপি সংযোগ বন্ধ হ্যান্ডশেককে সঠিকভাবে পরিচালনা করবে, একবার আপনি কোনও কাজ করার পরে Close()বা কোনও নতুন কাজ শুরু করবেন Get()। আপনি যখন ক্লায়েন্টটি সম্পন্ন করার পরে কেবল এটির নিষ্পত্তি করেন, বন্ধ হ্যান্ডশেক পরিচালনা করার কেউ নেই এবং আপনার পোর্টগুলির সমস্তগুলির জন্য TIME_WAIT অবস্থা থাকবে।
ম্লাদেন বি।

উত্তর:


39

মনে হচ্ছে এটি একটি বাধ্যতামূলক ব্লগ পোস্টের মতো। যাইহোক, সিদ্ধান্ত নেওয়ার আগে আমি প্রথমে একই পরীক্ষাগুলি চালাতাম যা ব্লগ লেখক দৌড়েছিলেন তবে আপনার নিজের কোডে। এইচটিপিপিলেট এবং এর আচরণ সম্পর্কে আমি আরও কিছু চেষ্টা করে দেখতে চাই।

এই পোস্টে বলা হয়েছে:

এইচটিটিপিপ্লায়েন্ট উদাহরণস্বরূপ কার্যকর হওয়া সমস্ত অনুরোধের জন্য প্রয়োগ করা সেটিংসের সংগ্রহ। তদ্ব্যতীত, প্রতিটি এইচটিটিপিপ্লিনেন্ট তার নিজস্ব সংযোগ পুল ব্যবহার করে, অন্যান্য এইচটিপিপিপ্লায়েন্ট উদাহরণস্বরূপ সম্পাদিত অনুরোধগুলি থেকে তার অনুরোধগুলি পৃথক করে।

সুতরাং যখন কোনও এইচটিপিপিলেটটি ভাগ করা হয় তখন যা ঘটে থাকে তা হ'ল সংযোগগুলি পুনরায় ব্যবহার করা হচ্ছে, যা আপনার যদি অবিচ্ছিন্ন সংযোগের প্রয়োজন না হয় তবে তা ঠিক। আপনার অবস্থার জন্য এই বিষয়গুলি আপনার নিজের পারফরম্যান্স পরীক্ষা চালানো কিনা তা আপনি নিশ্চিতভাবে জানতে পারবেন way

যদি আপনি খনন করেন, আপনি অন্যান্য বেশ কয়েকটি সংস্থান খুঁজে পাবেন যা এই সমস্যাটিকে সম্বোধন করে (মাইক্রোসফ্টের সেরা অনুশীলন নিবন্ধ সহ), সুতরাং যাইহোক (কিছু সতর্কতা অবলম্বন করে) এটি কার্যকর করা সম্ভবত ভাল ধারণা।

তথ্যসূত্র

আপনি HTTPClient ভুল ব্যবহার করছেন এবং এটি আপনার সফ্টওয়্যার
সিঙ্গলটন এইচটিটিপি ক্লিনেন্টকে অস্থিতিশীল করছে? এই গুরুতর আচরণ এবং এটি কীভাবে সংশোধন করা যায় সে সম্পর্কে সাবধান হন
- পারফরম্যান্স অপটিমাইজেশন: অনুপযুক্ত ইনস্ট্যানটিশন
কোড রিভিউতে পুনরায় ব্যবহারযোগ্য এইচটিটিপি ক্লিনেন্টের একক উদাহরণ
সিঙ্গলটন এইচটিটিপিএলসিএনটি ডিএনএস পরিবর্তনগুলিকে সম্মান করে না (কোরিএফএক্স)
এইচটিটিপিসিলেট ব্যবহারের জন্য সাধারণ পরামর্শ


1
এটি একটি ভাল বিস্তৃত তালিকা। এটি আমার সপ্তাহান্তে পড়া।
অঙ্কিত বিজয়

"যদি আপনি খনন করেন, আপনি আরও বেশ কয়েকটি সংস্থান খুঁজে পাবেন যা এই সমস্যাটিকে সম্বোধন করবে ..." আপনি টিসিপি সংযোগটি ওপেন ইস্যু বলতে চাইছেন?
অঙ্কিত বিজয়

সংক্ষিপ্ত উত্তর: একটি স্ট্যাটিক এইচটিপিপিলেট ব্যবহার করুন । আপনার যদি ডিএনএস পরিবর্তনগুলি (আপনার ওয়েব সার্ভার বা অন্যান্য সার্ভারগুলির) সমর্থন করতে হয় তবে আপনার সময়সামগ্রী সেটিংস সম্পর্কে চিন্তা করতে হবে।
জেস

3
এটি হ'ল এইচটিপিপ্লায়েন্টকে কীভাবে বিশৃঙ্খলা করল তার প্রমাণ that
usr ডিরেক্টরির

ডিএসএসের পরিবর্তে @ জেস - একক সকেটের মাধ্যমে আপনার ক্লায়েন্টের সমস্ত ট্র্যাফিক নিক্ষেপ করলে কি ভার ভারসাম্য হবে?
আইয়েন

16

আমি পার্টিতে দেরি করেছি, তবে এই কৌশলটি নিয়ে আমার শেখার যাত্রা এখানে।

১. এইচটিপিপিলেটকে পুনরায় ব্যবহার করার ক্ষেত্রে আমরা সরকারী আইনজীবী কোথায় পাব?

আমি বোঝাতে চাইছি, যদি এইচটিপিপ্লিয়েন্টকে পুনরায় ব্যবহারের উদ্দেশ্য হয় এবং তা করা গুরুত্বপূর্ণ হয় তবে এ জাতীয় উকিলগুলি তার নিজস্ব এপিআই ডকুমেন্টেশনে আরও বেশি "অ্যাডভান্সড টপিকস", "পারফরম্যান্স (অ্যান্টি) প্যাটার্ন" বা অন্য ব্লগ পোস্টগুলিতে লুকিয়ে থাকা থেকে নথিভুক্ত থাকে is । নইলে নতুন শিক্ষার্থী খুব দেরী হওয়ার আগে এটি জানার কথা কীভাবে?

এখন অবধি (মে 2018), গুগল করার সময় প্রথম অনুসন্ধান ফলাফল এমএসডিএন-তে এই এপিআই রেফারেন্স পৃষ্ঠাটিতে নির্দেশ করে , যা এই উদ্দেশ্যটির মোটেও উল্লেখ করে না। ঠিক আছে, নবাগতদের জন্য এখানে পাঠ 1 টি হ'ল এমএসডিএন সহায়তা পৃষ্ঠার শিরোনামের ঠিক পরে "অন্যান্য সংস্করণ" লিঙ্কটি ক্লিক করুন, আপনি সম্ভবত "বর্তমান সংস্করণ" এর লিঙ্কগুলি খুঁজে পাবেন। এই এইচটিটিপিপ্লায়েন্টের ক্ষেত্রে, এটি আপনাকে সেই উদ্দেশ্যে উদ্দেশ্যটির বিবরণ সহ এখানে সর্বশেষ নথিতে নিয়ে আসবে ।

আমার সন্দেহ হয় যে অনেক বিকাশকারী যারা এই বিষয়টিতে নতুন ছিলেন তারা সঠিক ডকুমেন্টেশন পৃষ্ঠাটিও খুঁজে পাননি, এ কারণেই এই জ্ঞানটি ব্যাপকভাবে ছড়িয়ে যায় না, এবং লোকেরা যখন পরে এটি খুঁজে পেল তখন সম্ভবত তারা খুব কঠিনভাবে আবিষ্কার করেছিল

2. (ভুল?) ধারণা using IDisposable

এই এক সামান্য প্রসঙ্গ-বহির্ভূত কিন্তু এখনও যে ইশারা, এটা অনুযোগ কিভাবে এই উপরোক্ত ব্লগ পোস্ট ব্যক্তিদের দেখতে একটি কাকতালীয় নয় সাধ্যমতো HttpClient'র IDisposableইন্টারফেস তোলে তাদের ব্যবহারের প্রবণতা using (var client = new HttpClient()) {...}প্যাটার্ন এবং তারপর সমস্যা হতে।

আমি বিশ্বাস করি যে অব্যক্ত (ভুল?) ধারণার অবতারণা হয়েছে : "একটি আইডিস্পোজযোগ্য অবজেক্টটি স্বল্পস্থায়ী হওয়ার আশা করা যায়"

যাইহোক, যখন আমরা এই স্টাইলে কোড লিখি তখন এটি অবশ্যই একটি স্বল্প-কালীন জিনিসের মতো লাগে:

using (var foo = new SomeDisposableObject())
{
    ...
}

IDisposable অফিসিয়াল ডকুমেন্টেশন কখনো উল্লেখ IDisposableবস্তু স্বল্পস্থায়ী হতে হবে। সংজ্ঞা অনুসারে, আইডিস্পোজেবল কেবল আপনাকে নিয়ন্ত্রণহীন সংস্থানগুলি ছাড়ার অনুমতি দেওয়ার একটি ব্যবস্থা। বেশি কিছু না. সেই অর্থে, অবশেষে নিষ্পত্তিটি ট্রিগার করতে আপনি ব্যর্থ, তবে স্বল্প-কালীন ফ্যাশনে এটি করার প্রয়োজন হয় না।

অতএব আপনার বাস্তব বস্তুর জীবনচক্রের প্রয়োজনীয়তার ভিত্তিতে নিষ্পত্তি কখন ট্রিগার করতে হবে তা সঠিকভাবে চয়ন করা আপনার কাজ। আপনাকে দীর্ঘায়িত উপায়ে আইডিস্পোসেবল ব্যবহার করা থেকে বিরত করার কিছুই নেই:

using System;
namespace HelloWorld
{
    class Hello
    {
        static void Main()
        {
            Console.WriteLine("Hello World!");

            using (var client = new HttpClient())
            {
                for (...) { ... }  // A really long loop

                // Or you may even somehow start a daemon here

            }

            // Keep the console window open in debug mode.
            Console.WriteLine("Press any key to exit.");
            Console.ReadKey();
        }
    }
}

এই নতুন বোঝাপড়ার সাথে, এখন আমরা সেই ব্লগ পোস্টটিতে পুনরায় ঘুরে দেখি , আমরা স্পষ্টভাবে লক্ষ্য করতে পারি যে "ফিক্স" HttpClientএকবারে আরম্ভ করে তবে কখনও তা নিষ্পত্তি করে না, এজন্য আমরা এর নেটস্যাট আউটপুট থেকে দেখতে পাচ্ছি যে সংযোগটি ESTABLISHED অবস্থায় রয়েছে যার অর্থ এটি রয়েছে সঠিকভাবে বন্ধ করা হয়নি। যদি এটি বন্ধ করা হয়, তবে তার রাজ্যটি পরিবর্তে TIME_WAIT এ থাকবে। বাস্তবে, আপনার পুরো প্রোগ্রামটি শেষ হওয়ার পরে কেবল একটি সংযোগ খোলা বড় কথা নয় এবং ব্লগ পোস্টার এখনও ঠিক করার পরে একটি পারফরম্যান্স লাভ দেখতে পাবে; তবে তবুও, আইডিস্পোজেবলকে দোষ দেওয়া এবং এটি নিষ্পত্তি না করা চয়ন করা ধারণাগতভাবে ভুল।

৩. আমাদের কি এইচটিপিপ্লিয়েন্টকে একটি স্থিতিশীল সম্পত্তিতে রাখতে হবে, বা এমনকি এটি সিঙ্গলটন হিসাবে রাখতে হবে?

পূর্ববর্তী বিভাগের বোঝার ভিত্তিতে, আমি মনে করি যে এখানে উত্তরটি পরিষ্কার হয়ে যায়: "অগত্যা নয়"। এটি আপনি কীভাবে আপনার কোডটি সংগঠিত করেন তার উপর নির্ভর করে যতক্ষণ আপনি কোনও HTTPClient এবং পুনরায় ব্যবহার করবেন না (আদর্শভাবে) অবশেষে এটি নিষ্পত্তি করবেন।

হাসিখুশিভাবে, বর্তমান সরকারী দস্তাবেজের মন্তব্য বিভাগেও উদাহরণটি যথাযথভাবে এটি সঠিকভাবে করে না। এটি একটি "গুডকন্ট্রোলার" শ্রেণি সংজ্ঞায়িত করে, যেখানে একটি স্থির এইচটিটিপি ক্লিনেন্ট সম্পত্তি থাকে যা নিষ্পত্তি হবে না; যা উদাহরণ বিভাগের আর একটি উদাহরণ জোর দিয়েছিল তা অমান্য করে : "ডিসপোজ কল করতে হবে ... সুতরাং অ্যাপ্লিকেশন সংস্থান ফাঁস করে না"।

এবং সবশেষে, সিঙ্গলটন এর নিজস্ব চ্যালেঞ্জ ছাড়া নয়।

"কতজন লোক বিশ্বব্যাপী পরিবর্তনশীলকে একটি ভাল ধারণা বলে মনে করেন? কেউ নেই।

কতজন লোক মনে করেন সিঙ্গলটন একটি ভাল ধারণা? কয়েকটি।

কি দেয়? সিঙ্গলেটগুলি গ্লোবাল ভেরিয়েবলগুলির একগুচ্ছ ""

- এই অনুপ্রেরণামূলক বক্তৃতা থেকে উদ্ধৃত, "গ্লোবাল স্টেট এবং সিঙ্গললেটস"

পিএস: স্কেল সংযোগ

এটি এখনকার প্রশ্নোত্তরের সাথে অপ্রাসঙ্গিক, তবে এটি সম্ভবত জানা-জানা। স্কেল সংযোগ ব্যবহারের ধরণটি আলাদা। আপনি SqlConnection পুনরায় ব্যবহার করার জন্য প্রয়োজন হবে না কারণ এটির সংযোগ পুল ভাল যে ভাবে হ্যান্ডেল করবে।

পার্থক্যটি তাদের বাস্তবায়নের পদ্ধতির কারণে ঘটে। প্রতিটি এইচটিপিপিপ্লায়েন্টের নিজস্ব সংযোগ পুল ব্যবহার করা হয় ( এখান থেকে উদ্ধৃত ); কিন্তু SqlConnection নিজেই একটি কেন্দ্রীয় সংযোগ পুল দ্বারা পরিচালিত হয়, অনুযায়ী এই

এবং আপনাকে এখনও স্কেল সংযোগটি নিষ্পত্তি করতে হবে, যেমন আপনি এইচটিপিপ্লিয়েন্টের জন্য করা উচিত।


14

আমি কিছু পরীক্ষা স্থির সঙ্গে কর্মক্ষমতা উন্নতি দেখতে HttpClient। আমি আমার পরীক্ষার জন্য নীচে কোড ব্যবহার করেছি:

namespace HttpClientTest
{
    using System;
    using System.Net.Http;

    class Program
    {
        private static readonly int _connections = 10;
        private static readonly HttpClient _httpClient = new HttpClient();

        private static void Main()
        {
            TestHttpClientWithStaticInstance();
            TestHttpClientWithUsing();
        }

        private static void TestHttpClientWithUsing()
        {
            try
            {
                for (var i = 0; i < _connections; i++)
                {
                    using (var httpClient = new HttpClient())
                    {
                        var result = httpClient.GetAsync(new Uri("http://bing.com")).Result;
                    }
                }
            }
            catch (Exception exception)
            {
                Console.WriteLine(exception);
            }
        }

        private static void TestHttpClientWithStaticInstance()
        {
            try
            {
                for (var i = 0; i < _connections; i++)
                {
                    var result = _httpClient.GetAsync(new Uri("http://bing.com")).Result;
                }
            }
            catch (Exception exception)
            {
                Console.WriteLine(exception);
            }
        }
    }
}

পরীক্ষার জন্য:

  • আমি 10, 100, 1000 এবং 1000 সংযোগ দিয়ে কোডটি চালিয়েছি।
  • গড় পরীক্ষা করতে প্রতিটি পরীক্ষা 3 বার চালান।
  • একবারে একটি পদ্ধতি কার্যকর করা হয়েছে

আমি অনুরোধের HttpClientজন্য নিষ্পত্তি না করে স্থিতিশীল ব্যবহার করে 40% থেকে 60% ইউন এর মধ্যে পারফরম্যান্সের উন্নতি পেয়েছি HttpClient। আমি এখানে ব্লগ পোস্টে পারফরম্যান্স পরীক্ষার ফলাফলের বিশদটি রেখেছি ।


1

টিসিপি সংযোগটি সঠিকভাবে বন্ধ করতে , আমাদের একটি টিআইপি সংযোগ খোলার সময় একটি এফআইএন - এফএন + এসি - এসি প্যাকেট ক্রম (এসআইএন - এসওয়াইএন + এসকে - এসিএকের মতো ) সম্পূর্ণ করতে হবে। আমরা যদি কেবল একটি। ক্লোজ () পদ্ধতি কল করি (সাধারণত কোনও HTTPClient নিষ্পত্তি করার সময় ঘটে থাকে ) এবং আমরা আমাদের নিকটতম অনুরোধ (FIN + ACK সহ) নিশ্চিত করার জন্য দূরবর্তী পক্ষের জন্য অপেক্ষা করি না, আমরা TIME_WAIT স্থিতিতে শেষ করব স্থানীয় টিসিপি বন্দর, কারণ আমরা আমাদের শ্রোতাদের (এইচটিটিপি ক্লিনেন্ট) নিষ্পত্তি করেছি এবং রিমোট পীর আমাদের একবার এফআইএন + এসি প্যাকেট প্রেরণ করার পরে আমরা কোনও বন্দর স্থিতিকে যথাযথ বন্ধ অবস্থায় পুনরায় সেট করার সুযোগ পাইনি।

টিসিপি সংযোগ বন্ধ করার যথাযথ উপায় হ'ল .ক্লোজ () পদ্ধতিটি কল করা এবং আমাদের পক্ষ থেকে অন্য দিকে (FIN + ACK) পৌঁছানোর জন্য কাছের ইভেন্টটির জন্য অপেক্ষা করা। তবেই আমরা আমাদের চূড়ান্ত ACK প্রেরণ করতে পারি এবং এইচটিটিপিপ্লাইয়েন্টটি নিষ্পত্তি করতে পারি।

কেবল যোগ করার জন্য, যদি আপনি এইচটিটিপি অনুরোধগুলি সম্পাদন করে থাকেন তবে টিসিপি সংযোগগুলি উন্মুক্ত রাখা অর্থবোধ করে, কারণ "সংযোগ: কিপ-জীবিত" HTTP শিরোনাম। আরও, আপনি এইচটিটিপি শিরোনাম "সংযোগ: বন্ধ করুন" সেট করে এর পরিবর্তে, রিমোট পিয়ারকে আপনার জন্য সংযোগ বন্ধ করতে বলবেন। এইভাবে, আপনার স্থানীয় পোর্টগুলি সর্বদা সঠিকভাবে TIME_WAIT অবস্থায় থাকার পরিবর্তে বন্ধ থাকবে।


1

এখানে একটি প্রাথমিক এপিআই ক্লায়েন্ট রয়েছে যা এইচটিপিপ্লাইয়েন্ট এবং এইচটিটিপিপ্লায়েন্টহ্যান্ডলারকে দক্ষতার সাথে ব্যবহার করে। আপনি যখন একটি অনুরোধ করার জন্য একটি নতুন এইচটিটিপিপ্লায়েন্ট তৈরি করেন তখন প্রচুর ওভারহেড থাকে। প্রতিটি অনুরোধের জন্য HTTPClient পুনরায় তৈরি করবেন না। যথাসম্ভব এইচটিপিপিপ্লায়েন্ট পুনরায় ব্যবহার করুন ...

using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
//You need to install package Newtonsoft.Json > https://www.nuget.org/packages/Newtonsoft.Json/
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;


public class MyApiClient : IDisposable
{
    private readonly TimeSpan _timeout;
    private HttpClient _httpClient;
    private HttpClientHandler _httpClientHandler;
    private readonly string _baseUrl;
    private const string ClientUserAgent = "my-api-client-v1";
    private const string MediaTypeJson = "application/json";

    public MyApiClient(string baseUrl, TimeSpan? timeout = null)
    {
        _baseUrl = NormalizeBaseUrl(baseUrl);
        _timeout = timeout ?? TimeSpan.FromSeconds(90);    
    }

    public async Task<string> PostAsync(string url, object input)
    {
        EnsureHttpClientCreated();

        using (var requestContent = new StringContent(ConvertToJsonString(input), Encoding.UTF8, MediaTypeJson))
        {
            using (var response = await _httpClient.PostAsync(url, requestContent))
            {
                response.EnsureSuccessStatusCode();
                return await response.Content.ReadAsStringAsync();
            }
        }
    }

    public async Task<TResult> PostAsync<TResult>(string url, object input) where TResult : class, new()
    {
        var strResponse = await PostAsync(url, input);

        return JsonConvert.DeserializeObject<TResult>(strResponse, new JsonSerializerSettings
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        });
    }

    public async Task<TResult> GetAsync<TResult>(string url) where TResult : class, new()
    {
        var strResponse = await GetAsync(url);

        return JsonConvert.DeserializeObject<TResult>(strResponse, new JsonSerializerSettings
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        });
    }

    public async Task<string> GetAsync(string url)
    {
        EnsureHttpClientCreated();

        using (var response = await _httpClient.GetAsync(url))
        {
            response.EnsureSuccessStatusCode();
            return await response.Content.ReadAsStringAsync();
        }
    }

    public async Task<string> PutAsync(string url, object input)
    {
        return await PutAsync(url, new StringContent(JsonConvert.SerializeObject(input), Encoding.UTF8, MediaTypeJson));
    }

    public async Task<string> PutAsync(string url, HttpContent content)
    {
        EnsureHttpClientCreated();

        using (var response = await _httpClient.PutAsync(url, content))
        {
            response.EnsureSuccessStatusCode();
            return await response.Content.ReadAsStringAsync();
        }
    }

    public async Task<string> DeleteAsync(string url)
    {
        EnsureHttpClientCreated();

        using (var response = await _httpClient.DeleteAsync(url))
        {
            response.EnsureSuccessStatusCode();
            return await response.Content.ReadAsStringAsync();
        }
    }

    public void Dispose()
    {
        _httpClientHandler?.Dispose();
        _httpClient?.Dispose();
    }

    private void CreateHttpClient()
    {
        _httpClientHandler = new HttpClientHandler
        {
            AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip
        };

        _httpClient = new HttpClient(_httpClientHandler, false)
        {
            Timeout = _timeout
        };

        _httpClient.DefaultRequestHeaders.UserAgent.ParseAdd(ClientUserAgent);

        if (!string.IsNullOrWhiteSpace(_baseUrl))
        {
            _httpClient.BaseAddress = new Uri(_baseUrl);
        }

        _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(MediaTypeJson));
    }

    private void EnsureHttpClientCreated()
    {
        if (_httpClient == null)
        {
            CreateHttpClient();
        }
    }

    private static string ConvertToJsonString(object obj)
    {
        if (obj == null)
        {
            return string.Empty;
        }

        return JsonConvert.SerializeObject(obj, new JsonSerializerSettings
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        });
    }

    private static string NormalizeBaseUrl(string url)
    {
        return url.EndsWith("/") ? url : url + "/";
    }
}

ব্যবহার:

using (var client = new MyApiClient("http://localhost:8080"))
{
    var response = client.GetAsync("api/users/findByUsername?username=alper").Result;
    var userResponse = client.GetAsync<MyUser>("api/users/findByUsername?username=alper").Result;
}

-5

এইচটিপিপিলেট ক্লাসটি ব্যবহার করার কোনও উপায় নেই। কীটি হ'ল আপনার অ্যাপ্লিকেশনটিকে এমনভাবে আর্কিটেকিং করা যা এর পরিবেশ এবং সীমাবদ্ধতার জন্য অর্থ দেয়।

এইচটিটিপি হ'ল ব্যবহারের জন্য একটি দুর্দান্ত প্রোটোকল যখন আপনার সর্বজনীন এপিআই প্রকাশ করতে হবে। এটি হালকা ওজন কম স্বল্পতা অভ্যন্তরীণ পরিষেবার জন্য কার্যকরভাবে ব্যবহার করা যেতে পারে - যদিও RPC বার্তা সারি প্যাটার্নটি প্রায়শই অভ্যন্তরীণ পরিষেবার জন্য আরও ভাল পছন্দ is

এইচটিটিপি ভাল করার ক্ষেত্রে অনেক জটিলতা রয়েছে।

নিম্নোক্ত বিবেচনা কর:

  1. সকেট তৈরি এবং একটি টিসিপি সংযোগ স্থাপন নেটওয়ার্ক ব্যান্ডউইথ এবং সময় ব্যবহার করে।
  2. HTTP / 1.1 একই সকেটে পাইপলাইন অনুরোধগুলি সমর্থন করে। পূর্ববর্তী প্রতিক্রিয়াগুলির জন্য অপেক্ষা করার প্রয়োজন ছাড়াই একের পর এক একাধিক অনুরোধ প্রেরণ করা - এটি সম্ভবত ব্লগ পোস্টের দ্বারা প্রতিবেদন করা গতির উন্নতির জন্য দায়ী।
  3. ক্যাচিং এবং লোড ব্যালেন্সার - যদি আপনার সার্ভারের সামনে লোড ব্যালেন্সার থাকে তবে আপনার অনুরোধগুলি যথাযথ ক্যাশে শিরোনাম রয়েছে তা নিশ্চিত করে আপনার সার্ভারের উপরের বোঝা হ্রাস করতে পারে এবং ক্লায়েন্টদের কাছে প্রতিক্রিয়াগুলি দ্রুত পেতে পারেন।
  4. কোনও রিসোর্সকে কখনই পোল করবেন না, পর্যায়ক্রমিক প্রতিক্রিয়াগুলি ফেরাতে HTTP চুনকিং ব্যবহার করুন।

তবে সর্বোপরি, পরীক্ষা করুন, পরিমাপ করুন এবং নিশ্চিত করুন। যদি এটি নকশা অনুযায়ী আচরণ না করে তবে আমরা কীভাবে আপনার প্রত্যাশিত ফলাফল অর্জন করতে পারি সে সম্পর্কে নির্দিষ্ট প্রশ্নের উত্তর দিতে পারি answer


4
এটি আসলে জিজ্ঞাসিত কিছু উত্তর দেয় না।
21

আপনি ধরে নিচ্ছেন যে একটি সঠিক উপায় আছে। আমি মনে করি না সেখানে আছে। আমি জানি যে আপনি এটি যথাযথভাবে ব্যবহার করতে হবে, তারপরে এটি কীভাবে আচরণ করে তা পরীক্ষা করুন এবং পরিমাপ করুন এবং তারপরে আপনি খুশি না হওয়া পর্যন্ত আপনার পদ্ধতির সমন্বয় করুন।
মাইকেল শ '

আপনি HTTP ব্যবহার করবেন বা যোগাযোগ করবেন না তা ব্যবহার সম্পর্কে কিছুটা লিখেছিলেন। ওপিতে কোনও নির্দিষ্ট গ্রন্থাগারের উপাদানটি কীভাবে ব্যবহার করা যায় তা সম্পর্কে জিজ্ঞাসা করা হয়েছিল।
হোসনেম

1
@ মিশেলশা: HttpClientপ্রয়োগসমূহ IDisposable। সুতরাং এটি অপেক্ষাকৃত অযৌক্তিক নয় যে এটি একটি স্বল্প-স্থায়ী অবজেক্ট যা নিজের পরে কীভাবে পরিষ্কার করতে জানে, usingপ্রতি বার যখন প্রয়োজন হবে তখন একটি বিবৃতিতে মোড়ানোর জন্য উপযুক্ত । দুর্ভাগ্যক্রমে, আসলে এটি কীভাবে কাজ করে না। ওপিতে লিঙ্ক করা ব্লগ পোস্টটি স্পষ্টভাবে প্রমাণ করে যে এমন সংস্থান রয়েছে (বিশেষত, টিসিপি সকেট সংযোগ) যা usingবিবৃতিটি সুযোগের বাইরে চলে যাওয়ার পরে এবং HttpClientঅবজেক্টটি সম্ভবত নিষ্পত্তি হয়েছে।
রবার্ট হার্ভে

1
আমি সেই চিন্তার প্রক্রিয়াটি বুঝতে পারি। এটি ঠিক যদি আপনি এইচটিটিপি সম্পর্কে আর্কিটেকচার দৃষ্টিকোণ থেকে ভাবছিলেন এবং একই পরিষেবাতে প্রচুর অনুরোধ করার ইচ্ছা পোষণ করেছিলেন - তবে আপনি ক্যাচিং এবং পাইপলাইনের কথা ভাববেন এবং তারপরে এইচটিটিপি ক্লায়েন্টকে একটি স্বল্প লাইভ অবজেক্ট তৈরি করার চিন্তাভাবনা করবে কেবল ভুল মনে হয়। তেমনিভাবে, আপনি যদি বিভিন্ন সার্ভারের কাছে অনুরোধ করে থাকেন এবং সকেটটি লাইভ রেখে কোনও উপকার না পেয়ে থাকেন, তবে এইচটিটিপিপ্লায়েন্ট বস্তুর ব্যবহারের পরে তা নিষ্পত্তি করা অর্থপূর্ণ হয়ে যায়।
মাইকেল শ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.