You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by Rainer Jung <ra...@kippdata.de> on 2009/04/06 18:13:50 UTC

Re: svn commit: r762374 - in /tomcat/trunk: build.xml java/org/apache/catalina/cluster/ java/org/apache/catalina/cluster/CollectedInfo.java java/org/apache/catalina/cluster/HeartbeatListener.java

A few comments inline.

On 06.04.2009 17:09, jfclere@apache.org wrote:
> Author: jfclere
> Date: Mon Apr  6 15:09:19 2009
> New Revision: 762374
> 
> URL: http://svn.apache.org/viewvc?rev=762374&view=rev
> Log:
> First support for httpd-trunk heartbeat logic.
> 
> Added:
>     tomcat/trunk/java/org/apache/catalina/cluster/
>     tomcat/trunk/java/org/apache/catalina/cluster/CollectedInfo.java
>     tomcat/trunk/java/org/apache/catalina/cluster/HeartbeatListener.java
> Modified:
>     tomcat/trunk/build.xml
> 
> Modified: tomcat/trunk/build.xml
> URL: http://svn.apache.org/viewvc/tomcat/trunk/build.xml?rev=762374&r1=762373&r2=762374&view=diff
> ==============================================================================
> --- tomcat/trunk/build.xml (original)
> +++ tomcat/trunk/build.xml Mon Apr  6 15:09:19 2009
> @@ -204,7 +204,6 @@
>      <include name="org/apache/naming/**" />
>      <!-- Modules -->
>      <exclude name="org/apache/catalina/ant/**" />
> -    <exclude name="org/apache/catalina/cluster/**" />
>      <exclude name="org/apache/catalina/ha/**" />
>      <exclude name="org/apache/catalina/mbeans/JmxRemote*" />
>      <exclude name="org/apache/catalina/tribes/**" />

See below concerning the package name.

> Added: tomcat/trunk/java/org/apache/catalina/cluster/CollectedInfo.java
> URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/cluster/CollectedInfo.java?rev=762374&view=auto
> ==============================================================================
> --- tomcat/trunk/java/org/apache/catalina/cluster/CollectedInfo.java (added)
> +++ tomcat/trunk/java/org/apache/catalina/cluster/CollectedInfo.java Mon Apr  6 15:09:19 2009
...

> +package org.apache.catalina.cluster;

Should we really reuse this package name? Until TC 5.5 that was the old
cluster, and the package name is still in use for the same classes in
the oacc sandbox.

> +
> +/* for MBean to read ready and busy */
> +
> +import javax.management.MBeanServer;
> +import javax.management.ObjectName;
> +import javax.management.ObjectInstance;
> +import java.util.Enumeration;
> +import java.util.Iterator;
> +import java.util.Set;
> +
> +import org.apache.tomcat.util.modeler.Registry;
> +import org.apache.juli.logging.Log;
> +import org.apache.juli.logging.LogFactory;
> +
> +/*
> + * Listener to provider informations to mod_heartbeat.c
> + * *msg_format = "v=%u&ready=%u&busy=%u"; (message to send).
> + * send the muticast merssage using the format...
> + * what about the bind(IP. port) only IP makes sense (for the moment).
> + * BTW:v  = version :-)
> + */
> +public class CollectedInfo {
> +
> +    /* Collect info via JMX */
> +    protected MBeanServer mBeanServer = null;
> +    protected ObjectName objName = null;
> +
> +    int ready;
> +    int busy;
> +
> +    public CollectedInfo(String host, int port) throws Exception {
> +        init(host, port);
> +    }
> +    public void init(String host, int port) throws Exception {
> +        String sport = Integer.toString(port);
> +        mBeanServer = Registry.getRegistry(null, null).getMBeanServer();
> +        String onStr = "*:type=ThreadPool,*";

Use a constant for this string?

> +        ObjectName objectName = new ObjectName(onStr);
> +        Set set = mBeanServer.queryMBeans(objectName, null);
> +        Iterator<ObjectInstance> iterator = set.iterator();
> +        while (iterator.hasNext()) {
> +            ObjectInstance oi = iterator.next();
> +            objName = oi.getObjectName();
> +            String name = objName.getKeyProperty("name");
> +            /* Name are:
> +             * http-8080
> +             * jk-10.33.144.3-8009
> +             * jk-jfcpc%2F10.33.144.3-8009
> +             */
> +            if (port==0 && host==null)
> +                  break; /* Take the first one */
> +            String [] elenames = name.split("-");
> +            if (elenames[elenames.length-1].compareTo(sport) != 0)
> +                continue; /* port doesn't match */
> +            if (host==null)
> +                break; /* Only port done */
> +            String [] shosts = elenames[1].split("%2F");
> +            if (shosts[0].compareTo(host) == 0)
> +                break; /* Done port and host are the expected ones */
> +        }
> +        if (objName == null)
> +            throw(new Exception("Can't find connector for " + host + ":" + sport));
> +        
> +    }
> +
> +    public void refresh() throws Exception {
> +        if (mBeanServer == null || objName == null) {
> +            throw(new Exception("Not initialized!!!"));
> +        }
> +        Integer imax = (Integer) mBeanServer.getAttribute(objName, "maxThreads");
> +
> +        // the currentThreadCount could be 0 before the threads are created...
> +        // Integer iready = (Integer) mBeanServer.getAttribute(objName, "currentThreadCount");
> +
> +        Integer ibusy  = (Integer) mBeanServer.getAttribute(objName, "currentThreadsBusy");
> +
> +        busy = ibusy.intValue();
> +        ready = imax.intValue() - ibusy;
> +    }
> +}
> 
> Added: tomcat/trunk/java/org/apache/catalina/cluster/HeartbeatListener.java
> URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/cluster/HeartbeatListener.java?rev=762374&view=auto
> ==============================================================================
> --- tomcat/trunk/java/org/apache/catalina/cluster/HeartbeatListener.java (added)
> +++ tomcat/trunk/java/org/apache/catalina/cluster/HeartbeatListener.java Mon Apr  6 15:09:19 2009
...
> +package org.apache.catalina.cluster;

See above.

