1.Dubbo是什么?
Dubbo是一个分布式服务框架,致力于提供高性能和透明化的
RPC远程服务调用方案,以及SOA服务治理方案.
2.Dubbo能做什么?
1.透明化的远程方法调用,就像调用本地方法一样调用远程方法.
2.软负载均衡及容错机制。
3.服务自动注册与发现,不再需要写死服务提供方地址,注册中心基于接
口名查询服务提供者的IP地址,并且能够平滑添加或删除服务提供者
Dubbo对比HTTP
http好比普通话,rpc好比团伙内部黑话。
讲普通话,好处就是谁都听得懂,谁都会讲。
讲黑话,好处是可以更精简、更加保密、更加可定制,坏处就是要求“说”黑话的
那一方(client端)也要懂,而且一旦大家都说一种黑话了,换黑话就困难了。
所以为什么要用rpc调用?
因为良好的rpc调用是面向服务的封装,针对服务的可用性和效率等都做了优化。单
纯使用http调用则缺少了这些特性。
http可以过防火墙,可以利用各种丰富的分析工具。http是文本协议,适合短连接
。http跨网络,易扩展。
dubbo通讯层用的netty,直接走socket的,没用http,socket是二进制协议,安全性
更高,数据有效率更高。
Dubbo架构
Zookeeper
zookeeper用来注册服务和进行负载均衡,哪一个服务由哪一个机器
来提供必需让调用者知道,简单来说就是ip地址和服务名称的对应关
系。
当然也可以 通过硬编码的方式把这种对应关系在调用方业务代码中实
现,但是如果提供服务的机器挂掉调用者无法知晓,如果不更改代码
会继续请求挂掉的机器提供服务。
zookeeper通过心跳机制可以检测挂掉的机器并将挂掉机器的ip和服
务对应关系从列表中删除。至于支持高并发,简单来说就是横向扩展
,在不更改代码 的情况通过添加机器来提高运算能力。通过添加新的
机器向zookeeper注册服务,服务的提供者多了能服务的客户就多了
Dubbo的将注册中心进行抽象,是得它可以外接不同的存储媒介给注册中心提供服务,有
ZooKeeper,Memcached,Redis等。
引入了ZooKeeper作为存储媒介,也就把ZooKeeper的特性引进来。首先是负载均衡
,单注册中心的承载能力是有限的,在流量达到一定程度的时 候就需要分流,负载均衡
就是为了分流而存在的,一个ZooKeeper群配合相应的Web应用就可以很容易达到负载均
衡;资源同步,单单有负载均衡还不 够,节点之间的数据和资源需要同步,ZooKeeper
集群就天然具备有这样的功能;命名服务,将树状结构用于维护全局的服务地址列表,服
务提供者在启动 的时候,向ZK上的指定节点/dubbo/${serviceName}/providers目录下写
入自己的URL地址,这个操作就完成了服务的发布。
Dubbo调用方式
Ø 集成spring调用
Ø generic泛化调用
Ø telnet调用
Spring调用
第一步:引jar包
因为dubbo是基于java的Rpc调用,就像本地调用接口一样 ,所以提供dubbo一般会提供一个sdk client
mvn install:install-file -Dfile=client-1.0-SNAPSHOT.jar -
DgroupId=dubbotomcatnew -DartifactId=client -Dversion=1.0-
SNAPSHOT -Dpackaging=jar
不要放在中文路径和特殊字符的文件夹下面
因为这个包不在远程服务器 所以可以本地安装到仓库中
dubbotomcatnew
client
1.0-SNAPSHOT
与服务提供者确定好调用什么接口,以及版本和组
见注册中心存在的接口
地址:http://ip:端口号/dubbo/
第二步:定义xml
Reference id === spring 里面的id,所以用法是一样的
protocol="zookeeper" />
interface="com.longteng.service.DubboTestService"
group="longteng" version="1.0" timeout="5000"
url="dubbo://ip:端口号">
注意: url不是必须配置的,配置url的意思是调用到指定ip,
因为我们的服务部署在阿里云上面,
对外的ip和本机ip不一致,所以我们强制指定ip
Dubbo节点说明
Ø Provider: 暴露服务的服务提供方。
Ø Consumer: 调用远程服务的服务消费方。
Ø Registry: 服务注册与发现的注册中心。
Ø Monitor: 统计服务的调用次调和调用时间的监控中心。
Ø Container: 服务运行容器。
Dubbo配置信息含义
Ø Protocol 支持dubbo、rmi、hessian、http、thrift等协议
Ø Service 声明需要暴露的服务接口
Ø Interface 具体的接口类
Ø Version 接口的版本,这个如果服务定义、客户端也要定义
Ø Group 接口组合版本一样
Ø Ref 映射的实现类、spring的东西(用来给一个对象的属性设置值)
Ø Bean 一个实例
Ø Reference 客户端的代理调用
第三步:启动容器调用
@Test
public void test(){
ApplicationContext context=new ClassPathXmlApplicationContext("consumer.xml");
DubboTestService dubboTestService =(DubboTestService)
context.getBean("dubboTestService");
String s =dubboTestService.sayHello("你好");
System.out.println(s);
泛化调用
如果不引用依赖如何调用呢?
1.设置应用以及注册中心地址
@Test
public void generic(){
ApplicationConfig application = new ApplicationConfig();
application.setName("dubbo-consumer");
// 连接注册中心配置
RegistryConfig registry = new RegistryConfig();
registry.setAddress("zookeeper://ip:端口号");
设置接口信息以及获取到
url不是必须设置,因为阿里云的ip原因
GenericService是一个代理接口,用于代理请求的接口,他是未知的
//设置接口信息,和xml一样的
ReferenceConfig reference = new
ReferenceConfig();
reference.setApplication(application);
reference.setRegistry(registry);
reference.setInterface("com.longteng.service.UserService");
reference.setGeneric(true); // 声明为泛化接口
reference.setUrl("dubbo://ip:端口号");
reference.setGroup("longteng");
reference.setVersion("1.0");
//从缓存里面拿接口
ReferenceConfigCache cache = ReferenceConfigCache.getCache();
GenericService genericService = cache.get(reference);
设置参数,根据入参类型,传递的参数一般情况是json串,
然后根据类型转成对应的对象,map与object一致
//设置参数类型
List paramType =new ArrayList<>();
paramType.add("com.longteng.domain.User");
String[] strings = new String[paramType.size()];
paramType.toArray(strings);
//设置参数
Map map=new HashMap();
map.put("id",1);
List objectList =new ArrayList<>();
objectList.add(map);
Object[] objects =new Object[objectList.size()];
objectList.toArray(objects);
// 基本类型以及Date,List,Map等不需要转换,直接调用
Object result = genericService.$invoke("getUser",strings, objects);
Telnet
Ø telnet ip 端口号 链接到dubbo服务
命令列表:
Ø ls 显示服务列表。
Ø ls –l 显示服务详细信息列表。
Ø ls XxxService 显示服务的方法列表。
Ø ls -l XxxService 显示服务的方法详细信息列表。
Ø Invoke
Invoke XxxService.xxxMethod({"prop": "value"})
调用指定方法
调用服务接口
语法
invoke XxxService.xxxMethod({"prop": "value"})
调用服务的方法(自动查找包含此方法的服务)。
例子
invoke com.longteng.service.DubboTestService.sayHello("hi")
调用接口时,然后打印返回值和所用时间。
dubbo>invoke com.test.DemoService.queryDemoPageList({"id":"100"}, 1, 2)
{"totalCount":1,"data":[{date":"2011-03-23 14:10:32","name":"张三
","keyword":null}]}
Telnet代码调用
com.longteng.lesson2.util.TelnetSocket
见代码
@Test
public void telnet() throws Exception{
TelnetSocket telnetSocket=new TelnetSocket("ip",端口号);
String cmd ="invoke com.longteng.service.DubboTestService.sayHello(\"你好\")";
String s= telnetSocket.send(cmd);
System.out.println(s);
String json="{\"id\":1}";
telnetSocket=new TelnetSocket("ip",端口号);
telnetSocket.setReadEncoding("GBK");
cmd="invoke com.longteng.service.UserService.getUser("+json+")";
s=telnetSocket.send(cmd);
System.out.println(s);
}