কীভাবে গোলাংয়ে http.Get () অনুরোধের সময়সীমা নির্ধারণ করবেন?


106

আমি গোতে একটি ইউআরএল ফ্যাচার তৈরি করছি এবং আনার জন্য ইউআরএলগুলির একটি তালিকা রয়েছে। আমি http.Get()প্রতিটি ইউআরএলকে অনুরোধ প্রেরণ এবং তাদের প্রতিক্রিয়া প্রাপ্ত।

resp,fetch_err := http.Get(url)

প্রতিটি অনুরোধের জন্য আমি কীভাবে একটি কাস্টম টাইমআউট সেট করতে পারি? (ডিফল্ট সময়টি খুব দীর্ঘ এবং এটি আমার ফ্যাচারটি সত্যিই ধীর করে দেয়)) আমি চাই আমার ফ্যাচারটির প্রায় 40-45 সেকেন্ডের সময়সীমা শেষ হয় যার পরে এটি "অনুরোধের সময়সীমা শেষ" হয় এবং পরবর্তী URL এ চলে যায়।

আমি কীভাবে এটি অর্জন করতে পারি?


1
কেবল আপনাকে ছেলেদের জানাতেই
অড্রিয়াস

@ অড্রিয়াস কোনও ধারণা নেই যে কোনও সমস্যা আছে যখন ডায়াল টাইমআউট কাজ করে না? আমি মনে করি আমি একই জিনিসটি দেখছি। আমি ভেবেছিলাম ডায়ালটাইমআউটটি কি?!?!?!
জর্ডান

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

উত্তর:


255

যান 1.3 মধ্যে দৃশ্যত http.Client সময়সীমা সমাপ্ত ক্ষেত্র রয়েছে

client := http.Client{
    Timeout: 5 * time.Second,
}
client.Get(url)

এটা আমার জন্য কৌতুক করেছে।


10
ঠিক আছে, এটা আমার পক্ষে যথেষ্ট। খুশি আমি কিছুটা স্ক্রোল করে রেখেছি :)
জেমস অ্যাডাম

5
অনুরোধের জন্য আলাদা আলাদা সময়সীমা রাখার কোনও উপায় আছে কি?
আরনাউড রিনকুইন

11
টাইমআউট হিট হলে কী হবে? না Getএকটি ত্রুটি আসতে? আমি কিছুটা বিভ্রান্ত কারণ গডোক Clientবলেছেন যে: টাইমারটি গেট, হেড, পোস্ট, বা ডু ফেরার পরে চলছে এবং রেসপন্স.বডি পড়তে বাধা দেবে। সুতরাং তার মানে কি বা হয় Get বা পড়া Response.Bodyএকটি ত্রুটি দ্বারা বাধা দেওয়া হতে পারে?
আভি ফ্ল্যাক্স

1
প্রশ্ন, http.Client.Timeoutবনাম মধ্যে পার্থক্য কি http.Transport.ResponseHeaderTimeout?
রায় লি

2
@ রয়লি ডক্স অনুসারে অন্যতম প্রধান পার্থক্য: http.Client.Timeoutপ্রতিক্রিয়া সংস্থার পড়ার সময়কে http.Transport.ResponseHeaderTimeoutঅন্তর্ভুক্ত করে না, এতে অন্তর্ভুক্ত হয় না।

53

আপনাকে নিজের পরিবহন দিয়ে নিজের ক্লায়েন্ট সেট আপ করতে হবে যা একটি কাস্টম ডায়াল ফাংশন ব্যবহার করে যা ডায়ালটাইমআউটের চারপাশে মোড় নেয়

মত (সম্পূর্ণরূপে কিছু অপরীক্ষিত ) এই :

var timeout = time.Duration(2 * time.Second)

func dialTimeout(network, addr string) (net.Conn, error) {
    return net.DialTimeout(network, addr, timeout)
}

func main() {
    transport := http.Transport{
        Dial: dialTimeout,
    }

    client := http.Client{
        Transport: &transport,
    }

    resp, err := client.Get("http://some.url")
}

অনেক ধন্যবাদ! আমি ঠিক এই জিনিসটি খুঁজছিলাম।
পিমড

নেট ব্যবহার করার সুবিধা কী? ট্রান্সপোর্টের ওপরে ডায়ালটাইমআউট.জেপজ এর উত্তর দ্বারা বর্ণিত রেসপনস হেইডারটাইমআউট?
ড্যানিয়েল বি

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

1
@ ভোলকার, আপনার উত্তরের জন্য ধন্যবাদ প্রকৃতপক্ষে আমি এটিও উপলব্ধি করেছিলাম: এটি দেখতে ট্রান্সপোর্টের মতো মনে হয় es ডিমিকেল দ্বারা সমাধান ডায়াল টাইমআউট এবং পড়ার সময়সীমা উভয়ই নিয়ে আসে।
ড্যানিয়েল বি

1
@ জন্নো: গো-তে কোনও কাস্ট নেই। এগুলি ধরণের রূপান্তর।
ভোলকার

31

ভোলকারের উত্তরে যুক্ত করতে, আপনি যদি সংযোগের সময়সীমা ছাড়াও পঠন / লেখার সময়সীমা সেট করতে চান তবে নীচের মতো কিছু করতে পারেন

package httpclient

import (
    "net"
    "net/http"
    "time"
)

