Made some adjustments to have it work for all the "we wait for sth from 
backend" and added as r1878433 in trunk.

> Am 02.06.2020 um 09:37 schrieb Stefan Eissing <[email protected]>:
> 
> Looks good!
> 
>> Am 29.05.2020 um 21:14 schrieb Ruediger Pluem <[email protected]>:
>> 
>> 
>> 
>> On 5/29/20 11:41 AM, Stefan Eissing wrote:
>>> 
>>> 
>>>> Am 29.05.2020 um 11:23 schrieb Ruediger Pluem <[email protected]>:
>>>> 
>>>> 
>>>> 
>>>> On 5/29/20 10:09 AM, Stefan Eissing wrote:
>>>>> Looks good. Now I learned about the "ping" parameter...
>>>> 
>>>> Committed as r1878264 with a tweaked comment to make clear what I do.
>> 
>> Thanks for backporting both
>> 
>>>> 
>>>> Getting me to the next possible enhancement. I already had a patch but 
>>>> when putting it to the mail I got doubts that it could work
>>>> due to the fact, that in most use cases HTTP/2 is encrypted.
>>>> In AJP a set ping parameter on the worker will also cause an AJP ping to 
>>>> be sent as the first thing even on fresh connections and
>>>> we only wait for the timeout set in the parameter for a reply. The idea 
>>>> behind this is that the backend might be able to deal with
>>>> a TCP handshake, but not with processing a request, because maybe all 
>>>> processing threads / processes on the backend application
>>>> are busy. This way this can be detected quickly and early and we can sent 
>>>> our request to a different backend in case of a load
>>>> balancing scenario.
>>>> With HTTP/2 we will likely have a TLS handshake first which likely already 
>>>> requires a responding backend application. So it would
>>>> not work to wait only for ping timeout time on a ping reply as we will 
>>>> already wait for the timeout set on the socket to get an
>>>> answer to our TLS client Hello. So the idea would be to already lower the 
>>>> socket timeout to ping timeout before the TLS handshake
>>>> starts and reset it back after we received the ping from the backend. 
>>>> Opinions?
>>> 
>>> HTTP/2 also has an initial SETTINGS frame handshake. We could use the ping 
>>> timeout on the socket until the first NGHTTP2_SETTINGS frame from the 
>>> backend arrives on a new connection.
>> 
>> And now I learned about the HTTP/2 handshake :-). I haven't though about the 
>> SETTINGS frame. So the high level idea would be:
>> 
>> 1. If a fresh session in h2_proxy_session_setup is created and the ping 
>> parameter is set on the worker change the socket timeout
>> to the one in ping, but tuck away the current socket timeout.
>> 2. In on_frame_recv in the NGHTTP2_SETTINGS restore the old timeout (if it 
>> was changed) and continue.
>> 
>> So something like the below?
>> 
>> Index: modules/http2/h2_proxy_session.c
>> ===================================================================
>> --- modules/http2/h2_proxy_session.c (revision 1878265)
>> +++ modules/http2/h2_proxy_session.c (working copy)
>> @@ -203,6 +203,21 @@
>>        case NGHTTP2_PUSH_PROMISE:
>>            break;
>>        case NGHTTP2_SETTINGS:
>> +            /*
>> +             * Check if we have saved a socket timeout before sending the
>> +             * SETTINGS frame in h2_proxy_session_setup to perform a quick
>> +             * "ping" on the backend. If yes, restore the saved timeout to
>> +             * the socket.
>> +             */
>> +            if (session->save_timeout != -1) {
>> +                apr_socket_t *socket = NULL;
>> +
>> +                socket = ap_get_conn_socket(session->c);
>> +                if (socket) {
>> +                    apr_socket_timeout_set(socket, session->save_timeout);
>> +                    session->save_timeout = -1;
>> +                }
>> +            }
>>            if (frame->settings.niv > 0) {
>>                n = nghttp2_session_get_remote_settings(ngh2, 
>> NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS);
>>                if (n > 0) {
>> @@ -634,6 +649,8 @@
>>        session->input = apr_brigade_create(session->pool, 
>> session->c->bucket_alloc);
>>        session->output = apr_brigade_create(session->pool, 
>> session->c->bucket_alloc);
>> 
>> +        session->save_timeout = -1;
>> +
>>        nghttp2_session_callbacks_new(&cbs);
>>        nghttp2_session_callbacks_set_on_frame_recv_callback(cbs, 
>> on_frame_recv);
>>        nghttp2_session_callbacks_set_on_data_chunk_recv_callback(cbs, 
>> stream_response_data);
>> @@ -654,6 +671,22 @@
>>        nghttp2_option_del(option);
>>        nghttp2_session_callbacks_del(cbs);
>> 
>> +        /*
>> +         * If a ping parameter is set on the worker set the socket timeout 
>> to
>> +         * it to "use" the possible TLS handshake and the initial SETTINGS
>> +         * frame as kind of ping. Tuck away the old timeout to restore it, 
>> once
>> +         * the SETTING frame arrived from the backend.
>> +         */
>> +        if (p_conn->worker->s->ping_timeout_set) {
>> +            apr_socket_t *socket = NULL;
>> +
>> +            socket = ap_get_conn_socket(session->c);
>> +            if (socket) {
>> +                apr_socket_timeout_get(socket, &session->save_timeout);
>> +                apr_socket_timeout_set(socket, 
>> p_conn->worker->s->ping_timeout);
>> +            }
>> +        }
>> +
>>        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c, APLOGNO(03362)
>>                      "setup session for %s", p_conn->hostname);
>>    }
>> Index: modules/http2/h2_proxy_session.h
>> ===================================================================
>> --- modules/http2/h2_proxy_session.h (revision 1878265)
>> +++ modules/http2/h2_proxy_session.h (working copy)
>> @@ -94,6 +94,8 @@
>> 
>>    apr_bucket_brigade *input;
>>    apr_bucket_brigade *output;
>> +
>> +    apr_time_t save_timeout;
>> };
>> 
>> h2_proxy_session *h2_proxy_session_setup(const char *id, proxy_conn_rec 
>> *p_conn,
>> 
>> 
>> Regards
>> 
>> RĂ¼diger
> 

Reply via email to