Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide a way to close a connection when exceeding the maximum age on server-side #2747

Merged
merged 9 commits into from
Jun 5, 2020

Conversation

ikhoon
Copy link
Contributor

@ikhoon ikhoon commented May 27, 2020

Motivation:

Sometimes users might want to disconnect an active connection after a certain period of time.
This is useful when balance loads with an L4 load balancer which not understand HTTP2 connection.
By closing connections periodically, new connections are able to spread to other servers.

Modifications:

  • Add defaultServerMaxConnectionAgeMillis flag. This option is disabled by default.
  • Add maxConnectionAge{Millis} to ServerBuilder`.
  • Record CONNECTION_START_TIME_NANO when a channel is initialized.
  • Disconnect a connection after exceeding maxConnectionAge by sending:
    • "Connection: close" for HTTP/1
    • GOAWAY frame for HTTP/2
  • Fix a bug where channel.close() throws NullPointerException when idle timeout is set to 0

Result:

  • You can now disconnect an old connection.

@ikhoon ikhoon added this to the 0.99.7 milestone May 27, 2020
@ikhoon ikhoon changed the title Provide a way to close a connection when exceeding the maximum age Provide a way to close a connection when exceeding the maximum age on server-side May 27, 2020
Motivation:

Sometimes users might want to disconnect an active connection after a certain period of time.
This is useful when balance loads with a L4 load balancer which not understand HTTP2 connection.
By closing connections periodically, new connections are able to spread to other servers.

Modifications:

- Add `defaultServerMaxConnectionAgeMillis` flag. This option is disabled by default.
- Add `maxConnectionAge{Millis} to `ServerBuilder`.
- Record `CONNECTION_START_TIME_NANO` when a channel is initialized.
- Disconnect a connection after exceeding maxConnectionAge by sending:
  - "Connection: close" for HTTP/1
  - GOAWAY frame for HTTP/2
- Fix a bug where `channel.close()` throws NullPointerException when idle timeout is set to 0

Result:

- You can now send `GOAWAY` frame with HTTP/2 and `Connection: close`
  with HTTP/1 for an old connection on server-side.
@ikhoon ikhoon force-pushed the server-max-connection-age branch from 17a68a0 to ab7e489 Compare June 2, 2020 02:01
@codecov
Copy link

codecov bot commented Jun 3, 2020

Codecov Report

Merging #2747 into master will increase coverage by 0.09%.
The diff coverage is 91.04%.

Impacted file tree graph

@@             Coverage Diff              @@
##             master    #2747      +/-   ##
============================================
+ Coverage     72.70%   72.80%   +0.09%     
- Complexity    11756    11867     +111     
============================================
  Files          1032     1042      +10     
  Lines         45875    46134     +259     
  Branches       5720     5757      +37     
============================================
+ Hits          33355    33588     +233     
+ Misses         9599     9596       -3     
- Partials       2921     2950      +29     
Impacted Files Coverage Δ Complexity Δ
...linecorp/armeria/client/HttpRequestSubscriber.java 70.73% <0.00%> (+5.48%) 32.00 <0.00> (+2.00)
...c/main/java/com/linecorp/armeria/common/Flags.java 59.92% <75.00%> (+0.21%) 62.00 <1.00> (+1.00)
...armeria/server/HttpServerPipelineConfigurator.java 75.63% <81.81%> (+0.09%) 11.00 <0.00> (ø)
...ecorp/armeria/server/ServerHttp2ObjectEncoder.java 85.29% <83.33%> (-0.43%) 16.00 <1.00> (+3.00) ⬇️
...ava/com/linecorp/armeria/server/ServerBuilder.java 81.45% <88.88%> (+0.18%) 117.00 <3.00> (+6.00)
...rp/armeria/client/Http1ClientKeepAliveHandler.java 100.00% <100.00%> (ø) 6.00 <1.00> (ø)
...p/armeria/client/Http2ClientConnectionHandler.java 88.09% <100.00%> (ø) 19.00 <0.00> (+1.00)
...rp/armeria/client/Http2ClientKeepAliveHandler.java 100.00% <100.00%> (ø) 2.00 <1.00> (ø)
...armeria/internal/common/Http2KeepAliveHandler.java 72.22% <100.00%> (ø) 10.00 <0.00> (ø)
...corp/armeria/internal/common/KeepAliveHandler.java 81.69% <100.00%> (+1.27%) 33.00 <2.00> (+5.00)
... and 76 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 69fae3c...e810065. Read the comment docs.

Copy link
Member

@trustin trustin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent work, @ikhoon 👍

Copy link
Member

@minwoox minwoox left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work, @ikhoon!

@trustin trustin merged commit ec336fa into line:master Jun 5, 2020
@ikhoon ikhoon deleted the server-max-connection-age branch June 22, 2020 05:22
fmguerreiro pushed a commit to fmguerreiro/armeria that referenced this pull request Sep 19, 2020
… server-side (line#2747)

Motivation:

Sometimes users might want to disconnect an active connection after a certain period of time.
This is useful when balance loads with an L4 load balancer which not understand HTTP2 connection.
By closing connections periodically, new connections are able to spread to other servers.

Modifications:

- Add `defaultServerMaxConnectionAgeMillis` flag. This option is disabled by default.
- Add `maxConnectionAge{Millis} to `ServerBuilder`.
- Record `CONNECTION_START_TIME_NANO` when a channel is initialized.
- Disconnect a connection after exceeding `maxConnectionAge` by sending:
  - "Connection: close" for HTTP/1
  - GOAWAY frame for HTTP/2
- Fix a bug where `channel.close()` throws NullPointerException when idle timeout is set to 0

Result:

- You can now disconnect an old connection.
ikhoon added a commit to ikhoon/armeria that referenced this pull request Jan 7, 2021
…for client

Motivation:

A long connection can cause load imbalance between servers if clients does not use client-side balance.
The clients will use L4 loadbalancer which keeps a connection to a server.

The traffic could be rebalanced by closing connections periodically or after N requests.
A max connection age for server-side was added by line#2747.
However max connection age for client and max number of requeets for server and client have not impletemented yet.

Related: line#203 line#2741 line#2747

Modifications:

- Add `maxNumRequests` to `ServerBuilder`, `ClientFactoryBuilder` and `Flags`
  - Send `GOAWAY` or `Connection: close` by server-side
  - Remove from channel pool and close a connection or send `GOAWAY` by client-side
- Add `maxConnnectionAge{Millis}` to `ClientFactoryBuilder` and `Flags`
- Keep track of requests count by KeepAliveHandler to determine a connection is needed to close
- Remove some fields, derived from ClientFatory, in `HttpChannelPool` and
  pass `ClientFactory` to `HttpSessionHandler` for reducing object size and simplicity.
- Add `MaxConnectionAgeExceededTask` to close an expired connection.

Result:

- You can now set a maximum allowed number of requests for a connection.
  ```java
  // For server
  Server.builder()
        // A connection will be closed after serving 10000 requests.
        .maxNumRequests(10000);

  // For client
  ClientFactory.builder()
               // A connection will be closed after fully receving 2000th requests.
               .maxNumRequests(2000)
  ```
- You can now set a maximum allowed connection age for a connection on client-side.
  ```java
  // A connection will be closed in 10 seconds after the connection is established.
  ClientFactory.builder()
               .maxConnnectionAgeMillis(10000)
  ```
- Fixes line#203
ikhoon added a commit to ikhoon/armeria that referenced this pull request Jan 7, 2021
…for client

Motivation:

A long connection can cause load imbalance between servers if clients do not use client-side balance.
The clients which use L4 load balancers keep a connection to a server.

The traffic could be rebalanced by closing connections periodically or after N requests.
A max connection age for server-side was added by line#2747.
However max connection age for client and max number of requests for server and client have not implemented yet.

Related: line#203 line#2741 line#2747

Modifications:

- Add `maxNumRequests` to `ServerBuilder`, `ClientFactoryBuilder` and `Flags`
  - Send `GOAWAY` or `Connection: close` by server-side
  - Remove from channel pool and close a connection or send `GOAWAY` by client-side
- Add `maxConnnectionAge{Millis}` to `ClientFactoryBuilder` and `Flags`
- Keep track of requests count by KeepAliveHandler to determine a connection is needed to close
- Remove some fields, derived from ClientFatory, in `HttpChannelPool` and
  pass `ClientFactory` to `HttpSessionHandler` for reducing object size and simplicity.
- Add `MaxConnectionAgeExceededTask` to close an expired connection.

Result:

- You can now set a maximum allowed number of requests for a connection.
  ```java
  // For server
  Server.builder()
        // A connection will be closed after serving 10000 requests.
        .maxNumRequests(10000);

  // For client
  ClientFactory.builder()
               // A connection will be closed after fully receiving 2000th requests.
               .maxNumRequests(2000)
  ```
- You can now set a maximum allowed connection age for a connection on client-side.
  ```java
  // A connection will be closed in 10 seconds after the connection is established.
  ClientFactory.builder()
               .maxConnnectionAgeMillis(10000)
  ```
- Fixes line#203
trustin pushed a commit that referenced this pull request Jan 27, 2021
…for client (#3267)

Motivation:

A long connection can cause load imbalance between servers if clients do not use client-side balance.
Because L4 load balancers keep a client connection to a server.

The traffic could be rebalanced by closing connections periodically or after N requests.
A max connection age for server-side was added by #2747.
However max connection age for client and max number of requests for server and client have not implemented yet.

Related: #203 #2741 #2747

Modifications:

- Add `maxNumRequestsPerConnection` to `ServerBuilder`, `ClientFactoryBuilder` and `Flags`
  - Send `GOAWAY` or `Connection: close` by server-side
  - Remove from channel pool and close a connection or send `GOAWAY` by client-side
- Add `maxConnnectionAge{Millis}` to `ClientFactoryBuilder` and `Flags`
- Keep track of requests count by KeepAliveHandler to determine a connection is needed to close
- Remove some fields, derived from ClientFatory, in `HttpChannelPool` and
  pass `ClientFactory` to `HttpSessionHandler` for reducing object size and simplicity.
- Add `MaxConnectionAgeExceededTask` to close an expired connection.

Result:

- You can now set a maximum allowed number of requests for a connection.
  ```java
  // For server
  Server.builder()
        // A connection will be closed after serving 10000 requests.
        .maxNumRequestsPerConnection(10000);

  // For client
  ClientFactory.builder()
               // A connection will be closed after fully receiving the response of 2000th requests.
               .maxNumRequestsPerConnection(2000);
  ```
- You can now set a maximum allowed connection age for a connection on client-side.
  ```java
  // A connection will be closed in 10 seconds after the connection is established.
  ClientFactory.builder()
               .maxConnnectionAgeMillis(10000);
  ```
- Fixes #203

Co-authored-by: julie-kim <julie.kim@linecorp.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants