Dubbox注解开发详细教程
问题描述:
1,dubbox开发环境是如何搭建的?
2,dubbox 注解开发使用如何使用的?
3,dubbox注解开发之服务超时?
4,dubbox 注解开发之集群失败重试?
5,dubbox注解之高效序列化?
6,dubbox 注解开发之集群负载均衡?
dubbx是当当网对原阿里dubbo2.x的升级,并且兼容原有的dubbox。其中升级了zookeeper和spring版本,并且支持restfull风格的远程调用。
dubbox git地址: https://github.com/dangdangdotcom/dubbox
下载完毕dubbox源码以后,需要在项目中引入dubbox相关的包文件,此时需要把源码进行编译打包部署到仓库中.
运行maven命令:mvn clean install -Dmaven.test.skip=true
将dubbox的源码打包发布到本地仓库,目的是为了获取:
dubbo-admin-2.8.4.war和dubbo-monitor.war以及相关的dubbox依赖jar包.
下面的坐标依赖仅仅是项目kryo,jackson序列化优化所需的坐标,项目需要依赖的spring,dubbox集群负载及其他的坐标,自行导入即可.
<dependency>
<groupId>com.alibabagroupId>
<artifactId>dubboartifactId>
<version>2.8.4version>
<exclusions>
<exclusion>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>org.apache.zookeepergroupId>
<artifactId>zookeeperartifactId>
<version>3.4.7version>
dependency>
<dependency>
<groupId>com.github.sgroschupfgroupId>
<artifactId>zkclientartifactId>
<version>0.1version>
dependency>
<dependency>
<groupId>com.esotericsoftware.kryogroupId>
<artifactId>kryoartifactId>
<version>2.24.0version>
dependency>
<dependency>
<groupId>de.javakaffeegroupId>
<artifactId>kryo-serializersartifactId>
<version>0.42version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-databindartifactId>
<version>2.4.2version>
dependency>
<dependency>
<groupId>org.jboss.resteasygroupId>
<artifactId>resteasy-clientartifactId>
<version> 3.0.7.Finalversion>
dependency>
<dependency>
<groupId>com.googlecode.xmemcachedgroupId>
<artifactId>xmemcachedartifactId>
<version>2.4.0version>
dependency>
<dependency>
<groupId>com.cauchogroupId>
<artifactId>hessianartifactId>
<version>4.0.33version>
dependency>
<dependency>
<groupId>org.apache.cxfgroupId>
<artifactId>cxf-rt-coreartifactId>
<version>2.6.1version>
dependency>
项目发布服务使用批量扫描的方式进行服务器注册.
服务消息者也使用批量扫描的方法,引入服务对象.
dubbox在发布服务和消费服务和dubbo并没有什么本质的变化,但是主要是在一些细节方面有些小的变化,下面在dubbox优化方面来说明他的变化。
Service服务提供者,web层服务消费者.interface是发布服务及依赖服务的关键.
测试前提是你的linux中zookeeper服务器已经安装成功,此时测试使用的zookeeper注册中心模式来注册服务对象.
使用dubbox提供的注解开发结合配置文件dubbox扫描配置,把service服务对象发布到zookeeper注册中心即可.dubbox通过Service注解即可实现服务注册,但是必须注意service直接必须使用dubbox提供的注解.
importcom.alibaba.dubbo.config.annotation.Service;
@Service
public class DemoServiceImpl implements DemoService {
public String findAll(){
String str = "welcome to me!";
return str;
}
}
服务表现层消费者使用@Reference这个注解来直接引用服务层服务,此注解由dubbox提供.
importorg.springframework.stereotype.Controller;
importorg.springframework.web.bind.annotation.PathVariable;
importorg.springframework.web.bind.annotation.RequestMapping;
importorg.springframework.web.bind.annotation.ResponseBody;
import cn.it.DemoService;
importcom.alibaba.dubbo.config.annotation.Reference;
@Controller
public class DemoController {
@Reference//引入服务
private DemoServicedemoService;
@RequestMapping("/demo/rest/{name}")
@ResponseBody
public String rest(@PathVariable String name){
String str = demoService.findAll();
return str+":"+name;
}
}
为了更好了解dubbox做了什么优化,及dubbox在项目应用中我们需要做什么优化,提高项目的性能,因此做了一下的测试.
· 两台独立服务器
· 4核Intel(R) Xeon(R) CPU E5-2603 0 @1.80GHz
· 8G内存
· 服务器之间网络通过百兆交换机
· CentOS5
· JDK7
· Tomcat7
· JVM参数-server -Xms1g -Xmx1g -XX:PermSize=64M-XX:+UseConcMarkSweepGC
和dubbo自身的基准测试保持接近:
10个并发客户端持续不断发出请求:
· 传入嵌套复杂对象(但单个数据量很小),不做任何处理,原样返回
· 传入50K字符串,不做任何处理,原样返回(TODO:结果尚未列出)
进行5分钟性能测试。(引用dubbo自身测试的考虑:“主要考察序列化和网络IO的性能,因此服务端无任何业务逻辑。取10并发是考虑到http协议在高并发下对CPU的使用率较高可能会先打到瓶颈。”)
下面的结果主要对比的是REST和dubbo RPC两种远程调用方式,并对它们作不同的配置,例如:
· “REST: Jetty+XML+GZIP”的意思是:测试REST,并采用jetty server,XML数据格式,启用GZIP压缩。
· “Dubbo: hessian2”的意思是:测试dubbo RPC,并采用hessian2序列化方式。
针对复杂对象的结果如下(响应时间越小越好,TPS越大越好):
远程调用方式 |
平均响应时间 |
平均TPS(每秒事务数) |
REST: Jetty + JSON |
7.806 |
1280 |
REST: Jetty + JSON + GZIP |
TODO |
TODO |
REST: Jetty + XML |
TODO |
TODO |
REST: Jetty + XML + GZIP |
TODO |
TODO |
REST: Tomcat + JSON |
2.082 |
4796 |
REST: Netty + JSON |
2.182 |
4576 |
Dubbo: FST |
1.211 |
8244 |
Dubbo: kyro |
1.182 |
8444 |
Dubbo: dubbo serialization |
1.43 |
6982 |
Dubbo: hessian2 |
1.49 |
6701 |
Dubbo: fastjson |
1.572 |
6352 |
仅就目前的结果,一点简单总结:
1)dubbo RPC(特别是基于高效java序列化方式如kryo,fst)比REST的响应时间和吞吐量都有较显著优势,内网的dubbo系统之间优先选择dubbo RPC。
2)在 REST的实现选择上,仅就性能而言,目前tomcat7和netty最优(当然目前使用的jetty和netty版本都较低)。tjws和sunhttp server在性能测试中表现极差,平均响应时间超过200ms,平均tps只有50左右(为了避免影响图片效果,没在上面列出)。
3)在REST中JSON数据格式性能优于XML(数据暂未在以上列出)。
4)在REST中启用GZIP对企业内网中的小数据量复杂对象帮助不大,性能反而有下降(数据暂未在以上列出)。
根据以上测试结果,对dubbox发布服务以及消费服务做出以下优化。
平均响应时间:
服务超时主要是指服务消费者给服务提供者发送请求,服务提供者迟迟没有回应,超过表现层预期访问的时间,那么表现层服务任务服务超时,就会抛出异常错误.
那么为了防止过快的服务超时,保持一个长连接,因此需要修改超时设置.
@Controller
public class DemoController {
@Reference(timeout=100000) //超时时间为100000ms
private DemoServicedemoService;
@RequestMapping("/demo/rest/{name}")
@ResponseBody
public String rest(@PathVariable String name){
String str = demoService.findAll();
return str+":"+name;
}
}
服务失败自动切换,当出现失败,重试其它服务器 。通常用于读操作,但重试会带来更长延迟
可通过 retries="2" 来设置重试次数
表现层设置服务重试
@Controller
public class DemoController {
@Reference(timeout=100000,retries=2)//对所有的service方法都起作用
private DemoServicedemoService;
@RequestMapping("/demo/rest/{name}")
@ResponseBody
public String rest(@PathVariable String name){
String str = demoService.findAll();
return str+":"+name;
}}
服务层设置失败重试:
@Service(retries=2)
public class DemoServiceImpl implements DemoService {
public String findAll(){
String str = "welcome to me!";
return str;
}
}
从上面性能测试即可看出,dubbox序列化有多种方式,其中kryo序列化是最高效的一种序列化方式.
<dubbo:applicationname="demo-service"/>
<dubbo:protocolname="dubbo"serialization="kryo"port="20880"/>
<dubbo:registryaddress="zookeeper://192.168.66.66:2181"/>
<dubbo:annotationpackage="cn.it"/>
必须注意,以上kryo序列化必须在相关坐标依赖的情况下才能进行正确的执行.
<dubbo:applicationname="demo-service"/>
<dubbo:protocolname="dubbo"serialization="jackson"port="20880"/>
<dubbo:registryaddress="zookeeper://192.168.66.66:2181"/>
<dubbo:annotationpackage="cn.it"/>
因此我们发现dubbox高效率的序列化实现非常简单,只需要在dubboprotocol中配置serialization即可实现.
Dubbox实现集群配置,必须导入dubbox集群坐标
<dependency>
<groupId>com.alibabagroupId>
<artifactId>dubbo-clusterartifactId>
<version>2.8.4version>
dependency>
准备3台tomcat服务器,一台表现层服务器,2台服务层服务器,提供负载均衡测试
配置tomcat服务器权限,使用tomcat热部署,必须先配置tomcat权限:
权限配置完毕后,启动所有的tomcat服务器.
配置服务tomcat插件热部署地址.
<plugin>
<groupId>org.apache.tomcat.mavengroupId>
<artifactId>tomcat7-maven-pluginartifactId>
<configuration>
<port>8080port>
<path>/path>
<url>http://192.168.66.66:9001/manager/texturl>
<username>tomcatusername>
<password>tomcatpassword>
configuration>
plugin>
执行tomcat插件命令即可实现把项目部署到tomcat服务器ROOT目录下:
命令:tomcat:redeploy
在集群负载均衡时,Dubbo 提供了多种均衡策略,缺省为 random 随机调用
l Random LoadBalance
Ø 随机,按权重设置随机概率。
Ø 在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较
均匀,有利于动态调整提供者权重。
Ø 配置案例
@Service(loadbalance="random",retries=2)//此配置为默认负载策略,可以不配置
public class DemoServiceImpl implements DemoService {
public String findAll(){
String str = "welcome to me!";
return str;
}
}
l RoundRobin LoadBalance
Ø 轮循,按公约后的权重设置轮循比率。
Ø 存在慢的提供者累积请求的问题,比如:第二台机器很慢,但没挂,当请求调到第二台
时就卡在那,久而久之,所有请求都卡在调到第二台上。
Ø 配置案例:
@Service(loadbalance="roundrobin",retries=2)
public class DemoServiceImpl implements DemoService {
public String findAll(){
String str = "welcome to me!";
return str;
}
}
l LeastActive LoadBalance
Ø 最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。
Ø 使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。
Ø 配置案例:
@Service(loadbalance="leastactive",retries=2)
public class DemoServiceImpl implements DemoService {
public String findAll(){
String str = "welcome to me!";
return str;
}
}
l ConsistentHash LoadBalance
Ø 一致性 Hash,相同参数的请求总是发到同一提供者。
Ø 当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,
不会引起剧烈变动。
Ø 配置案例:
@Service(loadbalance="consistenthash",retries=2)
public class DemoServiceImpl implements DemoService {
public String findAll(){
String str = "welcome to me!";
return str;
}
}