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

[FIXES JENKINS-28245] Allow finer-grained tuning of ChannelPinger. #1687

Conversation

deadmoose
Copy link
Contributor

  • Allows customization in seconds, not minutes
  • Allows customization of the ping timeout (before, you could set a
    custom interval, but the timeout would always be PingThread's 4
    minute default)

This also drops the serialVersionUID from ChannelPinger.SetUpRemotePing;
without one provided, the JVM will generate one on demand which is
sufficient for the purposes here since these are never persisted and
master & slave run the same compiled code. (And it demonstrably works
since countless other MasterToSlaveCallables fail to specify their own
custom IDs)

@@ -136,6 +150,7 @@ public void onClosed(Channel channel, IOException cause) {
});

t.start();
LOGGER.fine("Ping thread started for " + channel + " with a " + interval + " minute interval");
LOGGER.fine("Ping thread started for " + channel + " with a " +
intervalSeconds + " second interval and a " + timeoutSeconds + " second timeout.");
Copy link
Member

Choose a reason for hiding this comment

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

Maybe also change to not have slow logging?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What do you mean by slow logging? Building up the string like that (including in case of FINE not actually being logged)?

Copy link
Member

Choose a reason for hiding this comment

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

Logger.log(Level.FINE, "This is a {0} {1} {2}", new Object[] {"paramaterised", "message", "in a log"});

Using this the string concatenation will not take place if the log is not enabled (whereas the code in ln187 will always perform String concatenation).

Copy link
Member

Choose a reason for hiding this comment

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

Third argument should be array of argument objects

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Without benchmarking, I'd guess overhead for a string concatenation like this is going to be roughly comparable to the overhead of creating/GCing that object array, especially in the context of something that only happens once per slave connection, but I can swap to that.

(My main objection is the ugliness of losing the log-level convenience wrappers + needing to manually make the array... I really wish we'd just ship FormattingLogger as part of guava.)

Copy link
Member

Choose a reason for hiding this comment

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

SC will be worse - as it still involves garbage collection for the implicit StringBuilder and Object/array creation is highly optimized
(I pine for slf4j....)

@KostyaSha
Copy link
Member

👍 for seconds
If this change will be merged, then you need also update https://wiki.jenkins-ci.org/display/JENKINS/Features+controlled+by+system+properties

master & slave run the same compiled code.

Do you mean slave.jar?

@deadmoose
Copy link
Contributor Author

master & slave run the same compiled code.

Do you mean slave.jar?

No, slave.jar is the remoting jar, which is just enough to bootstrap the system. After that, the Jenkins master squirts its classes over the wire to the slave.

private static final String INTERVAL_MINUTES_PROPERTY = ChannelPinger.class.getName() + ".pingInterval";
private static final String INTERVAL_SECONDS_PROPERTY = ChannelPinger.class.getName() + ".pingIntervalSeconds";

private static final int DEFAULT_TIMEOUT_SECONDS = Integer.getInteger(TIMEOUT_SECONDS_PROPERTY, 4 * 60);
Copy link
Member

Choose a reason for hiding this comment

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

this is not a "default" if it gets the value from a system property.
Also there is no other code change here or linked to call the new constructor outside of the no args constructor - so this adds confusion where the attempt is to reduce it.

@oleg-nenashev
Copy link
Member

Marked as WiP (comments from @jtnord )

@deadmoose deadmoose force-pushed the channelpinger_seconds_and_timeout branch from 9abf88c to 3743bfe Compare May 18, 2015 20:33
@deadmoose
Copy link
Contributor Author

@jtnord - Updated. I'd had the other constructor for tests (which I hadn't finished buttoning up), but ditched it since the test harness needs to be able to play with the system properties anyways.

Added my test class to confirm that those properties are getting read & passed along, though it does NOT actually dig into the guts of the resulting PingThread like I'd originally intended.

@KostyaSha
Copy link
Member

Marked as WiP (comments from @jtnord )

@oleg-nenashev 1) what marked?
2) Just create WIP label and stop renaming topics?

public SetUpRemotePing(int pingInterval) {
this.pingInterval = pingInterval;
static class SetUpRemotePing extends MasterToSlaveCallable<Void, IOException> {
private final int pingTimeoutSeconds;
Copy link
Member

Choose a reason for hiding this comment

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

I think (but may be mistaken) that this should have a serialVersionUID defined.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As mentioned in the change description, it really isn't; these don't get persisted and re-read by potentially differently-compiled code, and remoting is already taking care of making master/slave run the same compiled bits with the JVM's same auto-rolled UID.

There are already plenty of Callables demonstrating this if you grep for MasterToSlaveCallable, e.g.:
https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/jenkins/util/VirtualFile.java#L417-L438
https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/jenkins/slaves/restarter/JnlpSlaveRestarterInstaller.java#L52-L92
https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/jenkins/slaves/StandardOutputSwapper.java#L38-L74
https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/jenkins/model/Jenkins.java#L2048-L2052

Copy link
Member

Choose a reason for hiding this comment

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

There are issues with differences in JVM versions between master and slave. I have customer issues where not having a serialVersionUID defined has caused Jenkins to blow up (thankfully all of these cases were in plugins). Just because some instances of callables in Core have been lucky so far does not mean it is a safe pattern to follow.

In addition, assuming that the Jenkins core implementation of Remoting (with its current contract of classloaders) is the only implementation is a risky assumption. We have an alternative implementation for Master-to-Master communication which (for security reasons) does not allow remote class loading and as such the serialVersionUID must match for any callables that are transferred over that Channel. While we are not in a position to release that implementation at the present time, I know it is on our roadmap to release it in the future. It would be better if the habit of serialVersionUID alway was better applied in Core so that when we do open source this code we can set an earlier lower-bound on the Master version that the code applies to.

@deadmoose deadmoose force-pushed the channelpinger_seconds_and_timeout branch from 3743bfe to 8c55dd2 Compare May 19, 2015 22:16
<groupId>com.google.guava</groupId>
<artifactId>guava-testlib</artifactId>
<version>${guavaVersion}</version>
<scope>test</scope>
Copy link
Member

Choose a reason for hiding this comment

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

sorry didn't notice this before but adding scope to a dependency in a dependency Management section is IMHO just evil (at some point you may want to actually depend on this thing and then all the transitive dependencies break - its also not clear in the using pom that it is using it at the right scope - and I have been bitten by this on one too many occasions now).

Other than that LGTM.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Whoops, good catch. Got my two poms mixed up there.

Updated!

 * Allows customization in seconds, not minutes
 * Allows customization of the ping timeout (before, you could set a
   custom interval, but the timeout would always be PingThread's 4
   minute default)

This also drops the serialVersionUID from ChannelPinger.SetUpRemotePing;
without one provided, the JVM will generate one on demand which is
sufficient for the purposes here since these are never persisted and
master & slave run the same compiled code. (And it demonstrably works
since countless other MasterToSlaveCallables fail to specify their own
custom IDs)
@deadmoose deadmoose force-pushed the channelpinger_seconds_and_timeout branch from 8c55dd2 to b20f158 Compare May 20, 2015 16:31
@jtnord
Copy link
Member

jtnord commented May 20, 2015

👍

<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava-testlib</artifactId>
<version>${guavaVersion}</version>
Copy link
Member

Choose a reason for hiding this comment

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

If I get the code correctly, it should be included in the test scope only

Copy link
Contributor Author

Choose a reason for hiding this comment

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

See the above comments on the previous version where I'd had a mental hiccup and done just that. This is the big block that's specifying versions of things, and then it's scoped to test down in in core/pom.xml where it's actually consumed. (And then, anecdotally, it appears scoping inside dependencyManagement is completely ignored since core/pom.xml still successfully picked up a version number from the supposedly scoped definition here)

Copy link
Member

Choose a reason for hiding this comment

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

Agreed

@oleg-nenashev
Copy link
Member

👍 for the improvement BTW

@daniel-beck
Copy link
Member

I think the serialVersionUID issue should be addressed, then this is ready to go.

@oleg-nenashev oleg-nenashev added the work-in-progress The PR is under active development, not ready to the final review label Oct 6, 2015
@oleg-nenashev
Copy link
Member

@deadmoose
There is an open comment from @daniel-beck , Moved the issue to WiP state

@oleg-nenashev oleg-nenashev added the needs-comments-resolved Comments in the PR need to be addressed before it can be considered for merging label Oct 25, 2015
@daniel-beck daniel-beck added the unresolved-merge-conflict There is a merge conflict with the target branch. label May 9, 2016
@alvarolobato
Copy link
Member

alvarolobato commented Nov 24, 2016

@deadmoose are you planning on finishing this PR? If not I propose to close it. I'll submit one with similar changes.

@batmat batmat added the proposed-for-close There is no consensus about feasibility of this PR, and maintainers do not see a way forward for it label Nov 24, 2016
@batmat
Copy link
Member

batmat commented Nov 28, 2016

Closing as superseded by #2645 where @deadmoose's work was preserved.

Please @deadmoose feel totally free to tell us if you feel something should (have) be done differently here. Even in private if you prefer. Thanks for your work!

@batmat batmat closed this Nov 28, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs-comments-resolved Comments in the PR need to be addressed before it can be considered for merging proposed-for-close There is no consensus about feasibility of this PR, and maintainers do not see a way forward for it unresolved-merge-conflict There is a merge conflict with the target branch. work-in-progress The PR is under active development, not ready to the final review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants