提交 d6b242f2 编写于 作者: K Kohsuke Kawaguchi

Merge branch 'nio'

......@@ -63,6 +63,8 @@ Upcoming changes</a>
<div id="rc" style="display:none;"><!--=BEGIN=-->
<h3><a name=v1.559>What's new in 1.559</a> <!--=DATE=--></h3>
<ul class=image>
<li class=rfe>
JNLP slaves are now handled through NIO-based remoting channels for better scalability.
<li class=rfe>
Slaves connected via Java Web Start now restart themselves when a connection to Jenkins is lost.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-19055">issue 19055</a>)
......
......@@ -818,7 +818,7 @@ public abstract class Launcher {
* Kill the process when the channel is severed.
*/
@Override
protected synchronized void terminate(IOException e) {
public synchronized void terminate(IOException e) {
super.terminate(e);
ProcessTree pt = ProcessTree.get();
try {
......
......@@ -32,8 +32,10 @@ import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.BindException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.channels.ServerSocketChannel;
import java.util.logging.Level;
import java.util.logging.Logger;
......@@ -55,7 +57,7 @@ import java.util.logging.Logger;
*/
public final class TcpSlaveAgentListener extends Thread {
private final ServerSocket serverSocket;
private final ServerSocketChannel serverSocket;
private volatile boolean shuttingDown;
public final int configuredPort;
......@@ -67,7 +69,8 @@ public final class TcpSlaveAgentListener extends Thread {
public TcpSlaveAgentListener(int port) throws IOException {
super("TCP slave agent listener port="+port);
try {
serverSocket = new ServerSocket(port);
serverSocket = ServerSocketChannel.open();
serverSocket.socket().bind(new InetSocketAddress(port));
} catch (BindException e) {
throw (BindException)new BindException("Failed to listen on port "+port+" because it's already in use.").initCause(e);
}
......@@ -82,7 +85,7 @@ public final class TcpSlaveAgentListener extends Thread {
* Gets the TCP port number in which we are listening.
*/
public int getPort() {
return serverSocket.getLocalPort();
return serverSocket.socket().getLocalPort();
}
@Override
......@@ -90,7 +93,7 @@ public final class TcpSlaveAgentListener extends Thread {
try {
// the loop eventually terminates when the socket is closed.
while (true) {
Socket s = serverSocket.accept();
Socket s = serverSocket.accept().socket();
// this prevents a connection from silently terminated by the router in between or the other peer
// and that goes without unnoticed. However, the time out is often very long (for example 2 hours
......
......@@ -4,9 +4,13 @@ import hudson.Extension;
import hudson.model.Computer;
import hudson.remoting.Channel;
import hudson.remoting.Channel.Mode;
import hudson.remoting.ChannelBuilder;
import jenkins.AgentProtocol;
import jenkins.model.Jenkins;
import jenkins.slaves.NioChannelSelector;
import org.jenkinsci.remoting.nio.NioChannelHub;
import javax.inject.Inject;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
......@@ -23,6 +27,9 @@ import java.net.Socket;
*/
@Extension
public class CliProtocol extends AgentProtocol {
@Inject
NioChannelSelector nio;
@Override
public String getName() {
return "CLI-connect";
......@@ -30,13 +37,23 @@ public class CliProtocol extends AgentProtocol {
@Override
public void handle(Socket socket) throws IOException, InterruptedException {
new Handler(socket).run();
new Handler(nio.getHub(),socket).run();
}
protected static class Handler {
protected final NioChannelHub hub;
protected final Socket socket;
/**
* @deprecated as of 1.559
* Use {@link #Handler(NioChannelHub, Socket)}
*/
public Handler(Socket socket) {
this(null,socket);
}
public Handler(NioChannelHub hub, Socket socket) {
this.hub = hub;
this.socket = socket;
}
......@@ -47,9 +64,21 @@ public class CliProtocol extends AgentProtocol {
}
protected void runCli(Connection c) throws IOException, InterruptedException {
Channel channel = new Channel("CLI channel from " + socket.getInetAddress(),
Computer.threadPoolForRemoting, Mode.BINARY,
new BufferedInputStream(c.in), new BufferedOutputStream(c.out), null, true, Jenkins.getInstance().pluginManager.uberClassLoader);
ChannelBuilder cb;
String name = "CLI channel from " + socket.getInetAddress();
// Connection can contain cipher wrapper, which can't be NIO-ed.
// if (hub!=null)
// cb = hub.newChannelBuilder(name, Computer.threadPoolForRemoting);
// else
cb = new ChannelBuilder(name, Computer.threadPoolForRemoting);
Channel channel = cb
.withMode(Mode.BINARY)
.withRestricted(true)
.withBaseLoader(Jenkins.getInstance().pluginManager.uberClassLoader)
.build(new BufferedInputStream(c.in), new BufferedOutputStream(c.out));
channel.setProperty(CliEntryPoint.class.getName(),new CliManagerImpl(channel));
channel.join();
}
......
......@@ -2,6 +2,7 @@ package hudson.cli;
import hudson.Extension;
import jenkins.model.Jenkins;
import org.jenkinsci.remoting.nio.NioChannelHub;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
......@@ -28,14 +29,22 @@ public class CliProtocol2 extends CliProtocol {
@Override
public void handle(Socket socket) throws IOException, InterruptedException {
new Handler2(socket).run();
new Handler2(nio.getHub(), socket).run();
}
protected static class Handler2 extends Handler {
/**
* @deprecated as of 1.559
* Use {@link #Handler2(NioChannelHub, Socket)}
*/
public Handler2(Socket socket) {
super(socket);
}
public Handler2(NioChannelHub hub, Socket socket) {
super(hub, socket);
}
@Override
public void run() throws IOException, InterruptedException {
try {
......
......@@ -73,7 +73,7 @@ public class Channels {
* Kill the process when the channel is severed.
*/
@Override
protected synchronized void terminate(IOException e) {
public synchronized void terminate(IOException e) {
super.terminate(e);
try {
proc.kill();
......@@ -109,7 +109,7 @@ public class Channels {
* Kill the process when the channel is severed.
*/
@Override
protected synchronized void terminate(IOException e) {
public synchronized void terminate(IOException e) {
super.terminate(e);
proc.destroy();
// the stderr copier should exit by itself
......
......@@ -2,18 +2,18 @@ package jenkins.slaves;
import hudson.AbortException;
import hudson.Extension;
import hudson.model.Computer;
import hudson.remoting.Channel;
import hudson.remoting.Channel.Listener;
import hudson.remoting.ChannelBuilder;
import hudson.remoting.Engine;
import hudson.remoting.SocketInputStream;
import hudson.remoting.SocketOutputStream;
import hudson.slaves.SlaveComputer;
import jenkins.AgentProtocol;
import jenkins.model.Jenkins;
import jenkins.security.HMACConfidentialKey;
import org.jenkinsci.remoting.nio.NioChannelHub;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import javax.inject.Inject;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
......@@ -55,6 +55,9 @@ import java.util.logging.Logger;
*/
@Extension
public class JnlpSlaveAgentProtocol extends AgentProtocol {
@Inject
NioChannelSelector hub;
@Override
public String getName() {
return "JNLP-connect";
......@@ -62,10 +65,11 @@ public class JnlpSlaveAgentProtocol extends AgentProtocol {
@Override
public void handle(Socket socket) throws IOException, InterruptedException {
new Handler(socket).run();
new Handler(hub.getHub(),socket).run();
}
protected static class Handler {
protected final NioChannelHub hub;
protected final Socket socket;
/**
......@@ -82,7 +86,16 @@ public class JnlpSlaveAgentProtocol extends AgentProtocol {
*/
protected final PrintWriter out;
/**
* @deprecated as of 1.559
* Use {@link #Handler(NioChannelHub, Socket)}
*/
public Handler(Socket socket) throws IOException {
this(null,socket);
}
public Handler(NioChannelHub hub, Socket socket) throws IOException {
this.hub = hub;
this.socket = socket;
in = new DataInputStream(socket.getInputStream());
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(),"UTF-8")),true);
......@@ -121,7 +134,14 @@ public class JnlpSlaveAgentProtocol extends AgentProtocol {
logw.println("JNLP agent connected from "+ socket.getInetAddress());
try {
computer.setChannel(new BufferedInputStream(new SocketInputStream(socket)), new BufferedOutputStream(new SocketOutputStream(socket)), log,
ChannelBuilder cb;
if (hub==null)
cb = new ChannelBuilder(nodeName, Computer.threadPoolForRemoting);
else
cb = hub.newChannelBuilder(nodeName, Computer.threadPoolForRemoting);
computer.setChannel(cb.withHeaderStream(log).build(socket), log,
new Listener() {
@Override
public void onClosed(Channel channel, IOException cause) {
......
......@@ -7,6 +7,7 @@ import hudson.remoting.Channel;
import hudson.remoting.Engine;
import hudson.slaves.SlaveComputer;
import jenkins.model.Jenkins;
import org.jenkinsci.remoting.nio.NioChannelHub;
import java.io.ByteArrayInputStream;
import java.io.IOException;
......@@ -40,14 +41,22 @@ public class JnlpSlaveAgentProtocol2 extends JnlpSlaveAgentProtocol {
@Override
public void handle(Socket socket) throws IOException, InterruptedException {
new Handler2(socket).run();
new Handler2(hub.getHub(),socket).run();
}
protected static class Handler2 extends Handler {
/**
* @deprecated as of 1.559
* Use {@link #Handler2(NioChannelHub, Socket)}
*/
public Handler2(Socket socket) throws IOException {
super(socket);
}
public Handler2(NioChannelHub hub, Socket socket) throws IOException {
super(hub, socket);
}
/**
* Handles JNLP slave agent connection request (v2 protocol)
*/
......
package jenkins.slaves;
import hudson.Extension;
import hudson.model.Computer;
import org.jenkinsci.remoting.nio.NioChannelHub;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Singleton holder of {@link NioChannelHub}
*
* @author Kohsuke Kawaguchi
*/
@Extension
public class NioChannelSelector {
private NioChannelHub hub;
public NioChannelSelector() {
try {
if (!DISABLED) {
this.hub = new NioChannelHub(Computer.threadPoolForRemoting);
Computer.threadPoolForRemoting.submit(hub);
}
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Failed to launch NIO hub",e);
this.hub = null;
DISABLED = true;
}
}
public NioChannelHub getHub() {
return hub;
}
/**
* Escape hatch to disable use of NIO.
*/
public static boolean DISABLED = Boolean.getBoolean(NioChannelSelector.class.getName()+".disabled");
private static final Logger LOGGER = Logger.getLogger(NioChannelSelector.class.getName());
}
......@@ -172,7 +172,7 @@ THE SOFTWARE.
<dependency>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>remoting</artifactId>
<version>2.37</version>
<version>2.38</version>
</dependency>
<dependency>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册