It's there in a few forms, but not as far as I'd like to see it
go. OpenEJB implements a lot of these things and Jeremy's
bullets capture why pretty well. I've chatted a lot about it
with him and others at Gluecode. I've been beating poor Hiram
on the head with it forever. It's essentially xinet.d, but in
Java.
The idea is to have one consistent way of producing sockets
which is decoupled from the consumers of the sockets (e.g. the
actual protocols). Further, the EJBContainers themselves are
not (at least didn't used to be) dependent on any of the
protocols, so you can add addition implementations of protocols
to the system without having to change the container.
Despite it being in the org.openejb namespace, the code is
already generic. So what we have in OpenEJB and soon to move
into ActiveIO is this:
A Socket Producer: Contains a stack of QoSs for producing the
socket, essentially as interceptors that can be stacked up
anyway you like.
Implemented now are:
- Simple thread-pool (not used since work manager support
was added)
- Geronimo Work manager (e.g. better thread pool)
- Host Based Authorization (for example, saying only
localhost can use this IP:PORT)
- Request Logging (doesn't do much now)
To be implemented:
- SSL support
- Support for ActiveIO abstractions so more than just TCP/IP
can be used.
- Better request logger
To be integrated:
- Hiram's One-port functionality is high on the slate.
A Socket Consumer: The thing that actually reads/writes data
from the socket.
Implemented now are:
- EJBd (the custom OpenEJB ejb/jndi protocol)
- Telnet (a cheap telnet implementation I wrote)
- HTTP (a cheap HTTP implementation I wrote, Jetty's or
Tomcat's would be better)
- Admin (a small protocol to do administrative stuff with
the server like starting/stopping things)
Could be implemented:
- One to wrap jetty's stuff
- A network-based deployer
- An Admin protocol specifically for Geronimo
- Any code that allows you to pass in a socket could just be
wrapped and plugged in
- A VM-level Socket producer so "legacy" code could be
supported as well (code we don't control that insists on
creating it's own ServerSocket)
- A proxy to reroute calls to another IP:PORT
Right now in a plan you can, for example, have two producers for
the EJB protocol. One only for local traffic and one for
internal traffic.
<!-- Public, smaller thread pool and restricted access to a
set of specific hosts -->
<gbean gbeanName="geronimo:type=NetworkService,name=EJB1"
class="org.openejb.server.StandardServiceStackGBean">
<attribute name="name">EJB</attribute>
<attribute name="port">2401</attribute>
<attribute name="host">209.237.227.195</attribute>
<attribute
name="allowHosts">209.98.98.9,207.171.163.90,216.239.39.99</
attribute>
<attribute
name="logOnSuccess">HOST,NAME,THREADID,USERID</ attribute>
<attribute name="logOnFailure">HOST,NAME</attribute>
<reference name="Executor"><name>DefaultThreadPool</
name></ reference>
<reference name="Server"><gbean-
name>openejb:type=Server,name=EJB</gbean-name></reference>
</gbean>
<gbean name="DefaultThreadPool"
class="org.apache.geronimo.pool.ThreadPool">
<attribute name="keepAliveTime">5000</attribute>
<attribute name="poolSize">30</attribute>
<attribute name="poolName">DefaultThreadPool</attribute>
</gbean>
<!-- Private IP bound, bigger thread pool, access to just
the local subnet -->
<gbean gbeanName="geronimo:type=NetworkService,name=EJB2"
class="org.openejb.server.StandardServiceStackGBean">
<attribute name="name">EJB</attribute>
<attribute name="port">2402</attribute>
<attribute name="host">192.168.10.12</attribute>
<attribute name="allowHosts">255.255.255.0</attribute>
<attribute
name="logOnSuccess">HOST,NAME,THREADID,USERID</ attribute>
<attribute name="logOnFailure">HOST,NAME</attribute>
<reference name="Executor"><name>HighThreadPool</name></
reference>
<reference name="Server"><gbean-
name>openejb:type=Server,name=EJB</gbean-name></reference>
</gbean>
<gbean name="HighThreadPool"
class="org.apache.geronimo.pool.ThreadPool">
<attribute name="keepAliveTime">1000</attribute>
<attribute name="poolSize">100</attribute>
<attribute name="poolName">HighThreadPool</attribute>
</gbean>
<gbean gbeanName="openejb:type=Server,name=EJB"
class="org.openejb.server.ejbd.EjbServerGBean">
<!-- blah blah blah -->
</gbean>
In this setup we have two different pools. It would be nice to
use the same pool for both, but partition them differently so we
could guarantee no one is dominating the pool.
The StandardServiceStackGBean is just one collection of QoSs.
You could create another gbean that had the ones you want or you
could declare them individually in a plan (a little hard to
manage though).
<gbean
gbeanName="geronimo:type=NetworkService,interceptor=Daemon"
class="org.openejb.server.ServiceDaemon">
<attribute name="port">2402</attribute>
<attribute name="inetAddress">192.168.10.12</attribute>
<reference name="SocketService"><gbean-
name>geronimo:type=NetworkService,interceptor=Logger</gbean-
name></ reference>
</gbean>
<gbean
gbeanName="geronimo:type=NetworkService,interceptor=Logger"
class="org.openejb.server.ServiceLogger">
<attribute name="logOnSuccess">HOST,THREADID</attribute>
<attribute name="logOnFailure">HOST</attribute>
<reference name="SocketService"><gbean-
name>geronimo:type=NetworkService,interceptor=AccessController</
gbean-name></reference>
</gbean>
<gbean
gbeanName="geronimo:type=NetworkService,interceptor=Pool"
class="org.openejb.server.ServicePool">
<attribute name="keepAliveTime">5000</attribute>
<attribute name="poolSize">30</attribute>
<attribute name="poolName">EjbRequestThreadPool</attribute>
<reference name="SocketService"><gbean-
name>openejb:type=Server,name=EJB</gbean-name></reference>
</gbean>
<gbean gbeanName="openejb:type=Server,name=EJB"
class="org.openejb.server.ejbd.EjbServerGBean">
<!-- blah blah blah -->
</gbean>
This is more or less same as the above except we;
- explicitly declared all the interceptors in the stack
- left out the Host-based authorization QoS
- Constructed the ServicePool in away that makes it
create it's own pool instead of passing one in.
Anyway, that's just what is there now. It gets a lot more fun
when you add SSL and have support for a remote deployer. Then
you could could still have a remote deployer, but enforce it
over SSL and restrict the hosts that can access it. Much more
is possible if you get creative. For example, HBA is still
really a naive way to prevent a denial of service attack. You
could implement something that did clever things to thwart those
kind of attacks, but only use that for publicly bound socket
producers.
This is a big long email, but by no means complete. There are
really a lot of things you can do with having a more robust way
that sockets are dished out in the system and ensuring the whole
server is using it. I consider what we have to be a good
prototype and plan to rewrite it all in ActiveIO to be more
transport agnostic. I know Greg Wilkins has some great code in
Jetty that is related and would like to get him contributing to
it was well if he's up for it.
-David
On Aug 13, 2005, at 6:24 PM, Dain Sundstrom wrote:
Isn't this something that ActiveIO already does? Hiram? David?
-dain
On Aug 13, 2005, at 5:24 PM, [EMAIL PROTECTED] wrote:
Jeremy Boynes <[EMAIL PROTECTED]> wrote on 14/08/2005 02:44:40
AM:
> Aaron's recent thread on SSL has made we wonder if we should
consider
> providing our own socket listeners for HTTP(S) and other
protocols
> rather than using the ones supplied by the containers we are
embedding.
>
> Reasons for doing it include:
> * ability to integrate with custom work managers (thread
pools) and
> SSL infrastructure
> * consistency across all embedded containers
> * potential for multi-protocol support on one end-point
> (i.e. multiplexing everything over one port like WebLogic
does which
> can make life easier when firewalls are involved)
> * potential for integrating with custom QoS frameworks e.g.
allowing
> custom negotiation with load-balancers in a clustered
environment
> * potential for hi-av version upgrades where we can version in a
> upgraded component and hand off the physical socket
resulting in
> no loss of availability
>
> Note that none of those features are HTTP specific.
>
> The downside of course is that it may weaken integration
between the
> listener and the container being embedded; for some
containers they may
> be so closely coupled that doing this will actually make things
> difficult. For example, I think doing this would be fairly
easy for
> Jetty, I don't know how easy it would be for Tomcat, OpenEJB,
JMX,
> ActiveMQ etc.
This sounds like a good idea. I assume we aren't forcing
containers to use this mechanism, so if someone want to
integrate container X but doesn't initially want to go to this
much effort, they can use X's socket listener and change to
use Geronimo's in the future (although this migration will
impact their configuration).
If we do end up going down this path, it would be worthwhile
talking with the Derby project about SSL and authentication
for the network server. AFAIK, this work hasn't been started
yet, so it would probably be a good time to talk with them.
See the mail thread from the links in http://issues.apache.org/
jira/browse/ GERONIMO-842 .
John
>
> --
> Jeremy
This e-mail message and any attachments may contain
confidential, proprietary or non-public information. This
information is intended solely for the designated recipient
(s). If an addressing or transmission error has misdirected
this e-mail, please notify the sender immediately and destroy
this e-mail. Any review, dissemination, use or reliance upon
this information by unintended recipients is prohibited. Any
opinions expressed in this e-mail are those of the author
personally.