> +
> +import org.apache.catalina.ContainerEvent;
> +import org.apache.catalina.ContainerListener;
> +import org.apache.catalina.Engine;
> +import org.apache.catalina.Lifecycle;
> +import org.apache.catalina.LifecycleEvent;
> +import org.apache.catalina.LifecycleListener;
> +import org.apache.juli.logging.Log;
> +import org.apache.juli.logging.LogFactory;
> +
> +import org.apache.catalina.connector.Connector;
> +
> +import java.net.MulticastSocket;
> +import java.net.InetAddress;
> +import java.net.DatagramPacket;
> +import java.io.UnsupportedEncodingException;
> +
> +import org.apache.tomcat.util.modeler.Registry;
> +
> +/*
> + * Listener to provider informations to mod_heartbeat.c
> + * *msg_format = "v=%u&ready=%u&busy=%u"; (message to send).
> + * send the muticast merssage using the format...
> + * what about the bind(IP. port) only IP makes sense (for the moment).
> + * BTW:v  = version :-)
> + */
> +public class HeartbeatListener
> +    implements LifecycleListener, ContainerListener {
> +
> +    public static Log log = LogFactory.getLog(HeartbeatListener.class);

public?

> +
> +    /* To allow to select the connector */
> +    int port = 0;
> +    String host = null;
> +    public void setHost(String host) { this.host = host; }
> +    public void setPort(int port) { this.port = port; }

Will we need getters as well?

> +
> +    /* for multicasting stuff */
> +    MulticastSocket s = null;
> +    InetAddress group = null;
> +    String ip = "224.0.1.105"; /* Multicast IP */
> +    int multiport = 23364;     /* Multicast Port */

I assume those two will be configurable in a future version ...

> +
> +    public void setGroup(String ip) { this.ip = ip; }
> +    public void setMultiport(int multiport) { this.multiport = multiport; }
> +
> +    private CollectedInfo coll = null;
> +
> +    public void containerEvent(ContainerEvent event) {
> +    }
> +
> +    public void lifecycleEvent(LifecycleEvent event) {
> +        Object source = event.getLifecycle();
> +        if (Lifecycle.PERIODIC_EVENT.equals(event.getType())) {
> +            if (s == null) {
> +                try {
> +                    group = InetAddress.getByName(ip);
> +                    s = new MulticastSocket(port);
> +                    s.setTimeToLive(16);

Use a constant instead of "16"?

> +                    s.joinGroup(group);
> +                } catch (Exception ex) {
> +                    log.error("Unable to use multicast: " + ex);
> +                    s = null;
> +                    return;
> +                } 
> +            }
> +// * *msg_format = "v=%u&ready=%u&busy=%u"; (message to send).
> +// v = version (1)
> +// ready & ready are read from the scoreboard in httpd.
> +// Endpoint ( getCurrentThreadsBusy ) ( getMaxThreads )

What's the use of these comments?

> +            if (coll == null) {
> +                try {
> +                    coll = new CollectedInfo(host, port);
> +                } catch (Exception ex) {
> +                    log.error("Unable to initialize info collection: " + ex);
> +                    coll = null;
> +                    return;
> +                } 
> +            }
> +            try {
> +                coll.refresh();
> +            } catch (Exception ex) {
> +                log.error("Unable to collect load information: " + ex);
> +                coll = null;
> +                return;
> +            }
> +            String output = new String();
> +            output = "v=1&ready=" + coll.ready + "&busy=" + coll.busy;

You might want to use string constants for the param names.

> +            byte[] buf;
> +            try {
> +                buf = output.getBytes("US-ASCII");
> +            } catch (UnsupportedEncodingException ex) {
> +                buf = output.getBytes();
> +            }
> +            DatagramPacket data = new DatagramPacket(buf, buf.length, group, multiport);
> +            try {
> +                s.send(data);
> +            } catch (Exception ex) {
> +                log.error("Unable to send colllected load information: " + ex);
> +                System.out.println(ex);

Please no System.out.println(). Left over from debugging ;)

> +                s.close();
> +                s = null;
> +            }
> +        }
> +    }
> +
> +}

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


Re: svn commit: r762374 - in /tomcat/trunk: build.xml java/org/apache/catalina/cluster/ java/org/apache/catalina/cluster/CollectedInfo.java java/org/apache/catalina/cluster/HeartbeatListener.java

Posted by Rainer Jung <ra...@kippdata.de>.
Hi Jean-Frederic,

On 06.04.2009 18:40, jean-frederic clere wrote:
> Rainer Jung wrote:
>> On 06.04.2009 17:09, jfclere@apache.org wrote:
>>> Author: jfclere
>>> +package org.apache.catalina.cluster;
>>
>> Should we really reuse this package name? Until TC 5.5 that was the old
>> cluster, and the package name is still in use for the same classes in
>> the oacc sandbox.
> 
> Ok... What about backend?

The thing might grow, so why don't we choose a sub package of
org.apache.catalina.custer, like e.g. o.a.c.c.xxx with xxx e.g.

- gauging
- rating
- measuring
- measurement

or depending on what the protocol will do in the future

- heartbeat
- detection

The old cluster and oacc sandbox already use mcast and multicast as sub
packages.

Regards,

Rainer

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


Re: svn commit: r762374 - in /tomcat/trunk: build.xml java/org/apache/catalina/cluster/ java/org/apache/catalina/cluster/CollectedInfo.java java/org/apache/catalina/cluster/HeartbeatListener.java

Posted by Filip Hanik - Dev Lists <de...@hanik.com>.
jean-frederic clere wrote:
> Filip Hanik - Dev Lists wrote:
>> Is the idea here to communicate the Tomcat server state to httpd 
>> using multicast?
>
> Yes.
>
>> For that, you could simply build the feature set into 
>> org.apache.catalina.ha where you can send multicast packets, where 
>> you already have heart beat information etc.
>
> Well the feature doesn't require a clustered tomcat.
you dont' have to do any replication in order to take advantage of that.
if you still want to write new code, just copy paste so you don't have 
to run into all the same bugs we did long time ago :)

