Jetty
  1. Jetty
  2. JETTY-496

Support inetd/xinetd through use of System.inheritedChannel()

    Details

    • Type: New Feature New Feature
    • Status: Resolved Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 6.1.15.rc4
    • Component/s: HTTP, NIO
    • Labels:
      None
    • Number of attachments :
      5

      Description

      It would be very nice if Jetty would support use of inetd/xinetd for use in hosting environments. The scenario is that there are many virtual hosts, each with their own jetty server running as that user for security reasons, but that's a lot of system resource. Especially if some of them are rarely actually using the server.

      Some way to launch the server on demand would be ideal, and on Linux there is xinetd for just this purpose. Since Java 5 the API System.inheritedChannel() has existed just for this purpose.

      I have found no servlet containers with this feature. It would be really great to have it, and jetty looks like an ideal server for hosting environments due to its small size and effeciency.

      1. java-server.tar.gz
        1 kB
        Michael Brown
      2. jetty496_xinetdsupport-6.diff
        10 kB
        Athena Yao
      3. jetty496_xinetdsupport-7.diff
        11 kB
        Athena Yao
      4. jetty-496-inheritedchannel-6.diff
        7 kB
        Athena Yao
      5. jetty-496-inheritedchannel-7.diff
        7 kB
        Athena Yao

        Activity

        Hide
        Michael Brown added a comment -

        Sorry, I seem to have assigned the wrong priority, and don't see how to change it. It would be really nice, but it's not a blocker.

        Show
        Michael Brown added a comment - Sorry, I seem to have assigned the wrong priority, and don't see how to change it. It would be really nice, but it's not a blocker.
        Hide
        Greg Wilkins added a comment -

        I will research this

        Show
        Greg Wilkins added a comment - I will research this
        Hide
        Greg Wilkins added a comment -

        Is the inherited channel the server socket with the client socket ready to accepted, or is it the accepted client connection?

        If it is the later, should jetty try to open the server socket or just deal with the client connection until it is closed and then exit?

        cheers

        Show
        Greg Wilkins added a comment - Is the inherited channel the server socket with the client socket ready to accepted, or is it the accepted client connection? If it is the later, should jetty try to open the server socket or just deal with the client connection until it is closed and then exit? cheers
        Hide
        Michael Brown added a comment -

        Hi!.. I am just doing a bit of research, and will come back with what I know.

        The general gist that I have so far is that Jetty should inherit the socket from inetd and then handle receiving connectings itself in an ongoing basis.. So inetd is acting as a lazy launch platform, but not launching per request.

        As I say, I'll come back with more specifics shortly, and hopefully some code samples.

        Show
        Michael Brown added a comment - Hi!.. I am just doing a bit of research, and will come back with what I know. The general gist that I have so far is that Jetty should inherit the socket from inetd and then handle receiving connectings itself in an ongoing basis.. So inetd is acting as a lazy launch platform, but not launching per request. As I say, I'll come back with more specifics shortly, and hopefully some code samples.
        Hide
        Michael Brown added a comment -

        Forgetting my manners.

        Thanks for taking this on! ...

        Show
        Michael Brown added a comment - Forgetting my manners. Thanks for taking this on! ...
        Hide
        Greg Wilkins added a comment -

        Michael Brown,

        thanks for bringing it to our attention.

        if it is indeed the accepting server socket that is passed, then I believe it will be very simple to support.

        cheers

        Show
        Greg Wilkins added a comment - Michael Brown, thanks for bringing it to our attention. if it is indeed the accepting server socket that is passed, then I believe it will be very simple to support. cheers
        Hide
        Michael Brown added a comment -

        Ok, a long delay and a doctors visit later.

        I'm attaching a sample program, with a start script and xinetd config file. It just reports the thread count at 3 seconds intervals, so with multiple telnets you can confirm that a single instance is handling each request. It shows how to inherit the channel and use it. Of course to give it a try yourself you'll have to edit things like the startup path, user and group name.

        Frankly it's all pretty simple stuff, but it's nice to show that the API works before anyone does some real work.

        To give credit where it's due, this test program was based on the following forum postings:

        http://forum.java.sun.com/thread.jspa?threadID=5252233&tstart=45

        Show
        Michael Brown added a comment - Ok, a long delay and a doctors visit later. I'm attaching a sample program, with a start script and xinetd config file. It just reports the thread count at 3 seconds intervals, so with multiple telnets you can confirm that a single instance is handling each request. It shows how to inherit the channel and use it. Of course to give it a try yourself you'll have to edit things like the startup path, user and group name. Frankly it's all pretty simple stuff, but it's nice to show that the API works before anyone does some real work. To give credit where it's due, this test program was based on the following forum postings: http://forum.java.sun.com/thread.jspa?threadID=5252233&tstart=45
        Hide
        Michael Brown added a comment -

        Err.. Forgot I could write a comment with the file... D'oh.. As above .

        Show
        Michael Brown added a comment - Err.. Forgot I could write a comment with the file... D'oh.. As above .
        Hide
        Greg Wilkins added a comment -

        Up for grabs

        Show
        Greg Wilkins added a comment - Up for grabs
        Hide
        Athena Yao added a comment -

        Hi Michael,

        Sorry for the long period of inactivity on this ticket. I've taken a look at the code,and I think I know what needs to be done to make Jetty use System.inheritedChannel, but one point: there will still be one instance of the inetd/xinetd service for each instance of Jetty. Jetty would get one instance of the inherited channel, then proceed to listen for incoming connections on the port in the configuration file (in this case 2002)

        I'm unsure from the previous comments whether this is what you want/need, and I want to clarify before implementing the changes to make sure I'm missing something.

        cheers

        Show
        Athena Yao added a comment - Hi Michael, Sorry for the long period of inactivity on this ticket. I've taken a look at the code,and I think I know what needs to be done to make Jetty use System.inheritedChannel, but one point: there will still be one instance of the inetd/xinetd service for each instance of Jetty. Jetty would get one instance of the inherited channel, then proceed to listen for incoming connections on the port in the configuration file (in this case 2002) I'm unsure from the previous comments whether this is what you want/need, and I want to clarify before implementing the changes to make sure I'm missing something. cheers
        Hide
        Michael Brown added a comment -

        Hi Athena,

        The key here is that Jetty should listen for connections on the inherited channel, and should not create a new server socket. This is because xinetd will launch Jetty as a result of an incoming connection on that port, and hands the port via inerhitedChannel to jetty, so that it can accept the connection, and any future connections.

        Also. Thanks for picking this up .

        Show
        Michael Brown added a comment - Hi Athena, The key here is that Jetty should listen for connections on the inherited channel, and should not create a new server socket. This is because xinetd will launch Jetty as a result of an incoming connection on that port, and hands the port via inerhitedChannel to jetty, so that it can accept the connection, and any future connections. Also. Thanks for picking this up .
        Hide
        Athena Yao added a comment -

        If I understand you correctly, xinetd hands over control of the port to jetty, so the expected use case is that you will have separate files in /etc/xinetd.d/ like this:

        service jetty

        { id = jetty1 port = 2002 ... }

        service jetty

        { id = jetty2 port = 2003 ... }

        If so, I think I have it working! I'll just need to fix it up a bit.

        Show
        Athena Yao added a comment - If I understand you correctly, xinetd hands over control of the port to jetty, so the expected use case is that you will have separate files in /etc/xinetd.d/ like this: service jetty { id = jetty1 port = 2002 ... } service jetty { id = jetty2 port = 2003 ... } If so, I think I have it working! I'll just need to fix it up a bit.
        Hide
        Athena Yao added a comment -

        Attached a patch against Jetty 7, with sample jetty-*.xml configuration file and script for usage.

        I'm not sure whether this will be ported to Jetty 6 because Jetty6 still needs to support Java1.4. System.inheritedChannel() is only available from Java 5 onwards

        – I'll have to ask.

        Show
        Athena Yao added a comment - Attached a patch against Jetty 7, with sample jetty-*.xml configuration file and script for usage. I'm not sure whether this will be ported to Jetty 6 because Jetty6 still needs to support Java1.4. System.inheritedChannel() is only available from Java 5 onwards – I'll have to ask.
        Hide
        Michael Brown added a comment -

        It should be possible to make the module conditional on the availability of System.inheritedChannel method. Then Jetty 6 will run on 1.4, and this feature would only be allowed on the 1.5 platform.

        Although, I do at the same time understand the need to keep new features to new releases.

        Show
        Michael Brown added a comment - It should be possible to make the module conditional on the availability of System.inheritedChannel method. Then Jetty 6 will run on 1.4, and this feature would only be allowed on the 1.5 platform. Although, I do at the same time understand the need to keep new features to new releases.
        Hide
        Athena Yao added a comment -

        Michael,

        Sorry for the silence. As much as possible, new features added to the experimental branch (jetty7) are added to the stable branch (jetty6). However, with this one, I was very concerned that it would prevent compatibility with Java 1.4, so I ended up sitting on it while trying to figure out how to handle that case. It turns out I need to worry about running with Java 1.4, but not about compiling with Java 1.4, which makes things much simpler.

        I'm attaching a revised patch, against both Jetty 6 and Jetty 7, for review. I'd appreciate if you could take a look at the sample xinetd configuration and sample jetty-xinetd.sh script (part of the diff) as well.

        Cheers

        Show
        Athena Yao added a comment - Michael, Sorry for the silence. As much as possible, new features added to the experimental branch (jetty7) are added to the stable branch (jetty6). However, with this one, I was very concerned that it would prevent compatibility with Java 1.4, so I ended up sitting on it while trying to figure out how to handle that case. It turns out I need to worry about running with Java 1.4, but not about compiling with Java 1.4, which makes things much simpler. I'm attaching a revised patch, against both Jetty 6 and Jetty 7, for review. I'd appreciate if you could take a look at the sample xinetd configuration and sample jetty-xinetd.sh script (part of the diff) as well. Cheers
        Hide
        Greg Wilkins added a comment -

        Athena, good work.... but I have some reservations.

        having the ability to call a 1.5 API will prevent these classes loading in 1.4. So I think this has to be a new type of connector rather than modifications to existing ones.

        Will the server handle only a single connection (the inherited one), or once started, will it be able to accept more connections? either way, when the number of connections returns to zero, should the server exit?

        As the number of connections can be expected to be low, basing a new connector type on socket server should be OK. InheritedSocketConnector it think.

        Show
        Greg Wilkins added a comment - Athena, good work.... but I have some reservations. having the ability to call a 1.5 API will prevent these classes loading in 1.4. So I think this has to be a new type of connector rather than modifications to existing ones. Will the server handle only a single connection (the inherited one), or once started, will it be able to accept more connections? either way, when the number of connections returns to zero, should the server exit? As the number of connections can be expected to be low, basing a new connector type on socket server should be OK. InheritedSocketConnector it think.
        Hide
        Athena Yao added a comment -

        Greg,

        Tested, and while I was unable to compile with 1.4, I was able to load the classes (compiled with Java 5). When running with java 1.4, System.inheritedChannel() throws a NoSuchMethodError, which can be caught, but does not prevent the classes from loading entirely. I do like the idea of inheriting off an existing class; feels cleaner. However I am not sure I understand what you mean by the server handling a single connection/closing once the number of connections drop to 0.

        If present, the inherited channel will be used as the _acceptChannel within a NIO connector. If not, jetty falls back upon normal ServerSocketChannel creation. Once it is done starting up, the Jetty server instance will act like a normal instance, handling incoming connections from browsers, etc.

        Probably the most common use case will be one like Michael described, where a sysad sets up xinetd configuration files for each user ("wait" set to yes will lock their instances of Jetty to the port in the xinetd configuration port). Users can start up their Jetty instances on demand, but it won't be running/taking up resources unless they need it. (On the very first visit, the page will take a long time to load because xinetd is launching the Jetty process, but subsequent page loads will be as normal).

        Show
        Athena Yao added a comment - Greg, Tested, and while I was unable to compile with 1.4, I was able to load the classes (compiled with Java 5). When running with java 1.4, System.inheritedChannel() throws a NoSuchMethodError, which can be caught, but does not prevent the classes from loading entirely. I do like the idea of inheriting off an existing class; feels cleaner. However I am not sure I understand what you mean by the server handling a single connection/closing once the number of connections drop to 0. If present, the inherited channel will be used as the _acceptChannel within a NIO connector. If not, jetty falls back upon normal ServerSocketChannel creation. Once it is done starting up, the Jetty server instance will act like a normal instance, handling incoming connections from browsers, etc. Probably the most common use case will be one like Michael described, where a sysad sets up xinetd configuration files for each user ("wait" set to yes will lock their instances of Jetty to the port in the xinetd configuration port). Users can start up their Jetty instances on demand, but it won't be running/taking up resources unless they need it. (On the very first visit, the page will take a long time to load because xinetd is launching the Jetty process, but subsequent page loads will be as normal).
        Hide
        Athena Yao added a comment -

        Separated it out into another class, and tweaked the other changes to point to this patch instead. Extended SelectChannelConnector for the new class.

        Show
        Athena Yao added a comment - Separated it out into another class, and tweaked the other changes to point to this patch instead. Extended SelectChannelConnector for the new class.
        Hide
        Michael Brown added a comment -

        Athena, your description was spot on.

        Show
        Michael Brown added a comment - Athena, your description was spot on.
        Hide
        Greg Wilkins added a comment -

        Jesse, can you check/test/commit this for athena.

        Thanks

        Show
        Greg Wilkins added a comment - Jesse, can you check/test/commit this for athena. Thanks
        Hide
        Greg Wilkins added a comment -

        Actually Jesse, I'm assigning this back to athena as I think she has earnt commit rights.
        She can commit etc.

        Show
        Greg Wilkins added a comment - Actually Jesse, I'm assigning this back to athena as I think she has earnt commit rights. She can commit etc.
        Hide
        Athena Yao added a comment -

        Applied the patches. Sorry, Michael, for the delay in getting this committed.

        Show
        Athena Yao added a comment - Applied the patches. Sorry, Michael, for the delay in getting this committed.

          People

          • Assignee:
            Athena Yao
            Reporter:
            Michael Brown
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: