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

Expose SocketOption querying on ConnectionContext API #950

Merged
merged 23 commits into from
Mar 3, 2020

Conversation

idelpivnitskiy
Copy link
Member

@idelpivnitskiy idelpivnitskiy commented Feb 27, 2020

Motivation:

Users should be able to read socket options for created connections.

Modifications:

  • Add ConnectionContext.socketOption API to query socket options;
  • Add ConnectionContextSocketOptionTest to test new API;

Results:

Users can read socket options of the connections.

public void tcpStandardSocketOptionIsNotNull() throws Exception {
testSocketOption("TCP_NODELAY", Boolean.class, is(notNullValue()),
// HTTP_2 stream channel does not have TCP_NODELAY option
protocol == Protocol.HTTP_2 ? equalTo("null") : not(equalTo("null")));
Copy link
Member Author

Choose a reason for hiding this comment

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

Server connection context uses child-stream for h2 that does not allow users to query multiple TCP options for the original parent connection, like TCP_NODELAY / SO_RCVBUF / SO_SNDBUF / etc.
Do we want to keep it as-is? We can expose options for the original TCP connection by keeping ref for the parent's ChannelConfig.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Are there any options for H2 that are applicable for a stream? If not, should we always just query the options from the parent context?

Copy link
Member Author

@idelpivnitskiy idelpivnitskiy Feb 28, 2020

Choose a reason for hiding this comment

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

From what I see in netty, it creates a new DefaultChannelConfig for each stream. And these config is a fresh new and is not related to the parent's ChannelConfig. Therefore, each channel has its own subset of options. In theory (but not in the current ST) some code may modify that options for each stream independently (like AUTO_READ, AUTO_CLOSE`, etc.) and it will not have side-effects for parent channel.

I think it will be more practical for users to be interested in parent channel options. It will require one more reference in DefaultNettyConnection. Let me try and will see the overhead.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done: 4fbb1f9

@idelpivnitskiy
Copy link
Member Author

JDK11 build failed due to docker issue

@servicetalk-bot test this please

@idelpivnitskiy
Copy link
Member Author

One of the builds failed with #952

if (option == ServiceTalkSocketOptions.IDLE_TIMEOUT) {
return idleTimeoutMs == null ? null : (T) idleTimeoutMs; // TODO: return (T) idleTimeoutMs;
}
// Try to look for a ChannelOption with the same name and type:
Copy link
Collaborator

Choose a reason for hiding this comment

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

In the method above we do not set any option that we do not recognize in the channel config then is trying to lookup for an unknown value here reasonable? Can we be consistent between get and set?

Copy link
Member Author

@idelpivnitskiy idelpivnitskiy Feb 28, 2020

Choose a reason for hiding this comment

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

Netty has a lot more other options that users might be interested in to query, especially for different transports, like TCP_FASTOPEN_CONNECT for epoll. See EpollChannelOption class from netty.

If we will follow the policy to be consistent between get and set, every time users request a new option for querying we will need to provide one more ServiceTalkSocketOption constant and implement support for setting this option. However, users may not bother with setting it, just querying. Also, maintaining a single or separate lists of ServiceTalkSocketOption constants that are applicable only for a specific transport may be not ideal.

SocketOption<T> is a public JDK API. Users can use it to create the required options for querying without asking us. The only risk here is that they can take internal ByteBufAllocator from netty. But that will be their risky choice or we can prevent specific options from querying. The list is short and contains only 3 options that are dengerous: ALLOCATOR, RCVBUF_ALLOCATOR, MESSAGE_SIZE_ESTIMATOR. All other netty options are read-only objects.

Considering that overhead of keeping get and set in consistency for every new option, I decided to let users query what they want with existing API.

Copy link
Member Author

Choose a reason for hiding this comment

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

As we discussed offline, I made get/set consistent in 09d0918.
Here is an issue to enhance these two methods to support custom options: #953

}

private DefaultNettyConnection(Channel channel, BufferAllocator allocator, Executor executor,
TerminalPredicate<Read> terminalMsgPredicate, CloseHandler closeHandler,
FlushStrategy flushStrategy, ExecutionStrategy executionStrategy,
@Nullable SSLSession sslSession) {
FlushStrategy flushStrategy, @Nullable Long idleTimeoutMs,
Copy link
Collaborator

Choose a reason for hiding this comment

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

I am somewhat apprehensive about individually adding options here which are otherwise not stored by netty. Anything else we add will mean we add more arguments here.

Can we instead take+store the TcpConfig here and pass the same to SocketOptionUtils for querying? If we do use TcpConfig we can use that to also get the FlushStrategy

Copy link
Member Author

@idelpivnitskiy idelpivnitskiy Feb 28, 2020

Choose a reason for hiding this comment

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

Thought about that but decided to defer until we add anything else to better understand how to structure it (maybe it will be better to have an object to keep these options instead of using the full TcpConfig).

We do not expose AbstractReadOnlyTcpConfig as a public class for now. If you think we can make AbstractReadOnlyTcpConfig public (it lives in tcp-netty-internal module) to keep DefaultNettyConnection reusable for client and server side, I can do the change now. Otherwise, let's defer?

We may also consider using a single ExecutionContext instead of other 3 separate arguments: BufferAllocator, Executor, ExecutionStrategy. Can do here or as a follow-up.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we just use TcpConfig for now as these are internal classes and we can make sure we do not update config? If you want, we can also wrap the config to throw from the setters.

I am also OK to defer, your call.

Copy link
Member Author

Choose a reason for hiding this comment

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

Will defer that, thanks

public void tcpStandardSocketOptionIsNotNull() throws Exception {
testSocketOption("TCP_NODELAY", Boolean.class, is(notNullValue()),
// HTTP_2 stream channel does not have TCP_NODELAY option
protocol == Protocol.HTTP_2 ? equalTo("null") : not(equalTo("null")));
Copy link
Collaborator

Choose a reason for hiding this comment

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

Are there any options for H2 that are applicable for a stream? If not, should we always just query the options from the parent context?

@idelpivnitskiy idelpivnitskiy merged commit 592a0c1 into apple:master Mar 3, 2020
@idelpivnitskiy idelpivnitskiy deleted the socket-options branch March 3, 2020 19:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants