[置顶] DUBBO-Lite 简化的DUBBO框架与高性能升级,以及完美的Spring集成能力

dubbo-lite

Dubbo 高性能升级版本,简单,高效

基于DUBBO 2.5.3构造

Github:https://github.com/xyp260466/dubbo-lite

主要升级及改动变化

1、去除所有坑余代码及不必要的扩展
2、分为 dubbo-common 与 dubbo-rpc两大主要模块
3、NIO网络传输层升级为Apache Mina(保留dubbo原始mina版本)
4、代理生成采用 dubbo-2.5.3原生 Javassist框架
5、序列化采用高性能框架 Protostuff-1.3.3 (相比hession提升90%,秒杀java-built-in)
6、保留部分核心
7、相比dubbo原始框架,代码结构清晰,有助于阅读及参考
8、欢迎积极扩展!

Protostuff Decoder & Encoder:

/* * Dubbo Mina Decoder Use Protostuff * * */
package com.alibaba.dubbo.rpc.codec;

import com.alibaba.dubbo.rpc.remoting.Request;
import com.alibaba.dubbo.rpc.remoting.Response;
import io.protostuff.ProtostuffIOUtil;
import io.protostuff.Schema;
import io.protostuff.runtime.RuntimeSchema;
import org.apache.mina.common.ByteBuffer;
import org.apache.mina.common.IoSession;
import org.apache.mina.filter.codec.ProtocolDecoderAdapter;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;

public class ProtostuffDubboDecoder extends ProtocolDecoderAdapter {

    public void decode(IoSession session, ByteBuffer in, ProtocolDecoderOutput out) throws Exception {
        InputStream stream = in.asInputStream();
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        byte b = (byte)stream.read();
        int bf;
        while((bf = stream.read()) != -1){
            os.write(bf);
        }
        byte[] protoStuff = os.toByteArray();
        if(b == 0x00){
            Schema<Request> schema = RuntimeSchema
                    .getSchema(Request.class);
            Request request = new Request();
            ProtostuffIOUtil.mergeFrom(protoStuff, request, schema);
            out.write(request);

        }else if(b == 0x01){
            Schema<Response> schema = RuntimeSchema
                    .getSchema(Response.class);
            Response response = new Response();
            ProtostuffIOUtil.mergeFrom(protoStuff, response, schema);
            out.write(response);
        }else{
            throw new IllegalStateException("Cannot Support Read Type: "+b);
        }

    }

}
/* * Dubbo Mina Encoder Use Protostuff * * * */
package com.alibaba.dubbo.rpc.codec;

import com.alibaba.dubbo.rpc.remoting.Request;
import com.alibaba.dubbo.rpc.remoting.Response;
import io.protostuff.LinkedBuffer;
import io.protostuff.ProtostuffIOUtil;
import io.protostuff.Schema;
import io.protostuff.runtime.RuntimeSchema;
import org.apache.mina.common.ByteBuffer;
import org.apache.mina.common.IoSession;
import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
import org.apache.mina.filter.codec.ProtocolEncoderOutput;

public class ProtostuffDubboEncoder extends ProtocolEncoderAdapter {

    /** * encode * * @param session * @param message * @param out * @throws Exception */
    public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
        ByteBuffer byteBuffer = ByteBuffer.allocate(4096);
        byteBuffer.setAutoExpand(true);
        if(message instanceof Request){
            byteBuffer.put((byte)0x00);
            Schema<Request> schema = RuntimeSchema
                    .getSchema(Request.class);
            LinkedBuffer buffer = LinkedBuffer.allocate(1024);
            byte[] protoStuff = ProtostuffIOUtil.toByteArray((Request)message, schema, buffer);
            byteBuffer.put(protoStuff);
        }else if(message instanceof Response){
            byteBuffer.put((byte)0x01);
            Schema<Response> schema = RuntimeSchema
                    .getSchema(Response.class);
            LinkedBuffer buffer = LinkedBuffer.allocate(4096);
            byte[] protoStuff = ProtostuffIOUtil.toByteArray((Response)message, schema, buffer);
            byteBuffer.put(protoStuff);
        }else{
            throw new IllegalStateException("Cannot Support Class Type: "+message.getClass().getName());
        }
        byteBuffer.flip();
        out.write(byteBuffer);
    }
}

使用非常简单:

发布服务:

