Go context ਟਾਈਮਆਊਟ ਢੀਲੀਆਂ DB ਕਾਲਾਂ ਅਤੇ ਬਾਹਰੀ ਰਿਕੁਏਸਟਾਂ ਨੂੰ ਇਕੱਠਾ ਹੋਣ ਤੋਂ ਰੋਕਦੇ ਹਨ। ਡੇਡਲਾਇਨ ਪ੍ਰਸਾਰ, ਕੈਂਸਲੇਸ਼ਨ ਅਤੇ ਸੁਰੱਖਿਅਤ ਡਿਫਾਲਟ ਸਿੱਖੋ।

ਇੱਕ ਇਕੱਲੀ ਢੀਲੀ ਬੇਨਤੀ ਅਕਸਰ "ਸਿਰਫ ਢੀਲੀ" ਨਹੀਂ ਹੁੰਦੀ। ਜਦੋਂ ਇਹ ਉਡੀਕ ਕਰਦੀ ਹੈ, ਇਹ ਇੱਕ ਗੋਰੁਟੀਨ ਨੂੰ ਜਿਊਂਦਾ ਰੱਖਦੀ ਹੈ, ਬਫਰਾਂ ਅਤੇ ਰਿਸਪਾਂਸ ਆਬਜੈਕਟਾਂ ਲਈ ਮੈਮੋਰੀ ਰੱਖਦੀ ਹੈ, ਅਤੇ ਅਕਸਰ ਡਾਟਾਬੇਸ ਕਨੈਕਸ਼ਨ ਜਾਂ ਪੂਲ ਵਿੱਚ ਇੱਕ ਸਲਾਟ ਘੇਰ ਲੈਦੀ ਹੈ। ਜਦੋਂ ਕਾਫੀ ਢੀਲੀਆਂ ਬੇਨਤੀਆਂ ਇਕੱਠੀਆਂ ਹੋ ਜਾਂਦੀਆਂ ਹਨ, ਤੁਹਾਡੀ API ਲਾਗੂ ਕੰਮ ਕਰਨਾ ਬੰਦ ਕਰ ਦਿੰਦੀ ਹੈ ਕਿਉਂਕਿ ਇਸਦੇ ਸੀਮਤ ਸਰੋਤ ਉਡੀਕ ਵਿੱਚ ਫਸੇ ਹੋਏ ਹੁੰਦੇ ਹਨ।
ਤੁਸੀਂ ਇਹ ਤਿੰਨ ਥਾਵਾਂ 'ਤੇ ਮਹਿਸੂਸ ਕਰਦੇ ਹੋ: ਗੋਰੁਟੀਨ ਇਕੱਠੇ ਹੋ ਜਾਂਦੇ ਹਨ ਅਤੇ ਸ਼ੇਡੀੂਲਿੰਗ ਓਵਰਹੈਡ ਵੱਧਦਾ ਹੈ, ਜਿਸ ਨਾਲ ਹਰ ਕਿਸੇ ਲਈ ਲੇਟੇੰਸੀ ਖਰਾਬ ਹੋ ਜਾਂਦੀ ਹੈ। ਡਾਟਾਬੇਸ ਪੂਲ ਖਾਲੀ ਕਨੈਕਸ਼ਨਾਂ ਤੋਂ ਖ਼ਤਮ ਹੋ ਜਾਂਦੇ ਹਨ, ਇਸ ਲਈ ਤੇਜ਼ ਕੁਏਰੀਆਂ ਵੀ ਢੀਲੀਆਂ ਦੇ ਪਿੱਛੇ ਕਤਾਰ ਵਿੱਚ ਲੱਗ ਜਾਣਦੀਆਂ ਹਨ। ਇਨ-ਫਲਾਈਟ ਡੇਟਾ ਅਤੇ ਅਧ-ਬਣੇ ਰਿਸਪਾਂਸਾਂ ਤੋਂ ਮੈਮੋਰੀ ਵਧਦੀ ਹੈ, ਜੋ GC ਦਾ ਕੰਮ ਵਧਾਉਂਦੀ ਹੈ।
ਹੋਰ ਸਰਵਰ ਜੋੜਨ ਨਾਲ ਅਕਸਰ ਇਹ ਮੁੱਦਾ ਹੱਲ ਨਹੀਂ ਹੁੰਦਾ। ਜੇ ਹਰ ਇੰਸਟੈਂਸ ਉਹੀ ਬੋਤਲਗਲ (ਛੋਟਾ DB ਪੂਲ, ਇੱਕ ਢੀਲਾ ਅਪਸਟਰੀਮ, ਸਾਂਝੇ ਰੇਟ ਲਿਮਿਟ) ਭੁਗਤ ਰਿਹਾ ਹੈ, ਤਾਂ ਤੁਸੀਂ ਬਸ ਕਤਾਰ ਨੂੰ ਹੋਰ ਜਗ੍ਹਾ ਭੇਜਦੇ ਹੋ ਅਤੇ ਵੱਧ ਖਰਚ ਕਰਦੇ ਹੋ ਪਰ ਐਰਰ ਫਿਰ ਵੀ ਆਉਂਦੇ ਹਨ।
ਇੱਕ ਹੈਂਡਲਰ ਸੋਚੋ ਜੋ ਫੈਨ ਆਉਟ ਹੁੰਦਾ ਹੈ: ਇਹ PostgreSQL ਤੋਂ ਯੂਜ਼ਰ ਲੋਡ ਕਰਦਾ ਹੈ, ਇੱਕ ਪੇਮੈਂਟਸ ਸੇਵਾ ਨੂੰ ਕਾਲ ਕਰਦਾ ਹੈ, ਫਿਰ ਇੱਕ ਸਿਫ਼ਾਰਸ਼ੀ ਸੇਵਾ ਨੂੰ ਕਾਲ ਕਰਦਾ ਹੈ। ਜੇ ਸਿਫ਼ਾਰਸ਼ੀ ਕਾਲ ਹੰਗ ਹੋ ਜਾਵੇ ਅਤੇ ਕੁਝ ਵੀ ਇਸਨੂੰ ਰੱਦ ਨਾ ਕਰੇ, ਤਾਂ ਰਿਕੁਏਸਟ ਕਦੇ ਮੁਕੰਮਲ ਨਹੀਂ ਹੁੰਦੀ। ਡੀਬੀ ਕਨੈਕਸ਼ਨ ਵਾਪਸ ਮਿਲ ਸਕਦੀ ਹੈ, ਪਰ ਗੋਰੁਟੀਨ ਅਤੇ HTTP ਕਲਾਇੰਟ ਸਰੋਤ ਫਸੇ ਰਿਹਾਂਦੇ ਹਨ। ਇਸਨੂੰ ਸੈਂਕੜੇ ਰਿਕੁਏਸਟਾਂ ਨਾਲ ਗੁਣਾ ਕਰੋ ਤੇ ਤੁਸੀਂ ਇੱਕ ਢੀਲਾ ਮੈਲਟਡਾਊਨ ਪਾਉਂਦੇ ਹੋ।
ਮਕਸਦ ਸਾਦਾ ਹੈ: ਇੱਕ ਸਾਫ਼ ਸਮਾਂ ਸੀਮਾ ਰੱਖੋ, ਸਮਾਂ ਖਤਮ ਹੋਣ ਤੇ ਕੰਮ ਰੋਕ ਦਿਓ, ਸਰੋਤ ਛੱਡ ਦਿਓ, ਅਤੇ ਇੱਕ ਪੇਸ਼ਗੋਈਯੋਗ ਐਰਰ ਵਾਪਸ ਕਰੋ। Go context ਟਾਈਮਆਊਟ ਹਰ ਕਦਮ ਨੂੰ ਇੱਕ ਡੇਡਲਾਇਨ ਦਿੰਦੇ ਹਨ ਤਾਂ ਜੋ ਯੂਜ਼ਰ ਜਦੋਂ ਹੋਰ ਉਡੀਕ ਨਹੀਂ ਕਰ ਰਿਹਾ, ਕੰਮ ਰੁੱਕ ਜਾਵੇ।
context.Context ਇੱਕ ਛੋਟਾ ਆਬਜੈਕਟ ਹੈ ਜੋ ਤੁਸੀਂ ਆਪਣੇ ਕਾਲ ਚੇਨ 'ਚ ਪਾਸ ਕਰਦੇ ਹੋ ਤਾਂ ਜੋ ਹਰ ਲੇਅਰ ਇੱਕ ਗੱਲ 'ਤੇ ਸਹਿਮਤ ਹੋਵੇ: ਇਸ ਰਿਕੁਏਸਟ ਨੂੰ ਕਦੋਂ ਰੋਕਣਾ ਹੈ। ਟਾਈਮਆਊਟ ਆਮ ਤਰੀਕਾ ਹਨ ਜੋ ਇੱਕ ਢੀਲੇ ਡਿਪੈਂਡੇਸੀ ਨੂੰ ਤੁਹਾਡੇ ਸਰਵਰ ਨਾਲ ਫਸਣ ਤੋਂ ਰੋਕਦੇ ਹਨ।
ਇੱਕ context ਤਿੰਨ ਕਿਸਮ ਦੀ ਜਾਣਕਾਰੀ ਰੱਖ ਸਕਦਾ ਹੈ: ਇੱਕ ਡੇਡਲਾਇਨ (ਜਦੋਂ ਕੰਮ ਰੁਕਣਾ ਚਾਹੀਦਾ ਹੈ), ਇੱਕ ਕੈਂਸਲੇਸ਼ਨ ਸਿਗਨਲ (ਕਿਸੇ ਨੇ ਝੱਲਾ ਕੇ ਰੋਕਿਆ), ਅਤੇ ਕੁਝ ਰਿਕੁਏਸਟ-ਸਕੋਪਡ ਵੈਲਯੂਜ਼ (ਇਹ ਸੰਭਾਲ ਕੇ ਵਰਤੋਂ, ਤੇ ਵੱਡੇ ਡੇਟਾ ਲਈ ਕਦੇ ਨਹੀਂ)।
ਕੈਂਸਲੇਸ਼ਨ ਜਾਦੂ ਨਹੀਂ ਹੈ। ਇੱਕ context Done() ਚੈਨਲ ਪ੍ਰਦਾਨ ਕਰਦਾ ਹੈ। ਜਦੋਂ ਇਹ ਬੰਦ ਹੋ ਜਾਂਦਾ ਹੈ, ਰਿਕੁਏਸਟ ਰੱਦ ਹੋ ਚੁੱਕੀ ਹੁੰਦੀ ਹੈ ਜਾਂ ਸਮਾਂ ਖਤਮ ਹੋ ਗਿਆ ਹੁੰਦਾ ਹੈ। ਕੌਡ ਜੋ context ਦੀ ਇੱਜ਼ਤ ਕਰਦਾ ਹੈ ਉਹ Done() ਨੂੰ ਚੈਕ ਕਰਦਾ ਹੈ (ਅਕਸਰ select ਨਾਲ) ਅਤੇ ਵਾਪਸ ਛੁਟਦਾ ਹੈ। ਤੁਸੀਂ ctx.Err() ਨੂੰ ਵੀ ਚੈਕ ਕਰ ਸਕਦੇ ਹੋ ਤਾਂ ਕਿ ਜਾਣ ਸਕੋ ਇਹ ਕਿਉਂ ਖਤਮ ਹੋਇਆ — ਆਮ ਤੌਰ 'ਤੇ context.Canceled ਜਾਂ context.DeadlineExceeded।
context.WithTimeout ਨੂੰ "X ਸਕਿੰਟ ਬਾਅਦ ਰੋਕੋ" ਲਈ ਵਰਤੋ। ਜਦੋਂ ਤੁਹਾਨੂੰ ਸਹੀ ਕਟਆਫ ਟਾਈਮ ਪਤਾ ਹੋਵੇ ਤਾਂ context.WithDeadline ਵਰਤੋ। ਜਦੋਂ ਕਿਸੇ ਪੈਰੇਂਟ ਹਾਲਤ ਨਾਲ ਕੰਮ ਨੂੰ ਪਹਿਲਾਂ ਰੋਕਨਾ ਹੋਵੇ (ਕਲਾਇੰਟ ਡਿਸਕਨੇਕਟ, ਯੂਜ਼ਰ ਦੂਰ ਚਲਾ ਗਿਆ, ਤੁਹਾਡੇ ਕੋਲ ਪਹਿਲਾਂ ਹੀ ਜਵਾਬ ਹੈ), ਤਾਂ context.WithCancel ਵਰਤੋ।
ਜਦੋਂ ਇੱਕ context ਕੈਂਸਲ ਹੋ ਜਾਂਦਾ ਹੈ, ਸਹੀ ਵਰਤਾਵ ਬੋਰਿੰਗ ਪਰ ਮਹੱਤਵਪੂਰਨ ਹੈ: ਕੰਮ ਰੋਕੋ, ਢੀਲੇ I/O ਉੱਤੇ ਰੁਕਨਾ ਬੰਦ ਕਰੋ, ਅਤੇ ਇੱਕ ਸਾਫ਼ ਐਰਰ ਵਾਪਸ ਕਰੋ। ਜੇ ਇੱਕ ਹੈਂਡਲਰ ਡੇਟਾਬੇਸ ਕੁਏਰੀ ਦੇ ਢੀਲੇ ਹੋਣ 'ਤੇ ਉਡੀਕ ਕਰ ਰਿਹਾ ਹੈ ਅਤੇ context ਖਤਮ ਹੋ ਜਾਂਦਾ ਹੈ, ਤੇਜ਼ੀ ਨਾਲ ਵਾਪਸ ਕਰੋ ਅਤੇ ਜੇ ਡੀਬੀ context ਸਮਰਥਨ ਕਰਦਾ ਹੈ ਤਾਂ ਕਵੇਰੀ ਨੂੰ ਰੱਦ ਹੋਣ ਦਿਓ।
ਢੀਲੀਆਂ ਬੇਨਤੀਆਂ ਨੂੰ ਰੋਕਣ ਲਈ ਸਭ ਤੋਂ ਸੁਰੱਖਿਅਤ ਜਗ੍ਹਾ ਉਹ ਬਾਊਂਡਰੀ ਹੈ ਜਿੱਥੋਂ ਟਰੈਫਿਕ ਤੁਹਾਡੀ ਸਰਵਿਸ ਵਿੱਚ ਆਉਂਦਾ ਹੈ। ਜੇ ਇੱਕ ਰਿਕੁਏਸਟ ਟਾਈਮਆਊਟ ਹੋਣ ਵਾਲੀ ਹੈ, ਤੁਸੀਂ ਚਾਹੁੰਦੇ ਹੋ ਕਿ ਉਹ ਨਿਸ਼ਚਿਤ ਅਤੇ ਜਲਦੀ ਹੋਵੇ, ਨਾ ਕਿ ਇਸ ਤੋਂ ਬਾਅਦ ਕਿ ਗੋਰੁਟੀਨ, DB ਕਨੈਕਸ਼ਨ, ਅਤੇ ਮੈਮੋਰੀ ਫਸ ਚੁੱਕੀ ਹੋਵੇ।
ਐਜ 'ਤੇ (ਲੋਡ ਬੈਲੈਂਸਰ, API ਗੇਟਵੇ, ਰਿਵਰਸ ਪ੍ਰਾਕਸੀ) ਇੱਕ ਹੈਰਦ ਕੈਪ ਸੈੱਟ ਕਰੋ ਕਿ ਕੋਈ ਵੀ ਰਿਕੁਏਸਟ ਕਿੰਨੇ ਸਮੇਂ ਤੱਕ ਜੀਵਤ ਰਹਿ ਸਕਦੀ ਹੈ। ਇਹ ਤੁਹਾਡੀ Go ਸਰਵਿਸ ਨੂੰ ਬਚਾਉਂਦਾ ਹੈ ਭਾਵੇਂ ਕੋਈ ਹੈਂਡਲਰ ਟਾਈਮਆਊਟ ਭੁੱਲ ਜਾਵੇ।
ਆਪਣੇ Go ਸਰਵਰ ਦੇ ਅੰਦਰ HTTP ਟਾਈਮਆਊਟ ਸੈੱਟ ਕਰੋ ਤਾਂ ਜੋ ਸਰਵਰ ਇੱਕ ਢੀਲੇ ਕਲਾਇੰਟ ਜਾਂ ਰੁਕੇ ਹੋਏ ਰਿਸਪਾਂਸ ਲਈ ਸਦਾ ਉਡੀਕ ਨਾ ਕਰੇ। ਘੱਟੋ-ਘੱਟ, ਰੀਡਿੰਗ ਹੈਡਰਜ਼, ਫੁੱਲ ਰਿਕੁਏਸਟ ਬਾਡੀ ਪੜ੍ਹਨਾ, ਰਿਸਪਾਂਸ ਲਿਖਣਾ, ਅਤੇ ਆਈਡਲ ਕਨੈਕਸ਼ਨਾਂ ਲਈ ਟਾਈਮਆਊਟ ਸੈੱਟ ਕਰੋ।
ਆਪਣੇ ਪ੍ਰੋਡਕਟ ਖਾਤਰ ਲਈ ਇੱਕ ਡਿਫੌਲਟ ਬਜਟ ਚੁਣੋ। ਬਹੁਤ ਸੇ APIs ਲਈ 1 ਤੋਂ 3 ਸਕਿੰਟ ਆਮ ਰਿਕੁਏਸਟਾਂ ਲਈ ਇੱਕ ਵਧੀਆ ਸ਼ੁਰੂਆਤੀ ਬਿੰਦੂ ਹੁੰਦਾ ਹੈ, ਜਦਕਿ ਜਾਣੇ-ਪਹਚਾਣੇ ਢੀਲੇ ਆਪਰੇਸ਼ਨਾਂ ਜਿਵੇਂ ਐਕਸਪੋਰਟ ਲਈ ਉੱਚੀ ਸੀਮਾ ਰੱਖੋ। ਨੰਬਰ ਤੋਂ ਵੱਧ ਅਹਮ ਗੱਲ ਲਗਾਤਾਰ ਰਹਿਣਾ, ਮੈਪਣਾ ਅਤੇ ਛੋਟੀਆਂ ਛੂਟਾਂ ਲਈ ਸਪਸ਼ਟ ਨਿਯਮ ਹੋਣਾ ਹੈ।
ਸਟ੍ਰੀਮਿੰਗ ਰਿਸਪਾਂਸਾਂ ਨੂੰ ਵਧੀਆ ਧਿਆਨ ਦੀ ਲੋੜ ਹੁੰਦੀ ਹੈ। ਆਸਾਨੀ ਨਾਲ ਅਕਸਮਾਤ ਅਨੰਤ ਸਟ੍ਰੀਮ ਬਣ ਜਾਂਦੀ ਹੈ ਜਿੱਥੇ ਸਰਵਰ ਕਨੈਕਸ਼ਨ ਖੋਲ੍ਹ ਕੇ ਛੋਟੇ-ਛੋਟੇ ਚੰੱਕ ਵਰਗੇ ਲਿਖਦਾ ਰਹਿੰਦਾ ਹੈ, ਜਾਂ ਪਹਿਲੇ ਬਾਈਟ ਤੋਂ ਪਹਿਲਾਂ ਸਦਾ ਉਡੀਕ ਕਰਦਾ ਰਹਿੰਦਾ ਹੈ। ਪਹਿਲਾਂ ਨਿਰਣਯ ਕਰੋ ਕਿ ਕੀ ਇੱਕ ਐਂਡਪਾਇੰਟ ਵਾਸਤਵ ਵਿੱਚ ਸਟ੍ਰੀਮ ਹੈ। ਜੇ ਨਹੀਂ, ਤਾਂ ਟੋਟਲ ਸਮੇਂ ਅਤੇ ਪਹਿਲੇ ਬਾਈਟ ਲਈ ਵੱਖਰੀ ਅਧਿਕਤਮ ਸਮਾਂ ਸੀਮਾ ਲਗਾਓ।
ਜਦੋਂ ਬਾਊਂਡਰੀ 'ਤੇ ਇੱਕ ਸਪੱਸ਼ਟ ਡੇਡਲਾਇਨ ਹੁੰਦੀ ਹੈ, ਤਾਂ ਉਹ ਡੇਡਲਾਇਨ ਪੂਰੇ ਰਿਕੁਏਸਟ ਵਿਚ ਪ੍ਰਸਾਰਿਤ ਕਰਨਾ ਆਸਾਨ ਹੋ ਜਾਂਦਾ ਹੈ।
ਸਭ ਤੋਂ ਸਾਦਾ ਸਥਾਨ ਸ਼ੁਰੂ ਕਰਨ ਲਈ HTTP ਹੈਂਡਲਰ ਹੈ। ਇਹ ਓਥੇ ਹੈ ਜਿੱਥੋਂ ਇੱਕ ਰਿਕੁਏਸਟ ਤੁਹਾਡੇ ਸਿਸਟਮ ਵਿੱਚ ਆਉਂਦਾ ਹੈ, ਇਸ ਲਈ ਇਹ ਇਕ ਕੁਦਰਤੀ ਥਾਂ ਹੈ ਕਠੋਰ ਸੀਮਾ ਸੈੱਟ ਕਰਨ ਲਈ।
ਨਵਾਂ context ਇੱਕ ਡੇਡਲਾਇਨ ਨਾਲ ਬਣਾਓ, ਅਤੇ ਯਕੀਨੀ ਬਣਾਓ ਕਿ ਤੁਸੀਂ ਇਸਨੂੰ cancel ਕਰੋ। ਫਿਰ ਉਹ context ਹਰ ਉਸ ਚੀਜ਼ ਵਿੱਚ ਪਾਸ ਕਰੋ ਜੋ ਬਲਾਕ ਹੋ ਸਕਦੀ ਹੈ: ਡੈਟਾਬੇਸ, HTTP ਕਾਲਾਂ, ਜਾਂ ਢੀਲੇ ਹਿਸਾਬ-ਕਿਤਾਬ।
func (s *Server) GetUser(w http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(r.Context(), 2*time.Second)
defer cancel()
userID := r.URL.Query().Get("id")
if userID == "" {
http.Error(w, "missing id", http.StatusBadRequest)
return
}
user, err := s.loadUser(ctx, userID)
if err != nil {
writeError(w, ctx, err)
return
}
writeJSON(w, http.StatusOK, user)
}
ਇੱਕ ਵਧੀਆ ਨਿਯਮ: ਜੇ ਕੋਈ ਫੰਕਸ਼ਨ I/O 'ਤੇ ਉਡੀਕ ਕਰ ਸਕਦਾ ਹੈ, ਉਦੋਂ ਉਸਨੂੰ context.Context ਲੈਣਾ ਚਾਹੀਦਾ ਹੈ। ਹੈਂਡਲਰ ਨੂੰ ਪੜ੍ਹਨਯੋਗ ਰੱਖਣ ਲਈ ਵੇਰਵੇ ਛੋਟੇ ਹੈਲਪਰ ਫੰਕਸ਼ਨਾਂ (ਜਿਵੇਂ loadUser) ਵਿੱਚ ਧੱਕੋ।
func (s *Server) loadUser(ctx context.Context, id string) (User, error) {
return s.repo.GetUser(ctx, id) // repo should use QueryRowContext/ExecContext
}
ਜੇ ਡੇਡਲਾਇਨ ਮਾਰਿਆ ਜਾਂਦਾ ਹੈ (ਜਾਂ ਕਲਾਇੰਟ ਡਿਸਕਨੇਕਟ ਹੋ ਜਾਂਦਾ ਹੈ), ਤਾਂ ਕੰਮ ਰੋਕੋ ਅਤੇ ਇਕ ਯੂਜ਼ਰ-ਫ੍ਰੈਂਡਲੀ ਰਿਸਪਾਂਸ ਵਾਪਸ ਦਿਓ। ਆਮ ਮੈਪਿੰਗ context.DeadlineExceeded ਨੂੰ 504 Gateway Timeout ਨਾਲ ਮਿਲਾਉਂਦੀ ਹੈ, ਅਤੇ context.Canceled ਨੂੰ "ਕਲਾਇੰਟ ਚਲਾ ਗਿਆ" ਵਜੋਂ ਸੋਚਿਆ ਜਾਂਦਾ ਹੈ (ਅਕਸਰ ਕੋਈ ਬਾਡੀ ਨਹੀਂ ਦਿੱਤੀ ਜਾਂਦੀ)।
func writeError(w http.ResponseWriter, ctx context.Context, err error) {
if errors.Is(err, context.DeadlineExceeded) {
http.Error(w, "request timed out", http.StatusGatewayTimeout)
return
}
if errors.Is(err, context.Canceled) {
// Client went away. Avoid doing more work.
return
}
http.Error(w, "internal error", http.StatusInternalServerError)
}
ਇਹ ਪੈਟਰਨ ਪਾਈਲ-ਅਪਸ ਨੂੰ ਰੋਕਦਾ ਹੈ। ਜਦੋਂ ਟਾਈਮਰ ਖਤਮ ਹੋ ਜਾਂਦਾ ਹੈ, ਹਰ context-ਅਗਿਆਨ ਫੰਕਸ਼ਨ ਚੇਨ ਵਿੱਚ ਇਹੋ ਜਿਹਾ ਸਟਾਪ ਸਿਗਨਲ ਪਾਂਦਾ ਹੈ ਅਤੇ ਜਲਦੀ ਬਾਹਰ ਨਿਕਲ ਸਕਦਾ ਹੈ।
ਜਦੋਂ ਤੁਹਾਡੇ ਹੈਂਡਲਰ ਕੋਲ ਡੇਡਲਾਇਨ ਵਾਲਾ context ਹੁੰਦਾ ਹੈ, ਸਭ ਤੋਂ ਮਹੱਤਵਪੂਰਨ ਨਿਯਮ ਸਾਦਾ ਹੈ: ਉਹੀ ctx ਡੀਬੀ ਕਾਲ ਵਿੱਚ ਤੱਕ ਪਹੁੰਚਾਓ। ਇਸੇ ਤਰ੍ਹਾਂ ਟਾਈਮਆਊਟਸ ਕੰਮ ਨੂੰ ਰੋਕਦੇ ਹਨ ਨਾ ਕਿ ਸਿਰਫ਼ ਹੈਂਡਲਰ ਦੀ ਉਡੀਕ ਹੀ ਬੰਦ ਹੋਵੇ।
database/sql ਨਾਲ, context-ਅਗਿਆਨ ਮੈਥਡਸ ਨੂੰ ਤਰਜੀਹ ਦਿਓ:
func (s *Server) getUser(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
row := s.db.QueryRowContext(ctx,
"SELECT id, email FROM users WHERE id = $1",
r.URL.Query().Get("id"),
)
var id int64
var email string
if err := row.Scan(&id, &email); err != nil {
// handle below
}
}
ਜੇ ਹੈਂਡਲਰ ਦਾ ਬਜਟ 2 ਸਕਿੰਟ ਹੈ, ਤਾਂ ਡੈਟਾਬੇਸ ਨੂੰ ਉਸਦਾ ਸਿਰਫ਼ ਇੱਕ ਹਿੱਸਾ ਦਿਓ। JSON ਐਂਕੋਡਿੰਗ, ਹੋਰ ਡਿਪੈਂਡੇਸੀਜ਼, ਅਤੇ ਐਰਰ ਹੈਂਡਲਿੰਗ ਲਈ ਸਮਾਂ ਛੱਡੋ। ਇੱਕ ਸਾਦਾ ਸ਼ੁਰੂਆਤ ਇਹ ਹੋ ਸਕਦੀ ਹੈ ਕਿ Postgres ਨੂੰ ਕੁੱਲ ਬਜਟ ਦਾ 30%–60% ਦਿਓ। 2 ਸਕਿੰਟ ਦੇ ਹੈਂਡਲਰ ਲਈ ਇਹ 800ms ਤੋਂ 1.2s ਹੋ ਸਕਦਾ ਹੈ।
ਜਦੋਂ context ਕੈਂਸਲ ਹੁੰਦਾ ਹੈ, ਡ੍ਰਾਈਵਰ Postgres ਨੂੰ ਕੁਏਰੀ ਰੋਕਣ ਲਈ ਕਹਿੰਦਾ ਹੈ। ਆਮ ਤੌਰ 'ਤੇ ਕਨੈਕਸ਼ਨ ਪੂਲ ਵਿੱਚ ਵਾਪਸ ਆ ਜਾਂਦੀ ਹੈ ਅਤੇ ਦੁਬਾਰਾ ਵਰਤੀ ਜਾ ਸਕਦੀ ਹੈ। ਜੇ ਕੈਂਸਲ ਕਰਨ ਦੌਰਾਨ ਨੈਟਵਰਕ ਬੁਰਾ ਹੋਵੇ, ਡ੍ਰਾਈਵਰ ਉਹ ਕਨੈਕਸ਼ਨ ਛੱਡ ਦੇ ਸਕਦਾ ਹੈ ਅਤੇ ਬਾਅਦ ਵਿੱਚ ਨਵਾਂ ਖੋਲ੍ਹੇਗਾ। ਕਿਸੇ ਵੀ ਹਾਲਤ ਵਿੱਚ, ਤੁਸੀਂ ਇੱਕ ਗੋਰੁਟੀਨ ਨੂੰ ਸਦਾ ਲਈ ਉਡੀਕ ਕਰਨ ਤੋਂ ਬਚਾਉਂਦੇ ਹੋ।
ਐਰਰ ਚੈੱਕ ਕਰਦਿਆਂ, ਟਾਈਮਆਊਟਾਂ ਨੂੰ ਅਸਲੀ DB ਫੇਲਿਅਰਾਂ ਤੋਂ ਵੱਖਰਾ ਵਰਤੋਂ। ਜੇ errors.Is(err, context.DeadlineExceeded), ਤਾਂ ਤੁਹਾਡਾ ਸਮਾਂ ਖਤਮ ਹੋ ਗਿਆ ਅਤੇ ਤੁਸੀਂ ਇੱਕ ਟਾਈਮਆਊਟ ਵਾਪਸ ਕਰੋ। ਜੇ errors.Is(err, context.Canceled) ਹੈ, ਤਾਂ ਕਲਾਇੰਟ ਚਲਾ ਗਿਆ ਅਤੇ ਤੁਹਾਨੂੰ ਸ਼ਾਂਤੀ ਨਾਲ ਰੁਕਣਾ ਚਾਹੀਦਾ ਹੈ। ਹੋਰ ਐਰਰ ਆਮ ਕੁਏਰੀ ਸਮੱਸਿਆਵਾਂ (ਖ਼ਰਾਬ SQL, ਰੋ-ਮਿਸਿੰਗ, ਪਰਮਿਸ਼ਨ) ਹਨ।
ਜੇ ਤੁਹਾਡੇ ਹੈਂਡਲਰ ਕੋਲ ਇੱਕ ਡੇਡਲਾਇਨ ਹੈ, ਤਾਂ ਤੁਹਾਡੇ ਆਊਟਬਾਊਂਡ HTTP ਕਾਲਾਂ ਨੂੰ ਵੀ ਇਹ ਦੀ ਇੱਜ਼ਤ ਕਰਨੀ ਚਾਹੀਦੀ ਹੈ। ਨਹੀਂ ਤਾਂ ਕਲਾਇੰਟ ਛੱਡ ਦੇਵੇਗਾ, ਪਰ ਤੁਹਾਡਾ ਸਰਵਰ ਇੱਕ ਢੀਲੇ ਅਪਸਟਰੀਮ ਉੱਤੇ ਉਡੀਕ ਕਰਕੇ ਗੋਰੁਟੀਨ, ਸਾਕਟਸ ਅਤੇ ਮੈਮੋਰੀ ਫਸਾ ਲਏਗਾ।
ਪੈਰੇਂਟ context ਨਾਲ ਆਊਟਬਾਊਂਡ ਰਿਕੁਏਸਟ ਬਣਾਓ ਤਾਂ ਕਿ ਕੈਂਸਲੇਸ਼ਨ ਆਟੋਮੈਟਿਕ ਤੌਰ 'ਤੇ ਘੁੰਮ ਜਾਏ:
func fetchUser(ctx context.Context, url string) ([]byte, error) {
// Add a small per-call cap, but never exceed the parent deadline.
ctx, cancel := context.WithTimeout(ctx, 800*time.Millisecond)
defer cancel()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return nil, err
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close() // always close, even on non-200
return io.ReadAll(resp.Body)
}
ਉਹ ਪ੍ਰਤੀ-ਕਾਲ ਟਾਈਮਆਊਟ ਇੱਕ ਸੇਫ਼ਟੀ ਨੈੱਟ ਹੈ। ਪੈਰੇਂਟ ਰਿਕੁਏਸਟ ਡੇਡਲਾਇਨ ਹਮੇਸ਼ਾ ਅਸਲੀ ਬੋਸ ਹੈ। ਇੱਕ ਹੀ ਘੜੀ ਸਾਰੇ ਰਿਕੁਏਸਟ ਲਈ, ਅਤੇ ਜੋਖ਼ਿਮ ਵਾਲੇ ਕਦਮਾਂ ਲਈ ਛੋਟੇ-ਛੋਟੇ ਕੈਪ।
ਟਰਾਂਸਪੋਰਟ ਲੈਵਲ 'ਤੇ ਵੀ ਟਾਈਮਆਊਟ ਸੈੱਟ ਕਰੋ। Context ਰਿਕੁਏਸਟ ਨੂੰ ਕੈਂਸਲ ਕਰਦਾ ਹੈ, ਪਰ ਟਰਾਂਸਪੋਰਟ ਟਾਈਮਆਊਟ ਤੁਹਾਨੂੰ ਧੀਮੀ ਹੈਂਡਸ਼ੇਕਸ ਅਤੇ ਉਹਨਾਂ ਸਰਵਰਾਂ ਤੋਂ ਬਚਾਉਂਦੇ ਹਨ ਜੋ ਹੀਡਰ ਹੀ ਨਹੀਂ ਭੇਜਦੇ।
ਇੱਕ ਤਾਂਕਿਦੀ ਗੱਲ ਜੋ ਟੀਮਾਂ ਨੂੰ ਕੱਟ ਸਕਦੀ ਹੈ: response bodies ਹਰ ਰਸਤੇ ਬੰਦ ਹੋਣੇ ਚਾਹੀਦੇ ਹਨ। ਜੇ ਤੁਸੀਂ ਜਲਦੀ ਵਾਪਸ ਆ ਜਾਂਦੇ ਹੋ (ਸਟੇਟਸ ਕੋਡ ਚੈਕ, JSON ਡੀਕੋਡ ਐਰਰ, context ਟਾਈਮਆਊਟ), ਤਦ ਵੀ ਬਾਡੀ ਬੰਦ ਕਰੋ। ਬਾਡੀ ਲੀਕ ਹੋਣ ਨਾਲ ਸ਼ਾਂਤ ਢੰਗ ਨਾਲ ਕਨੈਕਸ਼ਨ ਪੂਲ ਖਤਮ ਹੋ ਸਕਦਾ ਹੈ ਅਤੇ "ਰੈਂਡਮ" ਲੇਟੇੰਸੀ ਸਪਾਈਕ ਬਣ ਸਕਦੇ ਹਨ।
ਇੱਕ ਠੋਸ ਸਥਿਤੀ: ਤੁਹਾਡੀ API ਪੇਮੈਂਟ ਪ੍ਰੋਵਾਇਡਰ ਨੂੰ ਕਾਲ ਕਰਦੀ ਹੈ। ਕਲਾਇੰਟ 2 ਸਕਿੰਟ ਤੋਂ ਬਾਅਦ ਟਾਈਮਆਊਟ ਕਰਦਾ ਹੈ, ਪਰ upstream 30 ਸਕਿੰਟ ਲਈ ਹੰਗ ਰਹਿੰਦਾ ਹੈ। ਬਿਨਾਂ ਰਿਕੁਏਸਟ ਕੈਂਸਲੇਸ਼ਨ ਅਤੇ ਟਰਾਂਸਪੋਰਟ ਟਾਈਮਆਊਟ ਦੇ, ਤੁਸੀਂ ਹਰ ਛੱਡੀ ਹੋਈ ਬੇਨਤੀ ਲਈ ਉਹ 30 ਸਕਿੰਟ ਭੁਗਤਦੇ ਰਹੋਗੇ।
ਇੱਕ ਰਿਕੁਏਸਟ ਆਮ ਤੌਰ 'ਤੇ ਇੱਕ ਤੋਂ ਵੱਧ ਢੀਲੀਆਂ ਚੀਜ਼ਾਂ ਨੂੰ ਛੁਹਦਾ ਹੈ: ਹੈਂਡਲਰ ਦਾ ਕੰਮ, ਇੱਕ ਡੇਟਾਬੇਸ ਕੁਏਰੀ, ਅਤੇ ਇੱਕ ਜਾਂ ਹੋਰ ਬਾਹਰੀ APIs। ਜੇ ਤੁਸੀਂ ਹਰ ਕਦਮ ਨੂੰ ਖੁੱਲਾ ਬਜਟ ਦਿੰਦੇ ਹੋ, ਤਾਂ ਕੁੱਲ ਸਮਾਂ ਚੁੱਪਚਾਪ ਵਧਦਾ ਜਾਵੇਗਾ ਜਦ ਤੱਕ ਯੂਜ਼ਰ ਨੂੰ ਮਹਿਸੂਸ ਨਾ ਹੋਏ ਅਤੇ ਤੁਹਾਡਾ ਸਰਵਰ ਭਰਨਾ ਸ਼ੁਰੂ ਨਾ ਕਰ ਦੇ।
ਬਜਟਿੰਗ ਸਭ ਤੋਂ ਆਸਾਨ ਸੁਧਾਰ ਹੈ। ਇੱਕ ਪੈਰੇਂਟ ਡੇਡਲਾਇਨ ਚੁਣੋ, ਫਿਰ ਹਰ ਡਿਪੈਂਡੇਸੀ ਨੂੰ ਛੋਟਾ ਹਿੱਸਾ ਦਿਓ। ਚਾਈਲਡ ਡੇਡਲਾਇਨਜ਼ ਪੈਰੇਂਟ ਤੋਂ ਪਹਿਲਾਂ ਹੋਣ ਚਾਹੀਦੇ ਹਨ ਤਾਂ ਜੋ ਤੁਸੀਂ ਜਲਦੀ ਫੇਲ ਹੋ ਜਾਵੋ ਅਤੇ ਅਜੇ ਵੀ ਇਕ ਸਾਫ਼ ਐਰਰ ਵਾਪਸ ਕਰਨ ਲਈ ਸਮਾਂ ਰਹੇ।
ਅਸਲ ਸੇਵਾਵਾਂ ਵਿੱਚ ਚੱਲਣ ਵਾਲੇ ਨਿਯਮ:
ਇਸ ਤਰ੍ਹਾਂ ਟਾਈਮਆਊਟਸ ਨੂੰ ਏਕ-ਦੂਜੇ ਦੇ ਖ਼ਿਲਾਫ਼ ਰੱਖਣ ਤੋਂ ਬਚੋ। ਜੇ ਤੁਹਾਡੇ ਹੈਂਡਲਰ context ਦਾ ਡੇਡਲਾਇਨ 2 ਸਕਿੰਟ ਹੈ ਅਤੇ ਤੁਹਾਡੇ HTTP ਕਲਾਇੰਟ ਦਾ ਟਾਈਮਆਊਟ 10 ਸਕਿੰਟ ਹੈ, ਤਾਂ ਤੁਸੀਂ ਸੁਰੱਖਿਅਤ ਹੋ ਪਰ ਇਹ ਕੁਝ ਗੁੰਝਲਦਾਰ ਹੈ। ਵਿਰੋਧੀ ਢੰਗ ਨਾਲ, ਕਲਾਇੰਟ ਬਿਨਾਂ ਸੰਬੰਧ ਦੇ ਪਹਿਲਾਂ ਕੱਟ ਦੇ ਸਕਦਾ ਹੈ।
ਬੈਕਗ੍ਰਾਊਂਡ ਕੰਮ (ਆਡਿਟ ਲਾਗ, ਮੈਟ੍ਰਿਕਸ, ਈਮੇਲ) ਲਈ, ਰਿਕੁਏਸਟ context ਦੁਬਾਰਾ ਵਰਤੋ ਨਾ। ਐਲੱਗ context ਇੱਕ ਛੋਟੇ ਟਾਈਮਆਊਟ ਨਾਲ ਵਰਤੋ ਤਾਂ ਕਿ ਕਲਾਇੰਟ ਕੈਂਸਲੇਸ਼ਨ ਮਹੱਤਵਪੂਰਨ ਕਲੀਨਅਪ ਨੂੰ ਮਾਰ ਨਾ ਦੇਵੇ।
ਜ਼ਿਆਦਾਤਰ ਟਾਈਮਆਊਟ ਬੱਗ ਹੈਂਡਲਰ ਵਿੱਚ ਨਹੀਂ ਹੁੰਦੇ। ਉਹ ਇੱਕ ਜਾਂ ਦੋ ਲੇਅਰ ਹੇਠਾਂ ਹੁੰਦੇ ਹਨ, ਜਿੱਥੇ ਡੇਡਲਾਇਨ ਚੁਪਚਾਪ ਖੋ ਜਾਂਦੀ ਹੈ। ਜੇ ਤੁਸੀਂ ਐਜ 'ਤੇ ਟਾਈਮਆਊਟ ਸੈੱਟ ਕਰਦੇ ਹੋ ਪਰ ਮੱਧ ਵਿੱਚ ਉਨ੍ਹਾਂ ਨੂੰ ਅਣਦੇਖਾ ਕਰ ਦਿੰਦੇ ਹੋ, ਤਾਂ ਤੁਹਾਨੂੰ ਫਿਰ ਵੀ ਗੋਰੁਟੀਨ, ਡੀਬੀ ਕੁਏਰੀਆਂ, ਜਾਂ HTTP ਕਾਲਾਂ ਮਿਲ ਸਕਦੀਆਂ ਹਨ ਜੋ ਕਲਾਇੰਟ ਦੇ ਚلے ਜਾਣ ਦੇ ਬਾਅਦ ਚੱਲਦੀਆਂ ਰਹਿੰਦੀਆਂ ਹਨ।
ਸਭ ਤੋਂ ਅਕਸਰ ਪੈਟਰਨ ਸਧਾਰਨ ਹੁੰਦੇ ਹਨ:
context.Background() (ਜਾਂ TODO) ਨਾਲ ਕਾਲ ਕਰਨਾ। ਇਹ ਕੰਮ ਨੂੰ ਕਲਾਇੰਟ ਕੈਂਸਲ ਅਤੇ ਹੈਂਡਲਰ ਡੇਡਲਾਇਨ ਤੋਂ ਕੱਟ ਦਿੰਦਾ ਹੈ।ctx.Done() ਦੀ ਜਾਂਚ ਤੋਂ ਬਿਨਾਂ ਸਲੀਪ, ਰਿਟ੍ਰਾਈ, ਜਾਂ ਲੂਪ ਕਰਨਾ। ਰਿਕੁਏਸਟ ਕੈਂਸਲ ਹੋ ਗਿਆ ਹੈ, ਪਰ ਤੁਹਾਡਾ ਕੋਡ ਉਡੀਕ ਕਰ ਭਰਦਾ ਹੈ।context.WithTimeout ਲਪੇਟਣਾ — ਉਨ੍ਹਾਂ ਕੋਲ ਬਹੁਤ ਸਾਰੇ ਟਾਈਮਰ ਹੋ ਜਾਂਦੇ ਹਨ ਅਤੇ ਡੇਡਲਾਇਨ ਗੁੰਝਲਦਾਰ ਹੋ ਜਾਂਦੇ ਹਨ।ctx ਜੁੜਨਾ ਭੁੱਲਣਾ। ਹੈਂਡਲਰ ਟਾਈਮਆਊਟ ਬੇਕਾਰ ਹੈ ਜੇ ਡਿਪੈਂਡੇਸੀ ਇਸਨੂੰ ਨਜ਼ਰਅੰਦਾਜ਼ ਕਰੇ।ਇੱਕ ਕਲਾਸਿਕ ਫੇਲ: ਤੁਸੀਂ ਹੈਂਡਲਰ ਵਿੱਚ 2 ਸਕਿੰਟ ਦਾ ਟਾਈਮਆਊਟ ਜੋੜਦੇ ਹੋ, ਫਿਰ ਤੁਹਾਡੀ ਰੇਪੋ context.Background() ਨਾਲ ਡੀਬੀ ਕਾਲ ਕਰਦੀ ਹੈ। ਲੋਡ ਹੇਠਾਂ, ਇੱਕ ਢੀਲੀ ਕੁਏਰੀ ਕਲਾਇੰਟ ਦੇ ਛੱਡ dávਣ ਤੋਂ ਬਾਅਦ ਵੀ ਚੱਲਦੀ ਰਹਿੰਦੀ ਹੈ, ਅਤੇ ਕਤਾਰ ਵਧਦੀ ਰਹਿੰਦੀ ਹੈ।
ਮੁਢਲੇ ਨਿਯਮ ਸਹੀ ਕਰੋ: ਆਪਣੇ ਕਾਲ ਸਟੈਕ ਵਿੱਚ ctx ਪਹਿਲੇ ਆਰਗਿਫ਼ਮੈਂਟ ਵਜੋਂ ਪਾਸ ਕਰੋ। ਲੰਬੇ ਕੰਮ ਦੇ ਅੰਦਰ ਤੇਜ਼ ਚੈੱਕ ਜੋੜੋ ਜਿਵੇਂ:
select {
case <-ctx.Done():
return ctx.Err()
default:
}
context.DeadlineExceeded ਨੂੰ ਇੱਕ ਟਾਈਮਆਊਟ ਰਿਸਪਾਂਸ (ਅਕਸਰ 504) ਨਾਲ ਮੈਪ ਕਰੋ ਅਤੇ context.Canceled ਨੂੰ ਕਲਾਇੰਟ-ਕੈਨਸਲ ਸਟਾਈਲ ਰਿਸਪਾਂਸ (ਅਕਸਰ 408 ਜਾਂ 499) ਨਾਲ।
ਟਾਈਮਆਊਟਸ ਸਿਰਫ਼ ਕੰਮ ਕਰਦੇ ਹਨ ਜੇ ਤੁਸੀਂ ਉਨ੍ਹਾਂ ਨੂੰ ਦੇਖ ਸਕਦੇ ਹੋ ਅਤੇ ਇਹ ਪੁਸ਼ਟੀ ਕਰ ਸਕਦੇ ਹੋ ਕਿ ਸਿਸਟਮ ਸਾਫ਼ ਤਰੀਕੇ ਨਾਲ ਸਹੀ ਹੋ ਰਿਹਾ ਹੈ। ਜਦੋਂ ਕੁਝ ਢੀਲਾ ਹੁੰਦਾ ਹੈ, ਰਿਕੁਏਸਟ ਨੂੰ ਰੋਕਿਆ ਜਾਣا ਚਾਹੀਦਾ ਹੈ, ਸਰੋਤ ਛੱਡੇ ਜਾਣੇ ਚਾਹੀਦੇ ਹਨ, ਅਤੇ API ਰੀਸਪਾਂਸਿਵ ਰਹਿਣੀ ਚਾਹੀਦੀ ਹੈ।
ਹਰ ਰਿਕੁਏਸਟ ਲਈ ਇੱਕੋ ਛੋਟਾ ਸੈੱਟ ਫੀਲਡ ਲੌਗ ਕਰੋ ਤਾਂ ਜੋ ਤੁਸੀਂ ਨਾਰਮਲ ਰਿਕੁਏਸਟਾਂ ਬਨਾਮ ਟਾਈਮਆਊਟਸ ਦੀ ਤੁਲਨਾ ਕਰ ਸਕੋ। context ਡੇਡਲਾਇਨ (ਜੇ ਹੈ) ਅਤੇ ਜੋ ਕੰਮ ਨੇ ਅੰਤ ਕੀਤਾ ਉਸਦਾ ਕਾਰਨ ਲਿਖੋ।
ਉਪਯੋਗੀ ਫੀਲਡਾਂ ਵਿੱਚ ਡੇਡਲਾਇਨ (ਜਾਂ "none"), ਕੁੱਲ ਲੱਗਿਆ ਸਮਾਂ, ਕੈਂਸਲੇਸ਼ਨ ਕਾਰਨ (ਟਾਈਮਆਊਟ ਵਿਰੁੱਧ ਕਲਾਇੰਟ ਕੈਂਸਲ), ਇੱਕ ਛੋਟੀ ਓਪਰੇਸ਼ਨ ਲੇਬਲ ("db.query users", "http.call billing"), ਅਤੇ ਰਿਕੁਏਸਟ ID ਸ਼ਾਮਿਲ ਕਰੋ।
ਇੱਕ ਨਿਊਨਤਮ ਪੈਟਰਨ ਇਸ ਤਰ੍ਹਾਂ ਹੋ ਸਕਦਾ ਹੈ:
start := time.Now()
deadline, hasDeadline := ctx.Deadline()
err := doWork(ctx)
log.Printf("op=%s hasDeadline=%t deadline=%s elapsed=%s err=%v",
"getUser", hasDeadline, deadline.Format(time.RFC3339Nano), time.Since(start), err)
ਲੌਗ ਤੁਹਾਨੂੰ ਇੱਕ ਰਿਕੁਏਸਟ ਡੀਬੱਗ ਕਰਨ ਵਿੱਚ ਮਦਦ ਕਰਦਾ ਹੈ। ਮੈਟ੍ਰਿਕਸ ਰੁਝਾਨ ਦਿਖਾਉਂਦੇ ਹਨ।
ਕੁਝ ਸਿਗਨਲ ਟਰੈਕ ਕਰੋ ਜੋ ਆਮ ਤੌਰ 'ਤੇ ਪਹਿਲਾਂ ਸਪਾਈਕ ਕਰਦੇ ਹਨ ਜਦੋਂ ਟਾਈਮਆਊਟਸ ਗਲਤ ਹੁੰਦੀਆਂ ਹਨ: ਰੂਟ ਅਤੇ ਡਿਪੈਂਡੇੰਸੀ ਵਾਰ ਟਾਈਮਆਊਟ ਗਿਣਤੀ, ਇਨ-ਫਲਾਈਟ ਰਿਕੁਏਸਟ (ਲੋਡ ਹੇਠਾਂ ਲੈਵਲ ਆਉਣਾ ਚਾਹੀਦਾ ਹੈ), DB ਪੂਲ ਵੈਟ ਸਮਾਂ, ਅਤੇ ਲੇਟੇੰਸੀ ਪर्सੈਂਟਾਈਲ (p95/p99) ਸਫਲਤਾ ਵਿਰੁੱਧ ਟਾਈਮਆਊਟ ਨਾਲ ਵੱਖਰੇ।
ਧੀਮਾਪਣ ਨਿਸ਼ਚਿਤ ਬਣਾਓ। ਇੱਕ ਹੈਂਡਲਰ 'ਤੇ ਡੀਬੱਗ-ਕੇਵਲ ਦੇਰ ਜੋੜੋ, ਇੱਕ ਡੀਂਬੀ ਕੁਏਰੀ ਨੂੰ ਜਾਨਬੂਝ ਕੇ ਆਹਿਸਤਾ ਕਰੋ, ਜਾਂ ਇੱਕ ਟੈਸਟ ਸਰਵਰ ਨਾਲ ਆਊਟਬਾਊਂਡ ਕਾਲ ਨੂੰ ਸੌਂਵਣਾ ਕਰੋ। ਫਿਰ ਦੋ ਗੱਲਾਂ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ: ਤੁਸੀਂ ਟਾਈਮਆਊਟ ਐਰਰ ਦੇਖਦੇ ਹੋ, ਅਤੇ ਕੈਂਸਲੇਸ਼ਨ ਤੋਂ ਤੁਰੰਤ ਬਾਅਦ ਕੰਮ ਰੁਕ ਜਾਂਦਾ ਹੈ।
ਇੱਕ ਛੋਟਾ ਲੋਡ ਟੈਸਟ ਵੀ ਮਦਦਗਾਰ ਹੈ। 20–50 concurrency ਨਾਲ 30–60 ਸਕਿੰਟ ਲਈ ਇਕਠੇ ਰਿਕੁਏਸਟ ਚਲਾਓ ਜੇਹਨਾਂ ਵਿੱਚ ਇੱਕ ਜ਼ੋਰਦਾਰ ਢੀਲਾ ਡਿਪੈਂਡੇਸੀ ਹੋਵੇ। ਗੋਰੁਟੀਨ ਗਿਣਤੀ ਅਤੇ ਇਨ-ਫਲਾਈਟ ਰਿਕੁਏਸਟ ਵਧਣ ਅਤੇ ਫਿਰ ਲੈਵਲ ਆਫ਼ ਹੋ ਜਾਣੇ ਚਾਹੀਦੇ ਹਨ। ਜੇ ਉਹਨਾਂ ਨੇ ਚਲਦੇ ਹੀ ਕਾਇਮ ਰਹਿਣਾ ਹੈ, ਤਾਂ ਕੋਈ ਚੀਜ਼ context ਕੈਂਸਲੇਸ਼ਨ ਨੂੰ ਨਜ਼ਰਅੰਦਾਜ਼ ਕਰ ਰਹੀ ਹੈ।
ਟਾਈਮਆਊਟਸ ਸਿਰਫ਼ ਤਦ ਹੀ ਮਦਦ ਕਰਦੇ ਹਨ ਜਦੋਂ ਉਹ ਹਰ ਥਾਂ ਲਗਾਏ ਗਏ ਹੋਣ ਜਿੱਥੇ ਰਿਕੁਏਸਟ ਉਡੀਕ ਕਰ ਸਕਦਾ ਹੈ। ਡਿਪਲੋਈ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਆਪਣੀ ਕੋਡਬੇਸ 'ਤੇ ਇੱਕ ਵਾਰੀ ਜਾਂਚ ਕਰੋ ਕਿ ਉਹੀ ਨਿਯਮ ਹਰ ਹੈਂਡਲਰ ਵਿੱਚ ਲਾਗੂ ਹੋ ਰਹੇ ਹਨ।
context.DeadlineExceeded ਅਤੇ context.Canceled ਲਈ ਐਰਰ ਚੈੱਕ ਕੀਤੇ ਜਾਣ।http.NewRequestWithContext (ਜਾਂ req = req.WithContext(ctx)) ਵਰਤੇ ਅਤੇ ਕਲਾਇੰਟ ਟਰਾਂਸਪੋਰਟ ਟਾਈਮਆਊਟਸ ਹੋਣ। ਪ੍ਰੋਡੈਕਸ਼ਨ ਪਾਥ ਵਿੱਚ http.DefaultClient ਤੇ ਨਿਰਭਰ ਨਾ ਰਹੋ।ਰੇਲੀਜ਼ ਤੋਂ ਪਹਿਲਾਂ ਇੱਕ ਛੋਟੀ "ਢੀਲਾ ਡਿਪੈਂਡੇਸੀ" ਡ੍ਰਿਲ ਕਰਨਾ ਵਰਤੀ ਰਹੇ। ਇੱਕ SQL ਕੁਏਰੀ ਵਿੱਚ ਕਿਰਪਾ ਨਾਲ 2 ਸਕਿੰਟ ਦੀ ਦੇਰ ਜੋੜੋ ਅਤੇ ਤਿੰਨ ਗੱਲਾਂ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ: ਹੈਂਡਲਰ ਸਮੇਂ 'ਤੇ ਵਾਪਸ ਆਉਂਦਾ ਹੈ, DB ਕਾਲ ਵਾਸਤਵ ਵਿੱਚ ਰੋਕੀ ਜਾਂਦੀ ਹੈ (ਸਿਰਫ਼ ਹੈਂਡਲਰ ਉਡੀਕ ਨਹੀਂ ਕਰ ਰਿਹਾ), ਅਤੇ ਤੁਹਾਡੇ ਲਾਗ ਵਿੱਚ ਸਪਸ਼ਟ ਤੌਰ 'ਤੇ ਲਿਖਿਆ ਹੈ ਕਿ ਇਹ DB ਟਾਈਮਆਊਟ ਸੀ।
ਇੱਕ ਐਂਡਪਾਇੰਟ ਸੋਚੋ GET /v1/account/summary। ਇੱਕ ਯੂਜ਼ਰ ਐਕਸ਼ਨ ਤਿੰਨ ਚੀਜ਼ਾਂ ਟ੍ਰਿਗਰ ਕਰ ਸਕਦਾ ਹੈ: ਇੱਕ PostgreSQL ਕੁਏਰੀ (ਅਕਾਊਂਟ ਅਤੇ ਹਾਲੀਆ ਐਕਟਿਵਿਟੀ) ਅਤੇ ਦੋ ਬਾਹਰੀ HTTP ਕਾਲਾਂ (ਉਦਾਹਰਨ ਲਈ, ਬਿਲਿੰਗ ਸਟੇਟਸ ਚੈਕ ਅਤੇ ਪ੍ਰੋਫ਼ਾਈਲ ਐਨਰਿੱਚਮੈਂਟ ਲੁੱਕਅੱਪ)।
ਪੂਰੇ ਰਿਕੁਏਸਟ ਨੂੰ ਇੱਕ ਸਖਤ 2 ਸਕਿੰਟ ਬਜਟ ਦਿਓ। ਬਜਟ ਕਿੱਤੇ ਤੋਂ ਬਿਨਾਂ, ਇਕ ਢੀਲਾ ਡਿਪੈਂਡੇਸੀ ਗੋਰੁਟੀਨ, DB ਕਨੈਕਸ਼ਨ ਅਤੇ ਮੈਮੋਰੀ ਨੂੰ ਤੱਕੇ ਰੱਖ ਸਕਦਾ ਹੈ ਜਦ ਤੱਕ ਤੁਹਾਡੀ API ਹਰ ਥਾਂ ਟਾਈਮਆਊਟ ਹੋਣ ਲੱਗਦੀ ਹੈ।
ਸਰਲ ਵੰਡ ਹੋ ਸਕਦੀ ਹੈ: DB ਕੁਏਰੀ ਲਈ 800ms, ਬਾਹਰੀ ਕਾਲ A ਲਈ 600ms, ਅਤੇ ਬਾਹਰੀ ਕਾਲ B ਲਈ 600ms।
ਜਦੋਂ ਤੁਸੀਂ ਕੁੱਲ ਡੇਡਲਾਇਨ ਨੂੰ ਜਾਣ ਲੈਂਦੇ ਹੋ, ਉਸਨੂੰ ਹੇਠਾਂ ਪਾਸ ਕਰੋ। ਹਰ ਡਿਪੈਂਡੇਸੀ ਨੂੰ ਆਪਣਾ ਛੋਟਾ ਟਾਈਮਆਊਟ ਮਿਲਦਾ ਹੈ, ਪਰ ਇਹ ਫਿਰ ਵੀ ਪੈਰੇਂਟ ਤੋਂ ਕੈਂਸਲੇਸ਼ਨ ਵਾਰਸੇ ਹੋ ਲੈਂਦਾ ਹੈ।
func AccountSummary(w http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(r.Context(), 2*time.Second)
defer cancel()
dbCtx, dbCancel := context.WithTimeout(ctx, 800*time.Millisecond)
defer dbCancel()
aCtx, aCancel := context.WithTimeout(ctx, 600*time.Millisecond)
defer aCancel()
bCtx, bCancel := context.WithTimeout(ctx, 600*time.Millisecond)
defer bCancel()
// Use dbCtx for QueryContext, aCtx/bCtx for outbound HTTP requests.
}
ਜੇ ਬਾਹਰੀ ਕਾਲ B 2.5 ਸਕਿੰਟ ਲੈਂਦੀ ਹੈ, ਤਾਂ ਤੁਹਾਡਾ ਹੈਂਡਲਰ 600ms 'ਤੇ ਉਡੀਕ ਕਰਨਾ ਬੰਦ ਕਰ ਦੇਵੇਗਾ, ਚੱਲ ਰਹੇ ਕੰਮ ਨੂੰ ਕੈਂਸਲ ਕਰ ਦੇਵੇਗਾ, ਅਤੇ ਕਲਾਇੰਟ ਨੂੰ ਇੱਕ ਸਪਸ਼ਟ ਟਾਈਮਆਊਟ ਰਿਸਪਾਂਸ ਵਾਪਸ ਕਰੇਗਾ। ਕਲਾਇੰਟ ਇੱਕ ਫਾਸਟ ਫੇਲ ਦੇਖਦਾ ਹੈ ਬਜਾਏ ਕਿ ਲੰਬੀ ਉਡੀਕ ਵਾਲੀ ਸਪਿਨਰ।
ਤੁਹਾਡੇ ਲਾਗਸ ਇਹ ਅਸਾਨੀ ਨਾਲ ਦਿਖਾਉਣੇ ਚਾਹੀਦੇ ਹਨ ਕਿ ਕਿਸ ਨੇ ਬਜਟ ਵਰਤਿਆ: ਉਦਾਹਰਨ ਲਈ DB ਜਲਦੀ ਖਤਮ ਹੋਈ, ਬਾਹਰੀ A ਸਫਲ ਰਿਹਾ, ਬਾਹਰੀ B ਨੇ ਆਪਣਾ ਕੈਪ ਮਾਰਿਆ ਅਤੇ context deadline exceeded ਵਾਪਸ ਕੀਤਾ।
ਜਦੋਂ ਇੱਕ ਅਸਲ ਐਂਡਪਾਇੰਟ ਟਾਈਮਆਊਟਸ ਅਤੇ ਕੈਂਸਲੇਸ਼ਨ ਨਾਲ ਚੰਗੀ ਤਰ੍ਹਾਂ ਕੰਮ ਕਰਦਾ ਹੈ, ਉਸਨੂੰ ਇਕ ਦੁਹਰਾਓਯੋਗ ਪੈਟਰਨ ਵਿੱਚ ਬਦਲੋ। ਇਸਨੂੰ end-to-end ਲਗਾਓ: ਹੈਂਡਲਰ ਡੇਡਲਾਇਨ, ਡੀਬੀ ਕਾਲਾਂ, ਅਤੇ ਆਊਟਬਾਊਂਡ HTTP। ਫਿਰ ਇੱਕੋ ਹੀ ਢਾਂਚਾ ਅਗਲੇ ਐਂਡਪਾਇੰਟ 'ਤੇ ਨਕਲ ਕਰੋ।
ਤੁਸੀਂ ਤੇਜ਼ੀ ਨਾਲ ਅੱਗੇ ਵਧੋਗੇ ਜੇ ਤੁਸੀਂ ਉਦਾਹਰਨ ਵਾਲੀਆਂ ਚੀਜ਼ਾਂ ਕੇਂਦਰਿਤ ਕਰੋ: ਇੱਕ ਬਾਊਂਡਰੀ ਟਾਈਮਆਊਟ ਹੈਲਪਰ, ਰੈਪਰ ਜੋ ਯਕੀਨੀ ਬਣਾਉਂਦੇ ਹਨ ਕਿ ctx DB ਅਤੇ HTTP ਕਾਲਾਂ ਵਿੱਚ ਪਾਸ ਹੁੰਦਾ ਹੈ, ਅਤੇ ਇੱਕ ਇਕਸਾਰ ਐਰਰ ਮੈਪਿੰਗ ਅਤੇ ਲਾਗ ਫਾਰਮੈਟ।
ਜੇ ਤੁਸੀਂ ਇਸ ਪੈਟਰਨ ਨੂੰ ਤੇਜ਼ੀ ਨਾਲ ਪ੍ਰੋਟੋਟਾਈਪ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ, ਤਾਂ Koder.ai (koder.ai) Go ਹੈਂਡਲਰ ਅਤੇ ਸਰਵਿਸ ਕਾਲਾਂ ਨੂੰ ਚੈਟ ਪ੍ਰਾਮਪਟ ਤੋਂ ਜਨਰੇਟ ਕਰ ਸਕਦਾ ਹੈ, ਅਤੇ ਤੁਸੀਂ ਸੋਰਸ ਕੋਡ ਐਕਸਪੋਰਟ ਕਰਕੇ ਆਪਣੇ timeout ਹੈਲਪਰ ਅਤੇ ਬਜਟ ਲਾਗਿਕ ਲਗਾ ਸਕਦੇ ਹੋ। ਮਕਸਦ ਸਾਦਗੀ ਹੈ: ਢੀਲੇ ਕਾਲ ਜਲਦੀ ਰੁਕ ਜਾਣ, ਐਰਰ ਇੱਕੋ ਵਰਗੇ ਦਿਸਣ, ਅਤੇ ਡੀਬੱਗਿੰਗ ਕਿਸ ਨੇ ਲਿਖਿਆ ਇਸ 'ਤੇ ਨਿਰਭਰ ਨਾ ਰਹੇ।
ਇੱਕ ਢੀਰ ਹੋਈ ਬੇਨਤੀ ਉਹਨਾਂ ਸੀਮਤ ਸਰੋਤਾਂ ਨੂੰ ਰੋਕ ਕੇ ਰੱਖਦੀ ਹੈ ਜਦੋਂ ਉਹ ਵਕਤ ਦੀ ਉਡੀਕ ਕਰ ਰਹੀ ਹੁੰਦੀ ਹੈ: ਇੱਕ ਗੋਰੁਟੀਨ, ਬਫਰਾਂ ਅਤੇ ਰਿਸਪਾਂਸ ਆਬਜੈਕਟਾਂ ਲਈ ਮੈਮੋਰੀ, ਅਤੇ ਅਕਸਰ ਇੱਕ ਡਾਟਾਬੇਸ ਜਾਂ HTTP ਕਨੈਕਸ਼ਨ। ਜਦੋਂ ਕਈ ਬੇਨਤੀਆਂ ਇਕੱਠੀਆਂ ਹੋ ਜਾਂਦੀਆਂ ਹਨ, ਕਤਾਰ ਬਣ ਜਾਂਦੀ ਹੈ, ਲੇਟੇੰਸੀ ਸਾਰਿਆਂ ਲਈ ਵਧਦੀ ਹੈ, ਅਤੇ ਸੇਵਾ ਉਸ ਸਮੇਂ ਫੇਲ ਹੋ ਸਕਦੀ ਹੈ ਹਾਲਾਂਕਿ ਹਰ ਰਿਕੁਏਸਟ ਅਖੀਰਕਾਰ ਮੁਕੰਮਲ ਹੋ ਜਾਂਦੀ।
ਸਧਾਰਨ ਤਰੀਕਾ ਇਹ ਹੈ: ਰਿਕੁਏਸਟ ਦੀ ਸਰਹੱਦ 'ਤੇ ਇਕ ਸਾਫ਼ ਡੇਡਲਾਇਨ ਸੈੱਟ ਕਰੋ (ਪ੍ਰਾਕਸੀ/ਗੇਟਵੇ ਅਤੇ Go ਸਰਵਰ), ਹੈਂਡਲਰ ਦੇ ਅੰਦਰ ਇੱਕ ਟਾਇਮਡ context ਬਣਾਓ, ਅਤੇ ਉਹੀ ctx ਹਰ ਬਲਾਕਿੰਗ ਕਾਲ ਵਿੱਚ ਪਾਸ ਕਰੋ (ਡੇਟਾਬੇਸ ਅਤੇ ਆਊਟਬਾਊਂਡ HTTP)। ਜਦੋਂ ਡੇਡਲਾਇਨ ਪੂਰਾ ਹੋ ਜਾਂਦਾ ਹੈ, ਤੇਜ਼ੀ ਨਾਲ ਵਾਪਸ ਕਰੋ, ਇੱਕ ਇਕਸਾਰ ਟਾਈਮਆਊਟ ਜਵਾਬ ਦਿਓ ਅਤੇ ਕਿਸੇ ਵੀ ਇਨ-ਫਲਾਈਟ ਵਰਕ ਨੂੰ ਰੋਕੋ ਜੇ ਉਹ ਕੈਂਸਲ ਹੋ ਸਕਦਾ ਹੈ।
context.WithTimeout(parent, d) ਨੂੰ ਉਪਯੋਗ ਕਰੋ ਜਦੋਂ ਤੁਸੀਂ “ਇਸ ਅਵਧੀ ਤੋਂ ਬਾਅਦ ਰੋਕੋ” ਚਾਹੁੰਦੇ ਹੋ — ਇਹHandlers ਵਿੱਚ ਸਭ ਤੋਂ ਆਮ ਹੈ। ਜਦੋਂ ਤੁਹਾਡੇ ਕੋਲ ਪਹਿਲਾਂ ਹੀ ਇੱਕ ਨਿਰਧਾਰਿਤ ਕਟਆਫ਼ ਸਮਾਂ ਹੋਵੇ ਤਾਂ context.WithDeadline(parent, t) ਵਰਤੋ। ਜੇ ਅੰਦਰੂਨੀ ਹਾਲਤ (ਜਿਵੇਂ “ਸਾਡੇ ਕੋਲ ਜਵਾਬ ਆ ਗਿਆ”) ਦੇ ਆਧਾਰ 'ਤੇ ਕੰਮ ਰੋਕਣਾ ਹੈ, ਤਾਂ context.WithCancel(parent) ਵਰਤੋ।
ਹਮੇਸ਼ਾ cancel ਫੰਕਸ਼ਨ ਨੂੰ ਕਾਲ ਕਰੋ, ਆਮ ਤੌਰ 'ਤੇ defer cancel() ਤੁਰੰਤ ਬਾਅਦ। ਕੈਂਸਲ ਕਰਨਾ ਟਾਇਮਰ ਰਿਲੀਜ਼ ਕਰਦਾ ਹੈ ਅਤੇ ਉਹਨਾਂ ਚਾਈਲਡ ਵਰਕਾਂ ਨੂੰ ਸਾਫ਼ ਸਿਗਨਲ ਭੇਜਦਾ ਹੈ ਜੋ ਰੀਟਰਨ ਰਸਤੇ ਤੋਂ ਪਹਿਲਾਂ ਖਤਮ ਹੋ ਸਕਦੇ ਹਨ।
ਹੈੰਡਲਰ ਵਿੱਚ ਇੱਕ ਵਾਰ ਰਿਕੁਏਸਟ context ਬਣਾਓ ਅਤੇ ਅੱਗੇ ਜਾਉ। ਉਹੀ ctx ਉਹਨਾਂ ਫੰਕਸ਼ਨਾਂ ਨੂੰ ਪਹਿਲੇ ਆਰਗਿਫ਼ਮੈਂਟ ਵਜੋਂ ਪਾਸ ਕਰੋ ਜੋ ਬਲਾਕ ਕਰ ਸਕਦੀਆਂ ਹਨ। ਇੱਕ ਤੇਜ਼ ਨਿਯਮ: ਕੋਡਬੇਸ 'ਚ context.Background() ਜਾਂ context.TODO() ਲਈ ਖੋਜ ਕਰੋ; ਉਹ ਅਕਸਰ ਕੈਂਸਲ propagation ਨੂੰ ਟੁੱਟਦੇ ਹਨ।
context-ਅਗਿਆਨ ਡੀਬੀ ਮੈਥਡ ਵਰਤੋ ਜਿਵੇਂ QueryContext, QueryRowContext, ExecContext ਜਾਂ ਡ੍ਰਾਈਵਰ ਦੇ ਸਮਾਨ। ਜਦੋਂ context ਖਤਮ ਹੁੰਦਾ ਹੈ, ਡ੍ਰਾਈਵਰ Postgres ਨੂੰ ਕਹਿ ਸਕਦਾ ਹੈ ਕਿ ਕੁਏਰੀ ਰੋਕ ਦਿੱਤੀ ਜਾਵੇ ਤਾਂ ਤੁਸੀਂ ਅਨਵਾਂਛਿਤ ਸਮਾਂ ਅਤੇ ਕਨੈਕਸ਼ਨਾਂ ਨੂੰ ਬਚਾ ਸਕੋ।
ਮਾਪਦੇ ਹੋਏ parent context ਨੂੰ ਆਊਟਬਾਊਂਡ ਰਿਕੁਏਸਟ ਦੇ ਨਾਲ ਜੋੜੋ: http.NewRequestWithContext(ctx, ...)। ਇਸਦੇ ਨਾਲ-ਨਾਲ ਕਲਾਇੰਟ/ਟਰਾਂਸਪੋਰਟ ਟਾਈਮਆਊਟ ਵੀ ਸੈੱਟ ਕਰੋ ਤਾਂ ਜੋ connect, TLS ਅਤੇ response header ਦੀ ਉਡੀਕ ਦੌਰਾਨ ਸੁਰੱਖਿਆ ਰਹੇ। ਹਰ ਰਸਤੇ ਤੇ response.Body ਨੂੰ ਬੰਦ ਕਰੋ, ਭਾਵੇਂ ਕਿਵੇਂ ਵੀ ਰਿਸਪਾਂਸ ਹੋਵੇ — ਨਹੀਂ ਤਾਂ ਕਨੈਕਸ਼ਨ ਪੂਲ ਲੀਕ ਹੋ ਸਕਦਾ ਹੈ।
ਪਹਿਲਾਂ ਇੱਕ ਕੁੱਲ ਬਜਟ ਚੁਣੋ (ਉਦਾਹਰਨ ਲਈ, 2 ਸਕਿੰਟ ਇੱਕ ਯੂਜ਼ਰ-ਫੇਸਿੰਗ ਐਂਡਪਾਇੰਟ ਲਈ)। ਫਿਰ ਹਰ ਡਿਪੈਂਡੇਸੀ ਨੂੰ ਉਸਦਾ ਛੋਟਾ ਹਿੱਸਾ ਦੇ ਦਿਓ ਅਤੇ ਹੈਂਡਲਰ ਲਈ 100–200ms ਬਫਰ ਰੱਖੋ। ਜੇ ਮਾਤਾ (parent) context ਕੋਲ ਬਹੁਤ ਘੱਟ ਸਮਾਂ ਬਚਿਆ ਹੈ, ਤਾਂ ਮਹਿੰਗਾ ਕੰਮ ਸ਼ੁਰੂ ਨਾ ਕਰੋ ਜੋ ਸੰਭਵ ਨਹੀਂ ਕਿ ਖਤਮ ਹੋਵੇ।
ਸਧਾਰਨ ਡੈਫੌਲਟ: context.DeadlineExceeded ਨੂੰ 504 Gateway Timeout ਨਾਲ ਮੈਪ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ, ਇੱਕ ਛੋਟਾ ਸੁਨੇਹਾ जैसे “request timed out”। context.Canceled ਆਮ ਤੌਰ 'ਤੇ ਦਿਖਾਉਂਦਾ ਹੈ ਕਿ ਕਲਾਇੰਟ ਚਲਾ ਗਿਆ; ਅਕਸਰ ਸਭ ਤੋਂ ਵਧੀਆ ਕੰਮ ਹੈ ਕਿ ਵਧੇਰੇ ਵਰਕ ਨੂੰ ਰੋਕ ਦਿੱਤਾ ਜਾਵੇ ਅਤੇ ਬਾਡੀ ਲਿਖਣ ਤੋਂ ਬਚਿਆ ਜਾਵੇ।
ਸਭ ਤੋਂ ਆਮ ਗਲਤੀਆਂ: ਹੈਂਡਲਰ context ਨੂੰ ਛੱਡ ਦੇਣਾ (context.Background() ਦਾ ਇਸਤੇਮਾਲ), ctx.Done() ਦੀ ਜਾਂਚ ਕੀਤੇ ਬਿਨਾਂ ਸਲੀਪ/ਰਿਟ੍ਰਾਈ/ਲੂਪ ਕਰਨਾ, ਅਤੇ ਬਲਾਕਿੰਗ ਕਾਲਾਂ (DB, ਆਊਟਬਾਊਂਡ HTTP) ਨੂੰ ctx ਨਾਲ ਜੋੜਨਾ ਭੁੱਲ ਜਾਣਾ। ਇਹਨਾਂ ਕਾਰਨਾਂ ਨਾਲ timeout propagation ਟੁੱਟ ਜਾਂਦਾ ਹੈ।