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

IGNITE-13204 Add Java thin client Kubernetes auto discovery #8206

Merged

Conversation

timoninmaxim
Copy link
Member

  1. ReliableChannel now works with dynamic list of server addresses;
  2. ClientConfiguration can be configured with addressFinder;
  3. Provide Kubernetes addressFinder.

@ptupitsyn ptupitsyn changed the title IGNITE-13204 Thin client kubernetes auto discovery IGNITE-13204 Add Java thin client Kubernetes auto discovery Sep 3, 2020
Copy link
Contributor

@isapego isapego left a comment

Choose a reason for hiding this comment

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

I got an impression that provided solution has a lot of non-necessary parts, like a lot of different holders and wrappers, and their purpose is unclean. Can you add a detailed description for new classes which explains why are they needed?

@timoninmaxim timoninmaxim force-pushed the IGNITE-13204_kubernetes_thin_client branch from aea28f1 to cbd0dde Compare September 24, 2020 11:51
@timoninmaxim timoninmaxim force-pushed the IGNITE-13204_kubernetes_thin_client branch from 141524c to beebf80 Compare September 30, 2020 10:08
@timoninmaxim timoninmaxim force-pushed the IGNITE-13204_kubernetes_thin_client branch from beebf80 to 55f56c1 Compare September 30, 2020 12:59
@timoninmaxim
Copy link
Member Author

@ptupitsyn hi! I've merge your changes related to async thin client API. I leverage on introduced by me apply* methods and then remove AtomicInteger you're used for the counter, also I've fix exception issue (when final exception missed if it's different from ClientConnectionException after retry) and add test for that.

Could you please review my changes again.

chAndAttempts = applyOnDefaultChannel(channel -> channel, attemptsLimit);

} catch (Throwable ex) {
fut.completeExceptionally(ex);
Copy link
Contributor

Choose a reason for hiding this comment

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

NL

Copy link
Contributor

Choose a reason for hiding this comment

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

What if failure already not null here? We will lose this information?

Copy link
Member Author

Choose a reason for hiding this comment

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

fixed

.serviceAsync(op, payloadWriter, payloadReader)
.handle((res, err) -> {
if (err == null) {
fut.complete(res);
Copy link
Contributor

Choose a reason for hiding this comment

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

NL

Copy link
Member Author

Choose a reason for hiding this comment

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

Maybe you mean "Redundant NL"? Will fIx it this way

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah, I see in next comments. There is already NL, will not change it.

Copy link
Contributor

Choose a reason for hiding this comment

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

No, I mean missing empty line between fut.complete(res); and onChannelFailure(ch);

Copy link
Member Author

Choose a reason for hiding this comment

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

Sorry, I don't see this case.

if (scheduledChannelsReinit.get())
channelsInit(true);
else
rollCurrentChannel(hld);
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we skip rollCurrentChannel if scheduledChannelsReinit? I think we should roll channel in any case.

Copy link
Member Author

Choose a reason for hiding this comment

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

if channel fails and there is scheduled reinit, there are chances that reinitialization will fix the issue (reinitialization may assign new default channel).

Copy link
Contributor

Choose a reason for hiding this comment

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

There are chances if some dynamic address finder is used, but by default, you just check current address twice and skip one channel. In both cases (dynamic and static address finder) there is nothing bad happens if we roll current channel

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, if new default channel is assigned by channelsInit(), than rollCurrentChannel(hld) will do no-op, since hld already not a default channel.

Copy link
Member Author

Choose a reason for hiding this comment

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

Actually there is an invokation sequence for default case: channelsInit -> applyOnDefaultChannel to establish connection with default channel (that checks that connection is OK). So rolling is not required too. Also rolling at least acquires lock so it is not free.

So, there is a matrix of cases for channel failure:

  1. Fixed addreses, topology changes -> Channel is rolled with channelsInit -> applyOnDefaultChannel;
  2. Fixed addresses, topology does not change -> rollCurrentChannel;
  3. Dynamic address, topology changes -> channels are reinited twice, rolls with applyOnDefaultChannel;
  4. Dynamic address, topology does not change -> rollCurrentChannel.

So, there is an issue with double initialization for dynamic addresses only. I will fix it by skipping second initialization as describe in other comment.

* for every configured server. Otherwise only default channel is connected.
*/
void channelsInit(boolean force) {
if (!force && channels != null)
Copy link
Contributor

Choose a reason for hiding this comment

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

Currently, flag force is useless (at least for production code, but perhaps for test code too). There are 3 calls of this method from production code, first - right after constructor (when channels == null), two other calls with force == true.

Copy link
Member Author

Choose a reason for hiding this comment

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

fixed

}
chFailLsnrs.forEach(Runnable::run);

if (scheduledChannelsReinit.get())
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps && !partitionAwarenessEnabled should be added here (to avoid double reinit for partition awareness, first time here and second time in async thread). WDYT?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, it is a correct optimization. But I will add this condition inside if block to avoid additional rolling of current channel.

Copy link
Member Author

Choose a reason for hiding this comment

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

fixed

@ptupitsyn ptupitsyn merged commit fa9c483 into apache:master Oct 16, 2020
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.

None yet

4 participants