//initialize a protocol
Protocol protocol = DubboProtocol.getProtocol();

//export a service
protocol.export(new SimpleImpl(), Simple.class, 2880);

消费服务:

//initialize a protocol
Protocol protocol = DubboProtocol.getProtocol();

Simple invoker = protocol.refer(Simple.class, "127.0.0.1", 2880, 3600);

强大的与Spring基于注解的自动集成能力:

现在你会感觉Spring集成将会变的非常简单

在Spring配置文件中加入如下内容:

<dubbo:annotation-driven base-package="com"/>

系统将会自动将扫描到的Bean加入Spring容器并发布Dubbo服务,非常方便
Spring配置文件范例:

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.xyp260466.com/schema/dubbo" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.xyp260466.com/schema/dubbo META-INF/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> 

<context:component-scan base-package="com.xyp260466.dubbo.test.provider"/> 

<dubbo:annotation-driven base-package="com.xyp260466.dubbo.test.provider"/> 

</beans> 

消费服务:加上@Consumer注解

@Consumer
private SimpleProvider simpleProvider;

发布服务:加上@Provider注解

@Provider
public class SimpleProviderImpl implements SimpleProvider 

dubbo.xsd文件:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns="http://code.xyp260466.com/schema/dubbo" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://code.xyp260466.com/schema/dubbo">

    <xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
    <xsd:import namespace="http://www.springframework.org/schema/beans"/>
    <xsd:import namespace="http://www.springframework.org/schema/tool"/>

    <xsd:annotation>
        <xsd:documentation><![CDATA[ Namespace support for the dubbo services provided by dubbo framework. ]]></xsd:documentation>
    </xsd:annotation>


    <xsd:element name="annotation-driven">
        <xsd:annotation>
            <xsd:documentation><![CDATA[ Scans the classpath for annotated components that will be auto-registered as Spring beans. By default, the Dubbo-provided @Provider, @Interface, @Consumer stereotypes will be detected. ]]></xsd:documentation>
        </xsd:annotation>
        <xsd:complexType>
            <xsd:attribute name="base-package" type="xsd:string" use="required">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[ The comma-separated list of packages to scan for annotated components. ]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
        </xsd:complexType>
    </xsd:element>

</xsd:schema>

基于注解的Spring3.0集成实现部分:

package com.xyp260466.dubbo.schema;
import com.alibaba.dubbo.common.utils.ReflectUtils;
import com.xyp260466.dubbo.annotation.Provider;
import com.xyp260466.dubbo.annotation.Interface;
import com.xyp260466.dubbo.beans.ProviderBean;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.beans.factory.xml.XmlReaderContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.context.annotation.ComponentScanBeanDefinitionParser;
import org.springframework.context.annotation.DubboClassPathBeanDefinitionScanner;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;

import java.util.Map;
import java.util.Set;

/** * Created by xyp on 16-5-9. */
public class AutoBeanDefinitionParser extends ComponentScanBeanDefinitionParser {

    private static final String BASE_PACKAGE_ATTRIBUTE = "base-package";

    private static final Logger logger = Logger.getLogger(AutoBeanDefinitionParser.class);