Filip
>
>> So going that route, why not use code, or at least copy/paste the 
>> code where we fixed the bugs :)
>>
>> However, if I was to voice my opinion, I think you can easily 
>> transfer all the information you need as HTTP headers, and hence you 
>> could do so with minimal coding effort.
>> Multicast seems funky, since the httpd server already talks 
>> TCP/HTTP/AJP to tomcat. Why another transport protocol. Multicast is 
>> usually disallowed through firewalls, which means the very common 
>> scenario of having httpd in the DMZ and tomcat on the other side of 
>> the firewall will not work.
>
> The idea is to use this code with the already existing code in 
> httpd-trunk and the httpd module uses multicast.
> But yes I agree that the idea to use TCP/HTTP is a good option too but 
> that requires more code on the httpd side.
>
> Cheers
>
> Jean-Frederic
>
>>
>> Filip
>>
>> jean-frederic clere wrote:
>>> Rainer Jung wrote:
>>>> A few comments inline.
>>>>
>>>> On 06.04.2009 17:09, jfclere@apache.org wrote:
>>>>> Author: jfclere
>>>>> Date: Mon Apr  6 15:09:19 2009
>>>>> New Revision: 762374
>>>>>
>>>>> URL: http://svn.apache.org/viewvc?rev=762374&view=rev
>>>>> Log:
>>>>> First support for httpd-trunk heartbeat logic.
>>>>>
>>>>> Added:
>>>>>     tomcat/trunk/java/org/apache/catalina/cluster/
>>>>>     tomcat/trunk/java/org/apache/catalina/cluster/CollectedInfo.java
>>>>>     
>>>>> tomcat/trunk/java/org/apache/catalina/cluster/HeartbeatListener.java
>>>>> Modified:
>>>>>     tomcat/trunk/build.xml
>>>>>
>>>>> Modified: tomcat/trunk/build.xml
>>>>> URL: 
>>>>> http://svn.apache.org/viewvc/tomcat/trunk/build.xml?rev=762374&r1=762373&r2=762374&view=diff 
>>>>>
>>>>> ============================================================================== 
>>>>>
>>>>> --- tomcat/trunk/build.xml (original)
>>>>> +++ tomcat/trunk/build.xml Mon Apr  6 15:09:19 2009
>>>>> @@ -204,7 +204,6 @@
>>>>>      <include name="org/apache/naming/**" />
>>>>>      <!-- Modules -->
>>>>>      <exclude name="org/apache/catalina/ant/**" />
>>>>> -    <exclude name="org/apache/catalina/cluster/**" />
>>>>>      <exclude name="org/apache/catalina/ha/**" />
>>>>>      <exclude name="org/apache/catalina/mbeans/JmxRemote*" />
>>>>>      <exclude name="org/apache/catalina/tribes/**" />
>>>>
>>>> See below concerning the package name.
>>>>
>>>>> Added: 
>>>>> tomcat/trunk/java/org/apache/catalina/cluster/CollectedInfo.java
>>>>> URL: 
>>>>> http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/cluster/CollectedInfo.java?rev=762374&view=auto 
>>>>>
>>>>> ============================================================================== 
>>>>>
>>>>> --- 
>>>>> tomcat/trunk/java/org/apache/catalina/cluster/CollectedInfo.java 
>>>>> (added)
>>>>> +++ 
>>>>> tomcat/trunk/java/org/apache/catalina/cluster/CollectedInfo.java 
>>>>> Mon Apr  6 15:09:19 2009
>>>> ...
>>>>
>>>>> +package org.apache.catalina.cluster;
>>>>
>>>> Should we really reuse this package name? Until TC 5.5 that was the 
>>>> old
>>>> cluster, and the package name is still in use for the same classes in
>>>> the oacc sandbox.
>>>
>>> Ok... What about backend?
>>>
>>>>
>>>>> +
>>>>> +/* for MBean to read ready and busy */
>>>>> +
>>>>> +import javax.management.MBeanServer;
>>>>> +import javax.management.ObjectName;
>>>>> +import javax.management.ObjectInstance;
>>>>> +import java.util.Enumeration;
>>>>> +import java.util.Iterator;
>>>>> +import java.util.Set;
>>>>> +
>>>>> +import org.apache.tomcat.util.modeler.Registry;
>>>>> +import org.apache.juli.logging.Log;
>>>>> +import org.apache.juli.logging.LogFactory;
>>>>> +
>>>>> +/*
>>>>> + * Listener to provider informations to mod_heartbeat.c
>>>>> + * *msg_format = "v=%u&ready=%u&busy=%u"; (message to send).
>>>>> + * send the muticast merssage using the format...
>>>>> + * what about the bind(IP. port) only IP makes sense (for the 
>>>>> moment).
>>>>> + * BTW:v  = version :-)
>>>>> + */
>>>>> +public class CollectedInfo {
>>>>> +
>>>>> +    /* Collect info via JMX */
>>>>> +    protected MBeanServer mBeanServer = null;
>>>>> +    protected ObjectName objName = null;
>>>>> +
>>>>> +    int ready;
>>>>> +    int busy;
>>>>> +
>>>>> +    public CollectedInfo(String host, int port) throws Exception {
>>>>> +        init(host, port);
>>>>> +    }
>>>>> +    public void init(String host, int port) throws Exception {
>>>>> +        String sport = Integer.toString(port);
>>>>> +        mBeanServer = Registry.getRegistry(null, 
>>>>> null).getMBeanServer();
>>>>> +        String onStr = "*:type=ThreadPool,*";
>>>>
>>>> Use a constant for this string?
>>>>
>>>>> +        ObjectName objectName = new ObjectName(onStr);
>>>>> +        Set set = mBeanServer.queryMBeans(objectName, null);
>>>>> +        Iterator<ObjectInstance> iterator = set.iterator();
>>>>> +        while (iterator.hasNext()) {
>>>>> +            ObjectInstance oi = iterator.next();
>>>>> +            objName = oi.getObjectName();
>>>>> +            String name = objName.getKeyProperty("name");
>>>>> +            /* Name are:
>>>>> +             * http-8080
>>>>> +             * jk-10.33.144.3-8009
>>>>> +             * jk-jfcpc%2F10.33.144.3-8009
>>>>> +             */
>>>>> +            if (port==0 && host==null)
>>>>> +                  break; /* Take the first one */
>>>>> +            String [] elenames = name.split("-");
>>>>> +            if (elenames[elenames.length-1].compareTo(sport) != 0)
>>>>> +                continue; /* port doesn't match */
>>>>> +            if (host==null)
>>>>> +                break; /* Only port done */
>>>>> +            String [] shosts = elenames[1].split("%2F");
>>>>> +            if (shosts[0].compareTo(host) == 0)
>>>>> +                break; /* Done port and host are the expected 
>>>>> ones */
>>>>> +        }
>>>>> +        if (objName == null)
>>>>> +            throw(new Exception("Can't find connector for " + 
>>>>> host + ":" + sport));
>>>>> +        +    }
>>>>> +
>>>>> +    public void refresh() throws Exception {
>>>>> +        if (mBeanServer == null || objName == null) {
>>>>> +            throw(new Exception("Not initialized!!!"));
>>>>> +        }
>>>>> +        Integer imax = (Integer) 
>>>>> mBeanServer.getAttribute(objName, "maxThreads");
>>>>> +
>>>>> +        // the currentThreadCount could be 0 before the threads 
>>>>> are created...
>>>>> +        // Integer iready = (Integer) 
>>>>> mBeanServer.getAttribute(objName, "currentThreadCount");
>>>>> +
>>>>> +        Integer ibusy  = (Integer) 
>>>>> mBeanServer.getAttribute(objName, "currentThreadsBusy");
>>>>> +
>>>>> +        busy = ibusy.intValue();
>>>>> +        ready = imax.intValue() - ibusy;
>>>>> +    }
>>>>> +}
>>>>>
>>>>> Added: 
>>>>> tomcat/trunk/java/org/apache/catalina/cluster/HeartbeatListener.java
>>>>> URL: 
>>>>> http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/cluster/HeartbeatListener.java?rev=762374&view=auto 
>>>>>
>>>>> ============================================================================== 
>>>>>
>>>>> --- 
>>>>> tomcat/trunk/java/org/apache/catalina/cluster/HeartbeatListener.java 
>>>>> (added)
>>>>> +++ 
>>>>> tomcat/trunk/java/org/apache/catalina/cluster/HeartbeatListener.java 
>>>>> Mon Apr  6 15:09:19 2009
>>>> ...
>>>>> +package org.apache.catalina.cluster;
>>>>
>>>> See above.
>>>>
>>>>> +
>>>>> +import org.apache.catalina.ContainerEvent;
>>>>> +import org.apache.catalina.ContainerListener;
>>>>> +import org.apache.catalina.Engine;
>>>>> +import org.apache.catalina.Lifecycle;
>>>>> +import org.apache.catalina.LifecycleEvent;
>>>>> +import org.apache.catalina.LifecycleListener;
>>>>> +import org.apache.juli.logging.Log;
>>>>> +import org.apache.juli.logging.LogFactory;
>>>>> +
>>>>> +import org.apache.catalina.connector.Connector;
>>>>> +
>>>>> +import java.net.MulticastSocket;
>>>>> +import java.net.InetAddress;
>>>>> +import java.net.DatagramPacket;
>>>>> +import java.io.UnsupportedEncodingException;
>>>>> +
>>>>> +import org.apache.tomcat.util.modeler.Registry;
>>>>> +
>>>>> +/*
>>>>> + * Listener to provider informations to mod_heartbeat.c
>>>>> + * *msg_format = "v=%u&ready=%u&busy=%u"; (message to send).
>>>>> + * send the muticast merssage using the format...
>>>>> + * what about the bind(IP. port) only IP makes sense (for the 
>>>>> moment).
>>>>> + * BTW:v  = version :-)
>>>>> + */
>>>>> +public class HeartbeatListener
>>>>> +    implements LifecycleListener, ContainerListener {
>>>>> +
>>>>> +    public static Log log = 
>>>>> LogFactory.getLog(HeartbeatListener.class);
>>>>
>>>> public?
>>>
>>> fixed.
>>>
>>>>
>>>>> +
>>>>> +    /* To allow to select the connector */
>>>>> +    int port = 0;
>>>>> +    String host = null;
>>>>> +    public void setHost(String host) { this.host = host; }
>>>>> +    public void setPort(int port) { this.port = port; }
>>>>
>>>> Will we need getters as well?
>>>
>>> Probably :-)
>>>
>>>>
>>>>> +
>>>>> +    /* for multicasting stuff */
>>>>> +    MulticastSocket s = null;
>>>>> +    InetAddress group = null;
>>>>> +    String ip = "224.0.1.105"; /* Multicast IP */
>>>>> +    int multiport = 23364;     /* Multicast Port */
>>>>
>>>> I assume those two will be configurable in a future version ...
>>>
>>> ? They are already setGroup() and setPort().
>>>
>>>>
>>>>> +
>>>>> +    public void setGroup(String ip) { this.ip = ip; }
>>>>> +    public void setMultiport(int multiport) { this.multiport = 
>>>>> multiport; }
>>>>> +
>>>>> +    private CollectedInfo coll = null;
>>>>> +
>>>>> +    public void containerEvent(ContainerEvent event) {
>>>>> +    }
>>>>> +
>>>>> +    public void lifecycleEvent(LifecycleEvent event) {
>>>>> +        Object source = event.getLifecycle();
>>>>> +        if (Lifecycle.PERIODIC_EVENT.equals(event.getType())) {
>>>>> +            if (s == null) {
>>>>> +                try {
>>>>> +                    group = InetAddress.getByName(ip);
>>>>> +                    s = new MulticastSocket(port);
>>>>> +                    s.setTimeToLive(16);
>>>>
>>>> Use a constant instead of "16"?
>>>
>>> I have added a get/set for Ttl.
>>>
>>>>
>>>>> +                    s.joinGroup(group);
>>>>> +                } catch (Exception ex) {
>>>>> +                    log.error("Unable to use multicast: " + ex);
>>>>> +                    s = null;
>>>>> +                    return;
>>>>> +                } +            }
>>>>> +// * *msg_format = "v=%u&ready=%u&busy=%u"; (message to send).
>>>>> +// v = version (1)
>>>>> +// ready & ready are read from the scoreboard in httpd.
>>>>> +// Endpoint ( getCurrentThreadsBusy ) ( getMaxThreads )
>>>>
>>>> What's the use of these comments?
>>>
>>> Oops.
>>>
>>>>
>>>>> +            if (coll == null) {
>>>>> +                try {
>>>>> +                    coll = new CollectedInfo(host, port);
>>>>> +                } catch (Exception ex) {
>>>>> +                    log.error("Unable to initialize info 
>>>>> collection: " + ex);
>>>>> +                    coll = null;
>>>>> +                    return;
>>>>> +                } +            }
>>>>> +            try {
>>>>> +                coll.refresh();
>>>>> +            } catch (Exception ex) {
>>>>> +                log.error("Unable to collect load information: " 
>>>>> + ex);
>>>>> +                coll = null;
>>>>> +                return;
>>>>> +            }
>>>>> +            String output = new String();
>>>>> +            output = "v=1&ready=" + coll.ready + "&busy=" + 
>>>>> coll.busy;
>>>>
>>>> You might want to use string constants for the param names.
>>>>
>>>>> +            byte[] buf;
>>>>> +            try {
>>>>> +                buf = output.getBytes("US-ASCII");
>>>>> +            } catch (UnsupportedEncodingException ex) {
>>>>> +                buf = output.getBytes();
>>>>> +            }
>>>>> +            DatagramPacket data = new DatagramPacket(buf, 
>>>>> buf.length, group, multiport);
>>>>> +            try {
>>>>> +                s.send(data);
>>>>> +            } catch (Exception ex) {
>>>>> +                log.error("Unable to send colllected load 
>>>>> information: " + ex);
>>>>> +                System.out.println(ex);
>>>>
>>>> Please no System.out.println(). Left over from debugging ;)
>>>
>>> Oops.
>>>
>>> Cheers
>>>
>>> Jean-Frederic
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
>>> For additional commands, e-mail: dev-help@tomcat.apache.org
>>>
>>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
>> For additional commands, e-mail: dev-help@tomcat.apache.org
>>
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: dev-help@tomcat.apache.org
>
>


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


Re: svn commit: r762374 - in /tomcat/trunk: build.xml java/org/apache/catalina/cluster/ java/org/apache/catalina/cluster/CollectedInfo.java java/org/apache/catalina/cluster/HeartbeatListener.java

Posted by jean-frederic clere <jf...@gmail.com>.
Filip Hanik - Dev Lists wrote:
> Is the idea here to communicate the Tomcat server state to httpd using 
> multicast?

Yes.

> For that, you could simply build the feature set into 
> org.apache.catalina.ha where you can send multicast packets, where you 
> already have heart beat information etc.

Well the feature doesn't require a clustered tomcat.

> So going that route, why not use code, or at least copy/paste the code 
> where we fixed the bugs :)
> 
> However, if I was to voice my opinion, I think you can easily transfer 
> all the information you need as HTTP headers, and hence you could do so 
> with minimal coding effort.
> Multicast seems funky, since the httpd server already talks TCP/HTTP/AJP 
> to tomcat. Why another transport protocol. Multicast is usually 
> disallowed through firewalls, which means the very common scenario of 
> having httpd in the DMZ and tomcat on the other side of the firewall 
> will not work.

The idea is to use this code with the already existing code in 
httpd-trunk and the httpd module uses multicast.
But yes I agree that the idea to use TCP/HTTP is a good option too but 
that requires more code on the httpd side.

Cheers

Jean-Frederic

> 
> Filip
> 
> jean-frederic clere wrote:
>> Rainer Jung wrote:
>>> A few comments inline.
>>>
>>> On 06.04.2009 17:09, jfclere@apache.org wrote:
>>>> Author: jfclere
>>>> Date: Mon Apr  6 15:09:19 2009
>>>> New Revision: 762374
>>>>
>>>> URL: http://svn.apache.org/viewvc?rev=762374&view=rev
>>>> Log:
>>>> First support for httpd-trunk heartbeat logic.
>>>>
>>>> Added:
>>>>     tomcat/trunk/java/org/apache/catalina/cluster/
>>>>     tomcat/trunk/java/org/apache/catalina/cluster/CollectedInfo.java
>>>>     
>>>> tomcat/trunk/java/org/apache/catalina/cluster/HeartbeatListener.java
>>>> Modified:
>>>>     tomcat/trunk/build.xml
>>>>
>>>> Modified: tomcat/trunk/build.xml
>>>> URL: 
>>>> http://svn.apache.org/viewvc/tomcat/trunk/build.xml?rev=762374&r1=762373&r2=762374&view=diff 
>>>>
>>>> ============================================================================== 
>>>>
>>>> --- tomcat/trunk/build.xml (original)
>>>> +++ tomcat/trunk/build.xml Mon Apr  6 15:09:19 2009
>>>> @@ -204,7 +204,6 @@
>>>>      <include name="org/apache/naming/**" />
>>>>      <!-- Modules -->
>>>>      <exclude name="org/apache/catalina/ant/**" />
>>>> -    <exclude name="org/apache/catalina/cluster/**" />
>>>>      <exclude name="org/apache/catalina/ha/**" />
>>>>      <exclude name="org/apache/catalina/mbeans/JmxRemote*" />
>>>>      <exclude name="org/apache/catalina/tribes/**" />
>>>
>>> See below concerning the package name.
>>>
>>>> Added: tomcat/trunk/java/org/apache/catalina/cluster/CollectedInfo.java
>>>> URL: 
>>>> http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/cluster/CollectedInfo.java?rev=762374&view=auto 
>>>>
>>>> ============================================================================== 
>>>>
>>>> --- tomcat/trunk/java/org/apache/catalina/cluster/CollectedInfo.java 
>>>> (added)
>>>> +++ tomcat/trunk/java/org/apache/catalina/cluster/CollectedInfo.java 
>>>> Mon Apr  6 15:09:19 2009
>>> ...
>>>
>>>> +package org.apache.catalina.cluster;
>>>
>>> Should we really reuse this package name? Until TC 5.5 that was the old
>>> cluster, and the package name is still in use for the same classes in
>>> the oacc sandbox.
>>
>> Ok... What about backend?
>>
>>>
>>>> +
>>>> +/* for MBean to read ready and busy */
>>>> +
>>>> +import javax.management.MBeanServer;
>>>> +import javax.management.ObjectName;
>>>> +import javax.management.ObjectInstance;
>>>> +import java.util.Enumeration;
>>>> +import java.util.Iterator;
>>>> +import java.util.Set;
>>>> +
>>>> +import org.apache.tomcat.util.modeler.Registry;
>>>> +import org.apache.juli.logging.Log;
>>>> +import org.apache.juli.logging.LogFactory;
>>>> +
>>>> +/*
>>>> + * Listener to provider informations to mod_heartbeat.c
>>>> + * *msg_format = "v=%u&ready=%u&busy=%u"; (message to send).
>>>> + * send the muticast merssage using the format...
>>>> + * what about the bind(IP. port) only IP makes sense (for the moment).
>>>> + * BTW:v  = version :-)
>>>> + */
>>>> +public class CollectedInfo {
>>>> +
>>>> +    /* Collect info via JMX */
>>>> +    protected MBeanServer mBeanServer = null;
>>>> +    protected ObjectName objName = null;
>>>> +
>>>> +    int ready;
>>>> +    int busy;
>>>> +
>>>> +    public CollectedInfo(String host, int port) throws Exception {
>>>> +        init(host, port);
>>>> +    }
>>>> +    public void init(String host, int port) throws Exception {
>>>> +        String sport = Integer.toString(port);
>>>> +        mBeanServer = Registry.getRegistry(null, 
>>>> null).getMBeanServer();
>>>> +        String onStr = "*:type=ThreadPool,*";
>>>
>>> Use a constant for this string?
>>>
>>>> +        ObjectName objectName = new ObjectName(onStr);
>>>> +        Set set = mBeanServer.queryMBeans(objectName, null);
>>>> +        Iterator<ObjectInstance> iterator = set.iterator();
>>>> +        while (iterator.hasNext()) {
>>>> +            ObjectInstance oi = iterator.next();
>>>> +            objName = oi.getObjectName();
>>>> +            String name = objName.getKeyProperty("name");
>>>> +            /* Name are:
>>>> +             * http-8080
>>>> +             * jk-10.33.144.3-8009
>>>> +             * jk-jfcpc%2F10.33.144.3-8009
>>>> +             */
>>>> +            if (port==0 && host==null)
>>>> +                  break; /* Take the first one */
>>>> +            String [] elenames = name.split("-");
>>>> +            if (elenames[elenames.length-1].compareTo(sport) != 0)
>>>> +                continue; /* port doesn't match */
>>>> +            if (host==null)
>>>> +                break; /* Only port done */
>>>> +            String [] shosts = elenames[1].split("%2F");
>>>> +            if (shosts[0].compareTo(host) == 0)
>>>> +                break; /* Done port and host are the expected ones */
>>>> +        }
>>>> +        if (objName == null)
>>>> +            throw(new Exception("Can't find connector for " + host 
>>>> + ":" + sport));
>>>> +        +    }
>>>> +
>>>> +    public void refresh() throws Exception {
>>>> +        if (mBeanServer == null || objName == null) {
>>>> +            throw(new Exception("Not initialized!!!"));
>>>> +        }
>>>> +        Integer imax = (Integer) mBeanServer.getAttribute(objName, 
>>>> "maxThreads");
>>>> +
>>>> +        // the currentThreadCount could be 0 before the threads are 
>>>> created...
>>>> +        // Integer iready = (Integer) 
>>>> mBeanServer.getAttribute(objName, "currentThreadCount");
>>>> +
>>>> +        Integer ibusy  = (Integer) 
>>>> mBeanServer.getAttribute(objName, "currentThreadsBusy");
>>>> +
>>>> +        busy = ibusy.intValue();
>>>> +        ready = imax.intValue() - ibusy;
>>>> +    }
>>>> +}
>>>>
>>>> Added: 
>>>> tomcat/trunk/java/org/apache/catalina/cluster/HeartbeatListener.java
>>>> URL: 
>>>> http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/cluster/HeartbeatListener.java?rev=762374&view=auto 
>>>>
>>>> ============================================================================== 
>>>>
>>>> --- 
>>>> tomcat/trunk/java/org/apache/catalina/cluster/HeartbeatListener.java 
>>>> (added)
>>>> +++ 
>>>> tomcat/trunk/java/org/apache/catalina/cluster/HeartbeatListener.java 
>>>> Mon Apr  6 15:09:19 2009
>>> ...
>>>> +package org.apache.catalina.cluster;
>>>
>>> See above.
>>>
>>>> +
>>>> +import org.apache.catalina.ContainerEvent;
>>>> +import org.apache.catalina.ContainerListener;
>>>> +import org.apache.catalina.Engine;
>>>> +import org.apache.catalina.Lifecycle;
>>>> +import org.apache.catalina.LifecycleEvent;
>>>> +import org.apache.catalina.LifecycleListener;
>>>> +import org.apache.juli.logging.Log;
>>>> +import org.apache.juli.logging.LogFactory;
>>>> +
>>>> +import org.apache.catalina.connector.Connector;
>>>> +
>>>> +import java.net.MulticastSocket;
>>>> +import java.net.InetAddress;
>>>> +import java.net.DatagramPacket;
>>>> +import java.io.UnsupportedEncodingException;
>>>> +
>>>> +import org.apache.tomcat.util.modeler.Registry;
>>>> +
>>>> +/*
>>>> + * Listener to provider informations to mod_heartbeat.c
>>>> + * *msg_format = "v=%u&ready=%u&busy=%u"; (message to send).
>>>> + * send the muticast merssage using the format...
>>>> + * what about the bind(IP. port) only IP makes sense (for the moment).
>>>> + * BTW:v  = version :-)
>>>> + */
>>>> +public class HeartbeatListener
>>>> +    implements LifecycleListener, ContainerListener {
>>>> +
>>>> +    public static Log log = 
>>>> LogFactory.getLog(HeartbeatListener.class);
>>>
>>> public?
>>
>> fixed.
>>
>>>
>>>> +
>>>> +    /* To allow to select the connector */
>>>> +    int port = 0;
>>>> +    String host = null;
>>>> +    public void setHost(String host) { this.host = host; }
>>>> +    public void setPort(int port) { this.port = port; }
>>>
>>> Will we need getters as well?
>>
>> Probably :-)
>>
>>>
>>>> +
>>>> +    /* for multicasting stuff */
>>>> +    MulticastSocket s = null;
>>>> +    InetAddress group = null;
>>>> +    String ip = "224.0.1.105"; /* Multicast IP */
>>>> +    int multiport = 23364;     /* Multicast Port */
>>>
>>> I assume those two will be configurable in a future version ...
>>
>> ? They are already setGroup() and setPort().
>>
>>>
>>>> +
>>>> +    public void setGroup(String ip) { this.ip = ip; }
>>>> +    public void setMultiport(int multiport) { this.multiport = 
>>>> multiport; }
>>>> +
>>>> +    private CollectedInfo coll = null;
>>>> +
>>>> +    public void containerEvent(ContainerEvent event) {
>>>> +    }
>>>> +
>>>> +    public void lifecycleEvent(LifecycleEvent event) {
>>>> +        Object source = event.getLifecycle();
>>>> +        if (Lifecycle.PERIODIC_EVENT.equals(event.getType())) {
>>>> +            if (s == null) {
>>>> +                try {
>>>> +                    group = InetAddress.getByName(ip);
>>>> +                    s = new MulticastSocket(port);
>>>> +                    s.setTimeToLive(16);
>>>
>>> Use a constant instead of "16"?
>>
>> I have added a get/set for Ttl.
>>
>>>
>>>> +                    s.joinGroup(group);
>>>> +                } catch (Exception ex) {
>>>> +                    log.error("Unable to use multicast: " + ex);
>>>> +                    s = null;
>>>> +                    return;
>>>> +                } +            }
>>>> +// * *msg_format = "v=%u&ready=%u&busy=%u"; (message to send).
>>>> +// v = version (1)
>>>> +// ready & ready are read from the scoreboard in httpd.
>>>> +// Endpoint ( getCurrentThreadsBusy ) ( getMaxThreads )
>>>
>>> What's the use of these comments?
>>
>> Oops.
>>
>>>
>>>> +            if (coll == null) {
>>>> +                try {
>>>> +                    coll = new CollectedInfo(host, port);
>>>> +                } catch (Exception ex) {
>>>> +                    log.error("Unable to initialize info 
>>>> collection: " + ex);
>>>> +                    coll = null;
>>>> +                    return;
>>>> +                } +            }
>>>> +            try {
>>>> +                coll.refresh();
>>>> +            } catch (Exception ex) {
>>>> +                log.error("Unable to collect load information: " + 
>>>> ex);
>>>> +                coll = null;
>>>> +                return;
>>>> +            }
>>>> +            String output = new String();
>>>> +            output = "v=1&ready=" + coll.ready + "&busy=" + coll.busy;
>>>
>>> You might want to use string constants for the param names.
>>>
>>>> +            byte[] buf;
>>>> +            try {
>>>> +                buf = output.getBytes("US-ASCII");
>>>> +            } catch (UnsupportedEncodingException ex) {
>>>> +                buf = output.getBytes();
>>>> +            }
>>>> +            DatagramPacket data = new DatagramPacket(buf, 
>>>> buf.length, group, multiport);
>>>> +            try {
>>>> +                s.send(data);
>>>> +            } catch (Exception ex) {
>>>> +                log.error("Unable to send colllected load 
>>>> information: " + ex);
>>>> +                System.out.println(ex);
>>>
>>> Please no System.out.println(). Left over from debugging ;)
>>
>> Oops.
>>
>> Cheers
>>
>> Jean-Frederic
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
>> For additional commands, e-mail: dev-help@tomcat.apache.org
>>
>>
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: dev-help@tomcat.apache.org
> 
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


Re: svn commit: r762374 - in /tomcat/trunk: build.xml java/org/apache/catalina/cluster/ java/org/apache/catalina/cluster/CollectedInfo.java java/org/apache/catalina/cluster/HeartbeatListener.java

Posted by Filip Hanik - Dev Lists <de...@hanik.com>.
Is the idea here to communicate the Tomcat server state to httpd using 
multicast?
For that, you could simply build the feature set into 
org.apache.catalina.ha where you can send multicast packets, where you 
already have heart beat information etc.
So going that route, why not use code, or at least copy/paste the code 
where we fixed the bugs :)

However, if I was to voice my opinion, I think you can easily transfer 
all the information you need as HTTP headers, and hence you could do so 
with minimal coding effort.
Multicast seems funky, since the httpd server already talks TCP/HTTP/AJP 
to tomcat. Why another transport protocol. Multicast is usually 
disallowed through firewalls, which means the very common scenario of 
having httpd in the DMZ and tomcat on the other side of the firewall 
will not work.

Filip

jean-frederic clere wrote:
> Rainer Jung wrote:
>> A few comments inline.
>>
>> On 06.04.2009 17:09, jfclere@apache.org wrote:
>>> Author: jfclere
>>> Date: Mon Apr  6 15:09:19 2009
>>> New Revision: 762374
>>>
>>> URL: http://svn.apache.org/viewvc?rev=762374&view=rev
>>> Log:
>>> First support for httpd-trunk heartbeat logic.
>>>
>>> Added:
>>>     tomcat/trunk/java/org/apache/catalina/cluster/
>>>     tomcat/trunk/java/org/apache/catalina/cluster/CollectedInfo.java
>>>     
>>> tomcat/trunk/java/org/apache/catalina/cluster/HeartbeatListener.java
>>> Modified:
>>>     tomcat/trunk/build.xml
>>>
>>> Modified: tomcat/trunk/build.xml
>>> URL: 
>>> http://svn.apache.org/viewvc/tomcat/trunk/build.xml?rev=762374&r1=762373&r2=762374&view=diff 
>>>
>>> ============================================================================== 
>>>
>>> --- tomcat/trunk/build.xml (original)
>>> +++ tomcat/trunk/build.xml Mon Apr  6 15:09:19 2009
>>> @@ -204,7 +204,6 @@
>>>      <include name="org/apache/naming/**" />
>>>      <!-- Modules -->
>>>      <exclude name="org/apache/catalina/ant/**" />
>>> -    <exclude name="org/apache/catalina/cluster/**" />
>>>      <exclude name="org/apache/catalina/ha/**" />
>>>      <exclude name="org/apache/catalina/mbeans/JmxRemote*" />
>>>      <exclude name="org/apache/catalina/tribes/**" />
>>
>> See below concerning the package name.
>>
>>> Added: tomcat/trunk/java/org/apache/catalina/cluster/CollectedInfo.java
>>> URL: 
>>> http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/cluster/CollectedInfo.java?rev=762374&view=auto 
>>>
>>> ============================================================================== 
>>>
>>> --- tomcat/trunk/java/org/apache/catalina/cluster/CollectedInfo.java 
>>> (added)
>>> +++ tomcat/trunk/java/org/apache/catalina/cluster/CollectedInfo.java 
>>> Mon Apr  6 15:09:19 2009
>> ...
>>
>>> +package org.apache.catalina.cluster;
>>
>> Should we really reuse this package name? Until TC 5.5 that was the old
>> cluster, and the package name is still in use for the same classes in
>> the oacc sandbox.
>
> Ok... What about backend?
>
>>
>>> +
>>> +/* for MBean to read ready and busy */
>>> +
>>> +import javax.management.MBeanServer;
>>> +import javax.management.ObjectName;
>>> +import javax.management.ObjectInstance;
>>> +import java.util.Enumeration;
>>> +import java.util.Iterator;
>>> +import java.util.Set;
>>> +
>>> +import org.apache.tomcat.util.modeler.Registry;
>>> +import org.apache.juli.logging.Log;
>>> +import org.apache.juli.logging.LogFactory;
>>> +
>>> +/*
>>> + * Listener to provider informations to mod_heartbeat.c
>>> + * *msg_format = "v=%u&ready=%u&busy=%u"; (message to send).
>>> + * send the muticast merssage using the format...
>>> + * what about the bind(IP. port) only IP makes sense (for the moment).
>>> + * BTW:v  = version :-)
>>> + */
>>> +public class CollectedInfo {
>>> +
>>> +    /* Collect info via JMX */
>>> +    protected MBeanServer mBeanServer = null;
>>> +    protected ObjectName objName = null;
>>> +
>>> +    int ready;
>>> +    int busy;
>>> +
>>> +    public CollectedInfo(String host, int port) throws Exception {
>>> +        init(host, port);
>>> +    }
>>> +    public void init(String host, int port) throws Exception {
>>> +        String sport = Integer.toString(port);
>>> +        mBeanServer = Registry.getRegistry(null, 
>>> null).getMBeanServer();
>>> +        String onStr = "*:type=ThreadPool,*";
>>
>> Use a constant for this string?
>>
>>> +        ObjectName objectName = new ObjectName(onStr);
>>> +        Set set = mBeanServer.queryMBeans(objectName, null);
>>> +        Iterator<ObjectInstance> iterator = set.iterator();
>>> +        while (iterator.hasNext()) {
>>> +            ObjectInstance oi = iterator.next();
>>> +            objName = oi.getObjectName();
>>> +            String name = objName.getKeyProperty("name");
>>> +            /* Name are:
>>> +             * http-8080
>>> +             * jk-10.33.144.3-8009
>>> +             * jk-jfcpc%2F10.33.144.3-8009
>>> +             */
>>> +            if (port==0 && host==null)
>>> +                  break; /* Take the first one */
>>> +            String [] elenames = name.split("-");
>>> +            if (elenames[elenames.length-1].compareTo(sport) != 0)
>>> +                continue; /* port doesn't match */
>>> +            if (host==null)
>>> +                break; /* Only port done */
>>> +            String [] shosts = elenames[1].split("%2F");
>>> +            if (shosts[0].compareTo(host) == 0)
>>> +                break; /* Done port and host are the expected ones */
>>> +        }
>>> +        if (objName == null)
>>> +            throw(new Exception("Can't find connector for " + host 
>>> + ":" + sport));
>>> +        +    }
>>> +
>>> +    public void refresh() throws Exception {
>>> +        if (mBeanServer == null || objName == null) {
>>> +            throw(new Exception("Not initialized!!!"));
>>> +        }
>>> +        Integer imax = (Integer) mBeanServer.getAttribute(objName, 
>>> "maxThreads");
>>> +
>>> +        // the currentThreadCount could be 0 before the threads are 
>>> created...
>>> +        // Integer iready = (Integer) 
>>> mBeanServer.getAttribute(objName, "currentThreadCount");
>>> +
>>> +        Integer ibusy  = (Integer) 
>>> mBeanServer.getAttribute(objName, "currentThreadsBusy");
>>> +
>>> +        busy = ibusy.intValue();
>>> +        ready = imax.intValue() - ibusy;
>>> +    }
>>> +}
>>>
>>> Added: 
>>> tomcat/trunk/java/org/apache/catalina/cluster/HeartbeatListener.java
>>> URL: 
>>> http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/cluster/HeartbeatListener.java?rev=762374&view=auto 
>>>
>>> ============================================================================== 
>>>
>>> --- 
>>> tomcat/trunk/java/org/apache/catalina/cluster/HeartbeatListener.java 
>>> (added)
>>> +++ 
>>> tomcat/trunk/java/org/apache/catalina/cluster/HeartbeatListener.java 
>>> Mon Apr  6 15:09:19 2009
>> ...
>>> +package org.apache.catalina.cluster;
>>
>> See above.
>>
>>> +
>>> +import org.apache.catalina.ContainerEvent;
>>> +import org.apache.catalina.ContainerListener;
>>> +import org.apache.catalina.Engine;
>>> +import org.apache.catalina.Lifecycle;
>>> +import org.apache.catalina.LifecycleEvent;
>>> +import org.apache.catalina.LifecycleListener;
>>> +import org.apache.juli.logging.Log;
>>> +import org.apache.juli.logging.LogFactory;
>>> +
>>> +import org.apache.catalina.connector.Connector;
>>> +
>>> +import java.net.MulticastSocket;
>>> +import java.net.InetAddress;
>>> +import java.net.DatagramPacket;
>>> +import java.io.UnsupportedEncodingException;
>>> +
>>> +import org.apache.tomcat.util.modeler.Registry;
>>> +
>>> +/*
>>> + * Listener to provider informations to mod_heartbeat.c
>>> + * *msg_format = "v=%u&ready=%u&busy=%u"; (message to send).
>>> + * send the muticast merssage using the format...
>>> + * what about the bind(IP. port) only IP makes sense (for the moment).
>>> + * BTW:v  = version :-)
>>> + */
>>> +public class HeartbeatListener
>>> +    implements LifecycleListener, ContainerListener {
>>> +
>>> +    public static Log log = 
>>> LogFactory.getLog(HeartbeatListener.class);
>>
>> public?
>
> fixed.
>
>>
>>> +
>>> +    /* To allow to select the connector */
>>> +    int port = 0;
>>> +    String host = null;
>>> +    public void setHost(String host) { this.host = host; }
>>> +    public void setPort(int port) { this.port = port; }
>>
>> Will we need getters as well?
>
> Probably :-)
>
>>
>>> +
>>> +    /* for multicasting stuff */
>>> +    MulticastSocket s = null;
>>> +    InetAddress group = null;
>>> +    String ip = "224.0.1.105"; /* Multicast IP */
>>> +    int multiport = 23364;     /* Multicast Port */
>>
>> I assume those two will be configurable in a future version ...
>
> ? They are already setGroup() and setPort().
>
>>
>>> +
>>> +    public void setGroup(String ip) { this.ip = ip; }
>>> +    public void setMultiport(int multiport) { this.multiport = 
>>> multiport; }
>>> +
>>> +    private CollectedInfo coll = null;
>>> +
>>> +    public void containerEvent(ContainerEvent event) {
>>> +    }
>>> +
>>> +    public void lifecycleEvent(LifecycleEvent event) {
>>> +        Object source = event.getLifecycle();
>>> +        if (Lifecycle.PERIODIC_EVENT.equals(event.getType())) {
>>> +            if (s == null) {
>>> +                try {
>>> +                    group = InetAddress.getByName(ip);
>>> +                    s = new MulticastSocket(port);
>>> +                    s.setTimeToLive(16);
>>
>> Use a constant instead of "16"?
>
> I have added a get/set for Ttl.
>
>>
>>> +                    s.joinGroup(group);
>>> +                } catch (Exception ex) {
>>> +                    log.error("Unable to use multicast: " + ex);
>>> +                    s = null;
>>> +                    return;
>>> +                } +            }
>>> +// * *msg_format = "v=%u&ready=%u&busy=%u"; (message to send).
>>> +// v = version (1)
>>> +// ready & ready are read from the scoreboard in httpd.
>>> +// Endpoint ( getCurrentThreadsBusy ) ( getMaxThreads )
>>
>> What's the use of these comments?
>
> Oops.
>
>>
>>> +            if (coll == null) {
>>> +                try {
>>> +                    coll = new CollectedInfo(host, port);
>>> +                } catch (Exception ex) {
>>> +                    log.error("Unable to initialize info 
>>> collection: " + ex);
>>> +                    coll = null;
>>> +                    return;
>>> +                } +            }
>>> +            try {
>>> +                coll.refresh();
>>> +            } catch (Exception ex) {
>>> +                log.error("Unable to collect load information: " + 
>>> ex);
>>> +                coll = null;
>>> +                return;
>>> +            }
>>> +            String output = new String();
>>> +            output = "v=1&ready=" + coll.ready + "&busy=" + coll.busy;
>>
>> You might want to use string constants for the param names.
>>
>>> +            byte[] buf;
>>> +            try {
>>> +                buf = output.getBytes("US-ASCII");
>>> +            } catch (UnsupportedEncodingException ex) {
>>> +                buf = output.getBytes();
>>> +            }
>>> +            DatagramPacket data = new DatagramPacket(buf, 
>>> buf.length, group, multiport);
>>> +            try {
>>> +                s.send(data);
>>> +            } catch (Exception ex) {
>>> +                log.error("Unable to send colllected load 
>>> information: " + ex);
>>> +                System.out.println(ex);
>>
>> Please no System.out.println(). Left over from debugging ;)
>
> Oops.
>
> Cheers
>
> Jean-Frederic
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: dev-help@tomcat.apache.org
>
>


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


Re: svn commit: r762374 - in /tomcat/trunk: build.xml java/org/apache/catalina/cluster/ java/org/apache/catalina/cluster/CollectedInfo.java java/org/apache/catalina/cluster/HeartbeatListener.java

Posted by jean-frederic clere <jf...@gmail.com>.
Rainer Jung wrote:
> A few comments inline.
> 
> On 06.04.2009 17:09, jfclere@apache.org wrote:
>> Author: jfclere
>> Date: Mon Apr  6 15:09:19 2009
>> New Revision: 762374
>>
>> URL: http://svn.apache.org/viewvc?rev=762374&view=rev
>> Log:
>> First support for httpd-trunk heartbeat logic.
>>
>> Added:
>>     tomcat/trunk/java/org/apache/catalina/cluster/
>>     tomcat/trunk/java/org/apache/catalina/cluster/CollectedInfo.java
>>     tomcat/trunk/java/org/apache/catalina/cluster/HeartbeatListener.java
>> Modified:
>>     tomcat/trunk/build.xml
>>
>> Modified: tomcat/trunk/build.xml
>> URL: http://svn.apache.org/viewvc/tomcat/trunk/build.xml?rev=762374&r1=762373&r2=762374&view=diff
>> ==============================================================================
>> --- tomcat/trunk/build.xml (original)
>> +++ tomcat/trunk/build.xml Mon Apr  6 15:09:19 2009
>> @@ -204,7 +204,6 @@
>>      <include name="org/apache/naming/**" />
>>      <!-- Modules -->
>>      <exclude name="org/apache/catalina/ant/**" />
>> -    <exclude name="org/apache/catalina/cluster/**" />
>>      <exclude name="org/apache/catalina/ha/**" />
>>      <exclude name="org/apache/catalina/mbeans/JmxRemote*" />
>>      <exclude name="org/apache/catalina/tribes/**" />
> 
> See below concerning the package name.
> 
>> Added: tomcat/trunk/java/org/apache/catalina/cluster/CollectedInfo.java
>> URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/cluster/CollectedInfo.java?rev=762374&view=auto
>> ==============================================================================
>> --- tomcat/trunk/java/org/apache/catalina/cluster/CollectedInfo.java (added)
>> +++ tomcat/trunk/java/org/apache/catalina/cluster/CollectedInfo.java Mon Apr  6 15:09:19 2009
> ...
> 
>> +package org.apache.catalina.cluster;
> 
> Should we really reuse this package name? Until TC 5.5 that was the old
> cluster, and the package name is still in use for the same classes in
> the oacc sandbox.

Ok... What about backend?

> 
>> +
>> +/* for MBean to read ready and busy */
>> +
>> +import javax.management.MBeanServer;
>> +import javax.management.ObjectName;
>> +import javax.management.ObjectInstance;
>> +import java.util.Enumeration;
>> +import java.util.Iterator;
>> +import java.util.Set;
>> +
>> +import org.apache.tomcat.util.modeler.Registry;
>> +import org.apache.juli.logging.Log;
>> +import org.apache.juli.logging.LogFactory;
>> +
>> +/*
>> + * Listener to provider informations to mod_heartbeat.c
>> + * *msg_format = "v=%u&ready=%u&busy=%u"; (message to send).
>> + * send the muticast merssage using the format...
>> + * what about the bind(IP. port) only IP makes sense (for the moment).
>> + * BTW:v  = version :-)
>> + */
>> +public class CollectedInfo {
>> +
>> +    /* Collect info via JMX */
>> +    protected MBeanServer mBeanServer = null;
>> +    protected ObjectName objName = null;
>> +
>> +    int ready;
>> +    int busy;
>> +
>> +    public CollectedInfo(String host, int port) throws Exception {
>> +        init(host, port);
>> +    }
>> +    public void init(String host, int port) throws Exception {
>> +        String sport = Integer.toString(port);
>> +        mBeanServer = Registry.getRegistry(null, null).getMBeanServer();
>> +        String onStr = "*:type=ThreadPool,*";
> 
> Use a constant for this string?
> 
>> +        ObjectName objectName = new ObjectName(onStr);
>> +        Set set = mBeanServer.queryMBeans(objectName, null);
>> +        Iterator<ObjectInstance> iterator = set.iterator();
>> +        while (iterator.hasNext()) {
>> +            ObjectInstance oi = iterator.next();
>> +            objName = oi.getObjectName();
>> +            String name = objName.getKeyProperty("name");
>> +            /* Name are:
>> +             * http-8080
>> +             * jk-10.33.144.3-8009
>> +             * jk-jfcpc%2F10.33.144.3-8009
>> +             */
>> +            if (port==0 && host==null)
>> +                  break; /* Take the first one */
>> +            String [] elenames = name.split("-");
>> +            if (elenames[elenames.length-1].compareTo(sport) != 0)
>> +                continue; /* port doesn't match */
>> +            if (host==null)
>> +                break; /* Only port done */
>> +            String [] shosts = elenames[1].split("%2F");
>> +            if (shosts[0].compareTo(host) == 0)
>> +                break; /* Done port and host are the expected ones */
>> +        }
>> +        if (objName == null)
>> +            throw(new Exception("Can't find connector for " + host + ":" + sport));
>> +        
>> +    }
>> +
>> +    public void refresh() throws Exception {
>> +        if (mBeanServer == null || objName == null) {
>> +            throw(new Exception("Not initialized!!!"));
>> +        }
>> +        Integer imax = (Integer) mBeanServer.getAttribute(objName, "maxThreads");
>> +
>> +        // the currentThreadCount could be 0 before the threads are created...
>> +        // Integer iready = (Integer) mBeanServer.getAttribute(objName, "currentThreadCount");
>> +
>> +        Integer ibusy  = (Integer) mBeanServer.getAttribute(objName, "currentThreadsBusy");
>> +
>> +        busy = ibusy.intValue();
>> +        ready = imax.intValue() - ibusy;
>> +    }
>> +}
>>
>> Added: tomcat/trunk/java/org/apache/catalina/cluster/HeartbeatListener.java
>> URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/cluster/HeartbeatListener.java?rev=762374&view=auto
>> ==============================================================================
>> --- tomcat/trunk/java/org/apache/catalina/cluster/HeartbeatListener.java (added)
>> +++ tomcat/trunk/java/org/apache/catalina/cluster/HeartbeatListener.java Mon Apr  6 15:09:19 2009
> ...
>> +package org.apache.catalina.cluster;
> 
> See above.
> 
>> +
>> +import org.apache.catalina.ContainerEvent;
>> +import org.apache.catalina.ContainerListener;
>> +import org.apache.catalina.Engine;
>> +import org.apache.catalina.Lifecycle;
>> +import org.apache.catalina.LifecycleEvent;
>> +import org.apache.catalina.LifecycleListener;
>> +import org.apache.juli.logging.Log;
>> +import org.apache.juli.logging.LogFactory;
>> +
>> +import org.apache.catalina.connector.Connector;
>> +
>> +import java.net.MulticastSocket;
>> +import java.net.InetAddress;
>> +import java.net.DatagramPacket;
>> +import java.io.UnsupportedEncodingException;
>> +
>> +import org.apache.tomcat.util.modeler.Registry;
>> +
>> +/*
>> + * Listener to provider informations to mod_heartbeat.c
>> + * *msg_format = "v=%u&ready=%u&busy=%u"; (message to send).
>> + * send the muticast merssage using the format...
>> + * what about the bind(IP. port) only IP makes sense (for the moment).
>> + * BTW:v  = version :-)
>> + */
>> +public class HeartbeatListener
>> +    implements LifecycleListener, ContainerListener {
>> +
>> +    public static Log log = LogFactory.getLog(HeartbeatListener.class);
> 
> public?

fixed.

> 
>> +
>> +    /* To allow to select the connector */
>> +    int port = 0;
>> +    String host = null;
>> +    public void setHost(String host) { this.host = host; }
>> +    public void setPort(int port) { this.port = port; }
> 
> Will we need getters as well?

Probably :-)

> 
>> +
>> +    /* for multicasting stuff */
>> +    MulticastSocket s = null;
>> +    InetAddress group = null;
>> +    String ip = "224.0.1.105"; /* Multicast IP */
>> +    int multiport = 23364;     /* Multicast Port */
> 
> I assume those two will be configurable in a future version ...

? They are already setGroup() and setPort().

> 
>> +
>> +    public void setGroup(String ip) { this.ip = ip; }
>> +    public void setMultiport(int multiport) { this.multiport = multiport; }
>> +
>> +    private CollectedInfo coll = null;
>> +
>> +    public void containerEvent(ContainerEvent event) {
>> +    }
>> +
>> +    public void lifecycleEvent(LifecycleEvent event) {
>> +        Object source = event.getLifecycle();
>> +        if (Lifecycle.PERIODIC_EVENT.equals(event.getType())) {
>> +            if (s == null) {
>> +                try {
>> +                    group = InetAddress.getByName(ip);
>> +                    s = new MulticastSocket(port);
>> +                    s.setTimeToLive(16);
> 
> Use a constant instead of "16"?

I have added a get/set for Ttl.

> 
>> +                    s.joinGroup(group);
>> +                } catch (Exception ex) {
>> +                    log.error("Unable to use multicast: " + ex);
>> +                    s = null;
>> +                    return;
>> +                } 
>> +            }
>> +// * *msg_format = "v=%u&ready=%u&busy=%u"; (message to send).
>> +// v = version (1)
>> +// ready & ready are read from the scoreboard in httpd.
>> +// Endpoint ( getCurrentThreadsBusy ) ( getMaxThreads )
> 
> What's the use of these comments?

Oops.

> 
>> +            if (coll == null) {
>> +                try {
>> +                    coll = new CollectedInfo(host, port);
>> +                } catch (Exception ex) {
>> +                    log.error("Unable to initialize info collection: " + ex);
>> +                    coll = null;
>> +                    return;
>> +                } 
>> +            }
>> +            try {
>> +                coll.refresh();
>> +            } catch (Exception ex) {
>> +                log.error("Unable to collect load information: " + ex);
>> +                coll = null;
>> +                return;
>> +            }
>> +            String output = new String();
>> +            output = "v=1&ready=" + coll.ready + "&busy=" + coll.busy;
> 
> You might want to use string constants for the param names.
> 
>> +            byte[] buf;
>> +            try {
>> +                buf = output.getBytes("US-ASCII");
>> +            } catch (UnsupportedEncodingException ex) {
>> +                buf = output.getBytes();
>> +            }
>> +            DatagramPacket data = new DatagramPacket(buf, buf.length, group, multiport);
>> +            try {
>> +                s.send(data);
>> +            } catch (Exception ex) {
>> +                log.error("Unable to send colllected load information: " + ex);
>> +                System.out.println(ex);
> 
> Please no System.out.println(). Left over from debugging ;)

Oops.

Cheers

Jean-Frederic

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org