func TimeoutDialer(cTimeout time.Duration, rwTimeout time.Duration) func(net, addr string) (c net.Conn, err error) {
    return func(netw, addr string) (net.Conn, error) {
        conn, err := net.DialTimeout(netw, addr, cTimeout)
        if err != nil {
            return nil, err
        }
        conn.SetDeadline(time.Now().Add(rwTimeout))
        return conn, nil
    }
}

func NewTimeoutClient(connectTimeout time.Duration, readWriteTimeout time.Duration) *http.Client {

    return &http.Client{
        Transport: &http.Transport{
            Dial: TimeoutDialer(connectTimeout, readWriteTimeout),
        },
    }
}

এই কোডটি পরীক্ষিত এবং উত্পাদনে কাজ করছে। পরীক্ষাগুলির সাথে সম্পূর্ণ টুকরোটি এখানে উপলব্ধ https://gist.github.com/dmichael/5710968 এ

সচেতন থাকুন যে প্রতিটি অনুরোধের জন্য আপনাকে একটি নতুন ক্লায়েন্ট তৈরি করতে হবে কারণ conn.SetDeadlineএটি ভবিষ্যতে কোনও পয়েন্টের উল্লেখ করেtime.Now()


সংযোগের রিটার্ন মানটি পরীক্ষা করা উচিত নয়? সেটডেডলাইন?
এরিক আরবান

3
এই সময়সীমাটি রক্ষণশীল সংযোগগুলির সাথে কাজ করে না, যা পূর্বনির্ধারিত এবং বেশিরভাগ লোকেরা কী ব্যবহার করা উচিত তা আমি কল্পনা করি। এটি মোকাবেলায় আমি কী নিয়ে এসেছি তা এখানে: gist.github.com/seantalts/11266762
xitrium

অতিরিক্ত ইনপুট দেওয়ার জন্য @xitrium এবং এরিক ধন্যবাদ Thanks
ডিমিকেল

আমার মনে হচ্ছে এটি যেমনটি আপনি বলেছিলেন ঠিক তেমনটি নয় যে প্রতিটি অনুরোধের জন্য আমাদের একটি নতুন ক্লায়েন্ট তৈরি করতে হবে। যেহেতু ডায়াল একটি ফাংশন যা আমি মনে করি এটি প্রতিবার কল হয়ে আসে আপনি একই অনুরোধে প্রতিটি অনুরোধ প্রেরণ করেন।
এ-লেটব্বি

আপনি কি নিশ্চিত যে প্রতিবার নতুন ক্লায়েন্টের প্রয়োজন? প্রতিবার নেট ডায়াল করার পরিবর্তে ডায়াল করছে, এটি টাইমআউটডায়ালার তৈরি ফাংশনটি ব্যবহার করবে। এটি নতুন সংযোগ, প্রতিটি সময়কে নতুন সময় থেকে নির্ধারিত সময়সীমার সাথে। এখন () কল।
ব্লেক ক্যালডওয়েল

16

আপনি যদি অনুরোধ অনুযায়ী এটি করতে চান তবে ব্রেভিটির জন্য অগ্রাহ্য করা ভুল পরিচালনা:

ctx, cncl := context.WithTimeout(context.Background(), time.Second*3)
defer cncl()

req, _ := http.NewRequestWithContext(ctx, http.MethodGet, "https://google.com", nil)

resp, _ := http.DefaultClient.Do(req)

1
অতিরিক্ত তথ্য: প্রতি ডক হিসাবে, প্রসঙ্গ দ্বারা আরোপিত সময়সীমাটি বডিটিও পড়তে থাকে, একইভাবে http.Client.Timeout
kubanczyk

1
Go 1.7+ এর জন্য একটি স্বীকৃত উত্তর হওয়া উচিত। Go 1.13+ এর জন্য NewRequestWithContext
kubanczyk

9

একটি দ্রুত এবং নোংরা উপায়:

http.DefaultTransport.(*http.Transport).ResponseHeaderTimeout = time.Second * 45

এটি বিশ্বব্যাপী রাষ্ট্রের কোনও সমন্বয়কে পরিবর্তন করছে। তবুও এটি সম্ভবত আপনার ইউআরএল সংগ্রহের জন্য ঠিক আছে। অন্যথায় একটি ব্যক্তিগত উদাহরণ তৈরি করুন http.RoundTripper:

var myTransport http.RoundTripper = &http.Transport{
        Proxy:                 http.ProxyFromEnvironment,
        ResponseHeaderTimeout: time.Second * 45,
}

var myClient = &http.Client{Transport: myTransport}

resp, err := myClient.Get(url)
...

উপরের কিছুই পরীক্ষা করা হয়নি।


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

http.DefaultTransport.(*http.Transport).ResponseHeaderTimeout = time.Second * 45অনুরোধ সময়সীমার জন্য লেখার পরীক্ষায় আমাকে অনেক সাহায্য করুন। আপনাকে অনেক ধন্যবাদ.
লী


-1
timeout := time.Duration(5 * time.Second)
transport := &http.Transport{Proxy: http.ProxyURL(proxyUrl), ResponseHeaderTimeout:timeout}

এটি সহায়তা করতে পারে, তবে ResponseHeaderTimeoutসংযোগ স্থাপনের পরেই এটি সূচনা হবে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.