    public BeanDefinition parse(Element element, ParserContext parserContext) {

        logger.info("Parse Dubbo Services.");

        String[] basePackages = StringUtils.tokenizeToStringArray(element.getAttribute(BASE_PACKAGE_ATTRIBUTE),
                ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);

        Assert.notEmpty(basePackages, "At least one base package must be specified");

        DubboClassPathBeanDefinitionScanner scanner = new DubboClassPathBeanDefinitionScanner(parserContext);

        Set<BeanDefinitionHolder> beanDefinitions = scanner.scanComplete(basePackages);

        registerComponents(parserContext.getReaderContext(), beanDefinitions, element);

        for(BeanDefinitionHolder holder : beanDefinitions){

            RootBeanDefinition beanDefinition = new RootBeanDefinition();
            beanDefinition.setBeanClass(ProviderBean.class);
            beanDefinition.setLazyInit(false);

            ScannedGenericBeanDefinition srcDefinition = (ScannedGenericBeanDefinition) holder.getBeanDefinition();
            //process
            RootBeanDefinition classDefinition = new RootBeanDefinition();

            String beanClass = srcDefinition.getBeanClassName();

            classDefinition.setBeanClass(ReflectUtils.forName(beanClass));
            classDefinition.setLazyInit(false);

            beanDefinition.setBeanClassName(ProviderBean.class.getName());

            AnnotationMetadata metadata = srcDefinition.getMetadata();

            Map<String, Object> attributes = metadata.getAnnotationAttributes(Provider.class.getName());

            String[] interfaces = metadata.getInterfaceNames();

            if(interfaces.length == 0){
                throw new IllegalStateException("Class [ "+beanClass+" ] No Interfaces Detected!");
            }else {
                String interfaceTarget = null;
                if(interfaces.length > 1){
                    for(String interfaceStr : interfaces){
                        Class clazz = ReflectUtils.forName(interfaceStr);
                        if(clazz.isAnnotationPresent(Interface.class)){
                            interfaceTarget = interfaceStr;
                        }
                    }
                }else{
                    interfaceTarget = interfaces[0];
                }
                if(interfaceTarget == null){
                    throw new IllegalStateException("Class [ "+beanClass+" ] Cannot Find suitable Interface!");
                }else {
                    String id = interfaceTarget;
                    int counter = 2;
                    while(parserContext.getRegistry().containsBeanDefinition(id)) {
                        id = interfaceTarget + (counter ++);
                    }
                    if (parserContext.getRegistry().containsBeanDefinition(id))  {
                        throw new IllegalStateException("Duplicate spring bean id " + id);
                    }
                    parserContext.getRegistry().registerBeanDefinition(id, beanDefinition);
                    beanDefinition.getPropertyValues().addPropertyValue("id", id);
                    beanDefinition.getPropertyValues().addPropertyValue("interfaceClass", interfaceTarget);

                    String refId = interfaceTarget;
                    if (attributes.size() > 0 && attributes.get("value") != null) {
                        refId = attributes.get("value").toString();
                    }
                    beanDefinition.getPropertyValues().addPropertyValue("ref", new BeanDefinitionHolder(classDefinition, refId));

                }
            }
        }
        return null;
    }

    protected void registerComponents(
            XmlReaderContext readerContext, Set<BeanDefinitionHolder> beanDefinitions, Element element) {

        Object source = readerContext.extractSource(element);
        CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), source);

        for (BeanDefinitionHolder beanDefHolder : beanDefinitions) {
            compositeDef.addNestedComponent(new BeanComponentDefinition(beanDefHolder));
        }

        // Register annotation config processors, if necessary.
        Set<BeanDefinitionHolder> processorDefinitions =
                AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source);
        for (BeanDefinitionHolder processorDefinition : processorDefinitions) {
            compositeDef.addNestedComponent(new BeanComponentDefinition(processorDefinition));
        }

        readerContext.fireComponentRegistered(compositeDef);
    }
}

Spring集成测试:

配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.xyp260466.com/schema/dubbo" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.xyp260466.com/schema/dubbo META-INF/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.xyp260466.dubbo.test.provider"/>

    <dubbo:annotation-driven base-package="com.xyp260466"/>

</beans>

启动Spring容器:

package com.xyp260466.dubbo.test;
import org.apache.log4j.Logger;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/** * Created by xyp on 16-5-9. */
public class SpringTest {
    private static final Logger logger = Logger.getLogger(SpringTest.class);

    public static void main(String[] args) {
        new Thread(new Runnable() {
            public void run() {
                while (true){
                    try {
                        Thread.sleep(1000);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }

            }
        }).start();
        logger.info("spring container starting...");

        new ClassPathXmlApplicationContext("spring-provider.xml");
    }


}

测试客户端:

package com.xyp260466.dubbo.test;

import com.alibaba.dubbo.rpc.protocol.DubboProtocol;
import com.xyp260466.dubbo.test.provider.SimpleProvider;
import org.apache.log4j.Logger;

/** * Created by xyp on 16-5-10. */
public class CallSpringService {
    private static final Logger logger = Logger.getLogger(CallSpringService.class);

    public static void main(String[] args) {
        logger.info("Start Calling Spring Dubbo Service......");


        SimpleProvider simpleProvider = DubboProtocol.getProtocol().refer(SimpleProvider.class, "127.0.0.1", 20880);

        System.out.println("Spring Dubbo Service Result: "+simpleProvider.providerMethod("xiaoming"));




    }


}

你可能感兴趣的:(github,spring,框架,高性能)