You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by dk...@apache.org on 2015/03/19 22:39:27 UTC

[2/2] cxf git commit: Start stubbing in a throttling feature and a sample for it. Lots more work to go.

Start stubbing in a throttling feature and a sample for it.  Lots more work to go.


Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/3a080015
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/3a080015
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/3a080015

Branch: refs/heads/master
Commit: 3a080015474d27075b0b03aa9ec74ab443504ebd
Parents: 015419b
Author: Daniel Kulp <dk...@apache.org>
Authored: Thu Mar 19 17:38:45 2015 -0400
Committer: Daniel Kulp <dk...@apache.org>
Committed: Thu Mar 19 17:38:45 2015 -0400

----------------------------------------------------------------------
 distribution/src/main/release/samples/pom.xml   |   1 +
 .../main/release/samples/throttling/README.txt  |  24 +++
 .../src/main/release/samples/throttling/pom.xml | 158 +++++++++++++++++++
 .../throttling/src/main/config/hello_world.wsdl |  73 +++++++++
 .../java/demo/throttling/client/Client.java     | 113 +++++++++++++
 .../java/demo/throttling/server/Customer.java   | 110 +++++++++++++
 .../server/CustomerMetricsInterceptor.java      |  71 +++++++++
 .../demo/throttling/server/GreeterImpl.java     |  33 ++++
 .../java/demo/throttling/server/Server.java     |  82 ++++++++++
 rt/features/throttling/pom.xml                  |  46 ++++++
 .../cxf/throttling/ThrottlingInterceptor.java   |  62 ++++++++
 .../cxf/throttling/ThrottlingManager.java       |  35 ++++
 .../codahale/CodahaleMetricsContext.java        |  40 +++++
 rt/pom.xml                                      |   1 +
 14 files changed, 849 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/3a080015/distribution/src/main/release/samples/pom.xml
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/pom.xml b/distribution/src/main/release/samples/pom.xml
index 82d6bf4..ff09a4f 100644
--- a/distribution/src/main/release/samples/pom.xml
+++ b/distribution/src/main/release/samples/pom.xml
@@ -102,6 +102,7 @@
         <module>jax_rs/minimal_osgi</module>
         <module>ws_discovery</module>
         <module>ws_eventing</module>
+        <module>throttling</module>
     </modules>
     <dependencyManagement>
         <dependencies>

http://git-wip-us.apache.org/repos/asf/cxf/blob/3a080015/distribution/src/main/release/samples/throttling/README.txt
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/throttling/README.txt b/distribution/src/main/release/samples/throttling/README.txt
new file mode 100644
index 0000000..5468659
--- /dev/null
+++ b/distribution/src/main/release/samples/throttling/README.txt
@@ -0,0 +1,24 @@
+Throttling Hello World Demo
+=============================================
+This demo provides a "hello world" example of making SOAP calls.
+
+Please review the README in the samples directory before continuing.
+
+Building and running the demo using Maven
+-----------------------------------------
+From the base directory of this sample (i.e., where this README file is
+located), the Maven pom.xml file can be used to build and run the demo. 
+
+  mvn clean install (builds the demo)
+
+In the first terminal windows:
+  mvn -Pserver (starts the server)
+
+Sequentially, in the second terminal window:
+  mvn -Pclient
+
+Later, when desired:
+  mvn clean (removes all generated and compiled classes)
+
+
+

http://git-wip-us.apache.org/repos/asf/cxf/blob/3a080015/distribution/src/main/release/samples/throttling/pom.xml
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/throttling/pom.xml b/distribution/src/main/release/samples/throttling/pom.xml
new file mode 100644
index 0000000..c553c5f
--- /dev/null
+++ b/distribution/src/main/release/samples/throttling/pom.xml
@@ -0,0 +1,158 @@
+<?xml version="1.0"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements. See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership. The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License. You may obtain a copy of the License at
+ 
+  http://www.apache.org/licenses/LICENSE-2.0
+ 
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied. See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>throttling</artifactId>
+    <name>Demo using the throttling feature</name>
+    <description>Demo using the throttling feature</description>
+    <parent>
+        <groupId>org.apache.cxf.samples</groupId>
+        <artifactId>cxf-samples</artifactId>
+        <version>3.1.0-SNAPSHOT</version>
+    </parent>
+    <properties>
+        <wsdl.location>${basedir}/src/main/config/hello_world.wsdl</wsdl.location>
+    </properties>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.cxf</groupId>
+                <artifactId>cxf-codegen-plugin</artifactId>
+                <version>${project.version}</version>
+                <executions>
+                    <execution>
+                        <id>generate-sources</id>
+                        <phase>generate-sources</phase>
+                        <configuration>
+                            <wsdlOptions>
+                                <wsdlOption>
+                                    <faultSerialVersionUID>1</faultSerialVersionUID>
+                                    <wsdl>${wsdl.location}</wsdl>
+                                    <seiSuper>
+                                        <super>java.lang.AutoCloseable</super>
+                                        <super>javax.xml.ws.BindingProvider</super>
+                                    </seiSuper>
+                                </wsdlOption>
+                            </wsdlOptions>
+                        </configuration>
+                        <goals>
+                            <goal>wsdl2java</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+    <profiles>
+        <profile>
+            <id>server</id>
+            <build>
+                <defaultGoal>test</defaultGoal>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <phase>test</phase>
+                                <goals>
+                                    <goal>exec</goal>
+                                </goals>
+                                <configuration>
+                                    <executable>java</executable>
+                                    <arguments>
+                                        <argument>-classpath</argument>
+                                        <classpath />
+                                        <argument>demo.throttling.server.Server</argument>
+                                    </arguments>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>client</id>
+            <build>
+                <defaultGoal>integration-test</defaultGoal>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <phase>test</phase>
+                                <goals>
+                                    <goal>java</goal>
+                                </goals>
+                                <configuration>
+                                    <mainClass>demo.throttling.client.Client</mainClass>
+                                    <arguments>
+                                        <argument>${wsdl.location}</argument>
+                                    </arguments>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-frontend-jaxws</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-transports-http</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-transports-http-jetty</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-management</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-features-throttling</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>jcl-over-slf4j</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.dropwizard.metrics</groupId>
+            <artifactId>metrics-core</artifactId>
+        </dependency>
+    </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/cxf/blob/3a080015/distribution/src/main/release/samples/throttling/src/main/config/hello_world.wsdl
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/throttling/src/main/config/hello_world.wsdl b/distribution/src/main/release/samples/throttling/src/main/config/hello_world.wsdl
new file mode 100644
index 0000000..352986d
--- /dev/null
+++ b/distribution/src/main/release/samples/throttling/src/main/config/hello_world.wsdl
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements. See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership. The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License. You may obtain a copy of the License at
+ 
+  http://www.apache.org/licenses/LICENSE-2.0
+ 
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied. See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<wsdl:definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://apache.org/hello_world_soap_http" xmlns:x1="http://apache.org/hello_world_soap_http/types" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="HelloWorld" targetNamespace="http://apache.org/hello_world_soap_http">
+    <wsdl:types>
+        <schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://apache.org/hello_world_soap_http/types" targetNamespace="http://apache.org/hello_world_soap_http/types" elementFormDefault="qualified">
+            <simpleType name="MyStringType">
+                <restriction base="string">
+                    <maxLength value="30"/>
+                </restriction>
+            </simpleType>
+            <element name="greetMe">
+                <complexType>
+                    <sequence>
+                        <element name="requestType" type="tns:MyStringType"/>
+                    </sequence>
+                </complexType>
+            </element>
+            <element name="greetMeResponse">
+                <complexType>
+                    <sequence>
+                        <element name="responseType" type="string"/>
+                    </sequence>
+                </complexType>
+            </element>
+        </schema>
+    </wsdl:types>
+    <wsdl:message name="greetMeRequest">
+        <wsdl:part element="x1:greetMe" name="in"/>
+    </wsdl:message>
+    <wsdl:message name="greetMeResponse">
+        <wsdl:part element="x1:greetMeResponse" name="out"/>
+    </wsdl:message>
+    <wsdl:portType name="Greeter">
+        <wsdl:operation name="greetMe">
+            <wsdl:input message="tns:greetMeRequest" name="greetMeRequest"/>
+            <wsdl:output message="tns:greetMeResponse" name="greetMeResponse"/>
+        </wsdl:operation>
+    </wsdl:portType>
+    <wsdl:binding name="Greeter_SOAPBinding" type="tns:Greeter">
+        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+        <wsdl:operation name="greetMe">
+            <soap:operation soapAction="" style="document"/>
+            <wsdl:input name="greetMeRequest">
+                <soap:body use="literal"/>
+            </wsdl:input>
+            <wsdl:output name="greetMeResponse">
+                <soap:body use="literal"/>
+            </wsdl:output>
+        </wsdl:operation>
+    </wsdl:binding>
+    <wsdl:service name="SOAPService">
+        <wsdl:port binding="tns:Greeter_SOAPBinding" name="SoapPort">
+            <soap:address location="http://localhost:9001/SoapContext/SoapPort"/>
+        </wsdl:port>
+    </wsdl:service>
+</wsdl:definitions>

http://git-wip-us.apache.org/repos/asf/cxf/blob/3a080015/distribution/src/main/release/samples/throttling/src/main/java/demo/throttling/client/Client.java
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/throttling/src/main/java/demo/throttling/client/Client.java b/distribution/src/main/release/samples/throttling/src/main/java/demo/throttling/client/Client.java
new file mode 100644
index 0000000..7e191e7
--- /dev/null
+++ b/distribution/src/main/release/samples/throttling/src/main/java/demo/throttling/client/Client.java
@@ -0,0 +1,113 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package demo.throttling.client;
+
+import java.io.File;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.namespace.QName;
+import javax.xml.ws.BindingProvider;
+
+import org.apache.hello_world_soap_http.Greeter;
+import org.apache.hello_world_soap_http.SOAPService;
+
+public final class Client implements Runnable {
+
+    private static final QName SERVICE_NAME
+        = new QName("http://apache.org/hello_world_soap_http", "SOAPService");
+
+    private final String username;
+    private final SOAPService service;
+    private volatile boolean doStop;
+    private Client(String name, SOAPService service) {
+        this.username = name;
+        this.service = service;
+    }
+    
+    @Override
+    public void run() {
+        long start = System.currentTimeMillis();
+        try (Greeter port = service.getSoapPort()) {
+            port.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, username);
+            port.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "password");
+            int x = 0;
+            do {
+                if (doStop) {
+                    break;
+                }
+                port.greetMe(username + "-" + x);
+                x++;
+            } while (x < 10000);
+            long end = System.currentTimeMillis();
+            double rate = x * 1000 / (end - start);
+            System.out.println(username + " finished " + x + " invocations: " + rate + " req/sec");
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+    }
+    public void stop() {
+        doStop = true;
+    }
+    
+    public static void main(String args[]) throws Exception {
+        if (args.length == 0) {
+            System.out.println("please specify wsdl");
+            System.exit(1);
+        }
+
+        URL wsdlURL;
+        File wsdlFile = new File(args[0]);
+        if (wsdlFile.exists()) {
+            wsdlURL = wsdlFile.toURI().toURL();
+        } else {
+            wsdlURL = new URL(args[0]);
+        }
+
+        System.out.println(wsdlURL);
+        SOAPService ss = new SOAPService(wsdlURL, SERVICE_NAME);
+        List<Client> c = new ArrayList<Client>();
+        Client client = new Client("Tom", ss);
+        new Thread(client).start();
+        c.add(client);
+        client = new Client("Rob", ss);
+        new Thread(client).start();
+        c.add(client);
+        client = new Client("Vince", ss);
+        new Thread(client).start();
+        c.add(client);
+        client = new Client("Malcolm", ss);
+        new Thread(client).start();
+        c.add(client);
+        
+        System.out.println("Sleeping on main thread for 60 seconds");
+        Thread.sleep(60000);
+        for (Client c2 : c) {
+            c2.stop();
+        }
+        Thread.sleep(2000);
+
+        System.exit(0);
+    }
+
+    
+
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/3a080015/distribution/src/main/release/samples/throttling/src/main/java/demo/throttling/server/Customer.java
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/throttling/src/main/java/demo/throttling/server/Customer.java b/distribution/src/main/release/samples/throttling/src/main/java/demo/throttling/server/Customer.java
new file mode 100644
index 0000000..184468c
--- /dev/null
+++ b/distribution/src/main/release/samples/throttling/src/main/java/demo/throttling/server/Customer.java
@@ -0,0 +1,110 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package demo.throttling.server;
+
+import com.codahale.metrics.MetricRegistry;
+
+import org.apache.cxf.management.codahale.CodahaleMetricsContext;
+import org.apache.cxf.management.codahale.MetricsContext;
+import org.apache.cxf.message.Message;
+
+/**
+ * 
+ */
+public abstract class Customer {
+    protected final String name;
+    protected volatile CodahaleMetricsContext metrics;
+    
+    public Customer(String n) {
+        name = n;
+    }
+    
+    MetricsContext getMetricsContext(MetricRegistry registry) {
+        if (metrics == null) {
+            metrics = new CodahaleMetricsContext("Customer-" + name, registry);
+        }
+        return metrics;
+    }
+
+    public abstract long throttle(Message m);
+    
+    
+    public static class PremiumCustomer extends Customer {
+        public PremiumCustomer(String n) {
+            super(n);
+        }
+        public long throttle(Message m) {
+            //Premium customers are unthrottled
+            return 0;
+        }
+    }
+    public static class PreferredCustomer extends Customer {
+        public PreferredCustomer(String n) {
+            super(n);
+        }
+        public long throttle(Message m) {
+            //System.out.println("p  " + metrics.getTotals().getOneMinuteRate() + "  " + metrics.getTotals().getCount());
+            //Preferred customers are unthrottled until they hit 100req/sec, then start delaying by .05 seconds
+            //(drops to max of 50req/sec until below the 100req/sec rate)
+            if (metrics.getTotals().getOneMinuteRate() > 100) {
+                return 20;
+            }
+            return 0;
+        }
+    }
+    public static class RegularCustomer extends Customer {
+        public RegularCustomer(String n) {
+            super(n);
+        }
+        public long throttle(Message m) {
+            //Regular customers are unthrottled until they hit 25req/sec, then start delaying by 0.25 seconds 
+            //(drops to max of 4req/sec until below the 25req/sec rate)
+            if (metrics.getTotals().getOneMinuteRate() > 25) {
+                return 250;
+            }
+            //They also get throttled more if they are over 10req/sec over a 5 minute period  
+            //(drops to max of 2req/sec until below the 10req/sec rate)
+            if (metrics.getTotals().getFiveMinuteRate() > 10) {
+                return 500;
+            }
+            return 0;
+        }
+    }
+    public static class CheapCustomer extends Customer {
+        public CheapCustomer(String n) {
+            super(n);
+        }
+        public long throttle(Message m) {
+            //System.out.println("ch  " + metrics.getTotals().getOneMinuteRate() + "  " + metrics.getTotals().getCount());
+            //Cheap customers are always get a .1 sec delay
+            long delay = 100;
+            //Then they get futher throttled dependending on rates
+            if (metrics.getTotals().getOneMinuteRate() > 5) {
+                delay += 1000;
+            }
+            //They also get throttled after 5 minutes of more than 
+            if (metrics.getTotals().getFiveMinuteRate() > 1) {
+                delay += 1000;
+            }
+            return delay;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/3a080015/distribution/src/main/release/samples/throttling/src/main/java/demo/throttling/server/CustomerMetricsInterceptor.java
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/throttling/src/main/java/demo/throttling/server/CustomerMetricsInterceptor.java b/distribution/src/main/release/samples/throttling/src/main/java/demo/throttling/server/CustomerMetricsInterceptor.java
new file mode 100644
index 0000000..c84eaee
--- /dev/null
+++ b/distribution/src/main/release/samples/throttling/src/main/java/demo/throttling/server/CustomerMetricsInterceptor.java
@@ -0,0 +1,71 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package demo.throttling.server;
+
+import java.util.List;
+import java.util.Map;
+
+import com.codahale.metrics.MetricRegistry;
+
+import org.apache.cxf.common.util.Base64Exception;
+import org.apache.cxf.common.util.Base64Utility;
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.interceptor.Fault;
+import org.apache.cxf.management.codahale.MessageMetrics;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.AbstractPhaseInterceptor;
+import org.apache.cxf.phase.Phase;
+
+/**
+ * 
+ */
+public class CustomerMetricsInterceptor extends AbstractPhaseInterceptor<Message> {
+    MetricRegistry registry;
+    Map<String, Customer> customers;
+    public CustomerMetricsInterceptor(MetricRegistry reg, Map<String, Customer> c) {
+        super(Phase.PRE_STREAM);
+        registry = reg;
+        customers = c;
+    }
+
+    @Override
+    public void handleMessage(Message message) throws Fault {
+        MessageMetrics m = message.getExchange().get(MessageMetrics.class);
+        if (m != null) {
+            Map<String, List<String>> h = CastUtils.cast((Map<?,?>)message.get(Message.PROTOCOL_HEADERS));
+            String auth = h.get("Authorization").toString();
+            auth = auth.substring(auth.indexOf(' ') + 1);
+            try {
+                auth = new String(Base64Utility.decode(auth));
+            } catch (Base64Exception e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+            }
+            auth = auth.substring(0, auth.indexOf(':'));
+            Customer c = customers.get(auth);
+            if (c == null) {
+                throw new RuntimeException("Not authorized");
+            }
+            m.addContext(c.getMetricsContext(registry));
+            message.getExchange().put(Customer.class, c);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/3a080015/distribution/src/main/release/samples/throttling/src/main/java/demo/throttling/server/GreeterImpl.java
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/throttling/src/main/java/demo/throttling/server/GreeterImpl.java b/distribution/src/main/release/samples/throttling/src/main/java/demo/throttling/server/GreeterImpl.java
new file mode 100644
index 0000000..e8664ab
--- /dev/null
+++ b/distribution/src/main/release/samples/throttling/src/main/java/demo/throttling/server/GreeterImpl.java
@@ -0,0 +1,33 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package demo.throttling.server;
+
+
+@javax.jws.WebService(name = "Greeter", serviceName = "SOAPService", 
+                      targetNamespace = "http://apache.org/hello_world_soap_http", 
+                      wsdlLocation = "file:./src/main/config/hello_world.wsdl",
+                      endpointInterface = "org.apache.hello_world_soap_http.Greeter")
+                  
+public class GreeterImpl {
+
+    public String greetMe(String me) {
+        return "Hello " + me;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/3a080015/distribution/src/main/release/samples/throttling/src/main/java/demo/throttling/server/Server.java
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/throttling/src/main/java/demo/throttling/server/Server.java b/distribution/src/main/release/samples/throttling/src/main/java/demo/throttling/server/Server.java
new file mode 100644
index 0000000..bb01535
--- /dev/null
+++ b/distribution/src/main/release/samples/throttling/src/main/java/demo/throttling/server/Server.java
@@ -0,0 +1,82 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package demo.throttling.server;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.ws.Endpoint;
+
+import com.codahale.metrics.MetricRegistry;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.management.codahale.Metrics;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.Phase;
+import org.apache.cxf.throttling.ThrottlingInterceptor;
+import org.apache.cxf.throttling.ThrottlingManager;
+
+public class Server {
+    Map<String, Customer> customers = new HashMap<>();
+    
+    protected Server() throws Exception {
+        System.out.println("Starting Server");
+
+        customers.put("Tom", new Customer.PremiumCustomer("Tom"));
+        customers.put("Rob", new Customer.PreferredCustomer("Rob"));
+        customers.put("Vince", new Customer.RegularCustomer("Vince"));
+        customers.put("Malcolm", new Customer.CheapCustomer("Malcolm"));
+        
+        Bus b = BusFactory.getDefaultBus();
+        MetricRegistry registry = new MetricRegistry();
+        b.setExtension(registry, MetricRegistry.class);
+        new Metrics(b);
+        
+        
+        ThrottlingManager manager = new ThrottlingManager() {
+            @Override
+            public long getThrottleDelay(Message m) {
+                if (m.get("THROTTLED") != null) {
+                    return 0;
+                }
+                m.put("THROTTLED", true);
+                Customer c = m.getExchange().get(Customer.class);
+                return c.throttle(m);
+            }           
+        };
+        b.getInInterceptors().add(new CustomerMetricsInterceptor(registry, customers));
+        b.getInInterceptors().add(new ThrottlingInterceptor(Phase.PRE_STREAM, manager));
+        //add Throttling
+        
+        Object implementor = new GreeterImpl();
+        String address = "http://localhost:9001/SoapContext/SoapPort";
+        Endpoint.publish(address, implementor);
+    }
+
+    public static void main(String args[]) throws Exception {
+        new Server();
+        System.out.println("Server ready...");
+
+        Thread.sleep(5 * 60 * 1000);
+        System.out.println("Server exiting");
+        System.exit(0);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/3a080015/rt/features/throttling/pom.xml
----------------------------------------------------------------------
diff --git a/rt/features/throttling/pom.xml b/rt/features/throttling/pom.xml
new file mode 100644
index 0000000..1cf7d1c
--- /dev/null
+++ b/rt/features/throttling/pom.xml
@@ -0,0 +1,46 @@
+<project
+    xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.cxf</groupId>
+        <artifactId>cxf-parent</artifactId>
+        <version>3.1.0-SNAPSHOT</version>
+        <relativePath>../../../parent/pom.xml</relativePath>
+    </parent>
+    <artifactId>cxf-rt-features-throttling</artifactId>
+    <packaging>bundle</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.easymock</groupId>
+            <artifactId>easymock</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-frontend-jaxws</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-transports-http-jetty</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cxf/blob/3a080015/rt/features/throttling/src/main/java/org/apache/cxf/throttling/ThrottlingInterceptor.java
----------------------------------------------------------------------
diff --git a/rt/features/throttling/src/main/java/org/apache/cxf/throttling/ThrottlingInterceptor.java b/rt/features/throttling/src/main/java/org/apache/cxf/throttling/ThrottlingInterceptor.java
new file mode 100644
index 0000000..f35e144
--- /dev/null
+++ b/rt/features/throttling/src/main/java/org/apache/cxf/throttling/ThrottlingInterceptor.java
@@ -0,0 +1,62 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.throttling;
+
+import java.util.logging.Logger;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.continuations.Continuation;
+import org.apache.cxf.continuations.ContinuationProvider;
+import org.apache.cxf.interceptor.Fault;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.AbstractPhaseInterceptor;
+
+/**
+ * 
+ */
+public class ThrottlingInterceptor extends AbstractPhaseInterceptor<Message> {
+    public static final Logger LOG = LogUtils.getL7dLogger(ThrottlingInterceptor.class); 
+    
+    final ThrottlingManager manager;
+    public ThrottlingInterceptor(String phase, ThrottlingManager manager) {
+        super(ThrottlingInterceptor.class.getName() + "-" + phase, phase);
+        this.manager = manager;
+    }
+
+    @Override
+    public void handleMessage(Message message) throws Fault {
+        long l = manager.getThrottleDelay(message);
+        if (l > 0) {
+            ContinuationProvider cp = message.get(ContinuationProvider.class);
+            if (cp == null) {
+                LOG.warning("No ContinuationProvider available, sleeping on current thread");
+                try {
+                    Thread.sleep(l);
+                } catch (InterruptedException e) {
+                    //ignore
+                }
+                return;
+            }
+            Continuation c = cp.getContinuation();
+            c.suspend(l);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/3a080015/rt/features/throttling/src/main/java/org/apache/cxf/throttling/ThrottlingManager.java
----------------------------------------------------------------------
diff --git a/rt/features/throttling/src/main/java/org/apache/cxf/throttling/ThrottlingManager.java b/rt/features/throttling/src/main/java/org/apache/cxf/throttling/ThrottlingManager.java
new file mode 100644
index 0000000..ea7c841
--- /dev/null
+++ b/rt/features/throttling/src/main/java/org/apache/cxf/throttling/ThrottlingManager.java
@@ -0,0 +1,35 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.throttling;
+
+import org.apache.cxf.message.Message;
+
+/**
+ * 
+ */
+public interface ThrottlingManager {
+    
+    /**
+     * Returns the number of milliseconds the request should be delayed before further processing
+     * @param m
+     * @return
+     */
+    long getThrottleDelay(Message m);
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/3a080015/rt/management/src/main/java/org/apache/cxf/management/codahale/CodahaleMetricsContext.java
----------------------------------------------------------------------
diff --git a/rt/management/src/main/java/org/apache/cxf/management/codahale/CodahaleMetricsContext.java b/rt/management/src/main/java/org/apache/cxf/management/codahale/CodahaleMetricsContext.java
index 9c23d75..8c547b3 100644
--- a/rt/management/src/main/java/org/apache/cxf/management/codahale/CodahaleMetricsContext.java
+++ b/rt/management/src/main/java/org/apache/cxf/management/codahale/CodahaleMetricsContext.java
@@ -106,4 +106,44 @@ public class CodahaleMetricsContext implements MetricsContext, Closeable {
         inFlight.dec();
     }
 
+    public Counter getInFlight() {
+        return inFlight;
+    }
+
+    public Timer getTotals() {
+        return totals;
+    }
+
+    public Timer getUncheckedApplicationFaults() {
+        return uncheckedApplicationFaults;
+    }
+
+    public Timer getCheckedApplicationFaults() {
+        return checkedApplicationFaults;
+    }
+
+    public Timer getRuntimeFaults() {
+        return runtimeFaults;
+    }
+
+    public Timer getLogicalRuntimeFaults() {
+        return logicalRuntimeFaults;
+    }
+
+    public Meter getIncomingData() {
+        return incomingData;
+    }
+
+    public Meter getOutgoingData() {
+        return outgoingData;
+    }
+
+    public String getBaseName() {
+        return baseName;
+    }
+
+    public MetricRegistry getRegistry() {
+        return registry;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/3a080015/rt/pom.xml
----------------------------------------------------------------------
diff --git a/rt/pom.xml b/rt/pom.xml
index c2f5c70..7e8555e 100644
--- a/rt/pom.xml
+++ b/rt/pom.xml
@@ -40,6 +40,7 @@
         <module>bindings</module>
         <module>features/clustering</module>
         <module>features/logging</module>
+        <module>features/throttling</module>
         <module>frontend/simple</module>
         <module>frontend/jaxws</module>
         <module>frontend/jaxrs</module>