Dubbo
Author: Lijb
Email: lijb1121@163.com
1.什么是Dubbo
dubbo:是一个基于soa思想的rpc框架
soa思想:面向服务的架构
给每一个模块暴露对应的ip和端口,当做一个服务进行运行
重点在于服务的管理(负载均衡,容灾模式,服务的横向扩展)
2.架构的演变
- dubbo的架构图
节点角色说明
节点 角色说明
Provider 暴露服务的服务提供方
Consumer 调用远程服务的服务消费方
Registry 服务注册与发现的注册中心
Monitor 统计服务的调用次数和调用时间的监控中心 Container 服务运行容器
调用关系说明
-
- 服务容器负责启动,加载,运⾏服务提供者。
-
- 服务提供者在启动时,向注册中心注册自己提供的服务。
-
- 服务消费者在启动时,向注册中⼼订阅自己所需的服务。
-
- 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
-
- 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
-
- 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监
4.Dubbo的入门案例
dubbo的开发方式
- dubbo+spring
- dubbo 原始API
- duibbo+spring注解式开发
引入Dubbo依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.5</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo-cluster</artifactId>
<version>2.6.5</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo-config-spring</artifactId>
<version>2.6.5</version>
</dependency>
<!-- curator-framework 连接zk-->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.7.1</version>
</dependency>
如果是2.6.2以前版本默认使用的zkclient连接zookeeper。
Dubbo+Spring配置文件版
- 启动zookeeper ./bin/zkServer.sh start zoo.cfg 启动 ./bin/zkCli.sh -server CentOS:2181 ls / --在zookeeper查看注册服务列表
服务提供者暴露服务
<?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://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://dubbo.apache.org/schema/dubbo
http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!--对服务起名字,一般要求服务名唯一-->
<dubbo:application name="usercenter-provider"/>
<!--连接zookeer,未来将服务注册到zk中-->
<dubbo:registry protocol="zookeeper" address="CentOS:2181"/>
<!--定制服务接受协议 启动netty-server -->
<dubbo:protocol name="dubbo" port="20880"/>
<!--暴露本地的bean服务-->
<dubbo:service interface="com.baizhi.service.IUserService" ref="userService" />
</beans>
-
开发服务提供者接口
publicinterface UserService { public String findName(String name); }
-
开发服务提供者实现类
public classUserServiceImpl implements UserService { public String findName(String name) { System.out.println("这是根据用户名: "+name+" 查询用户的业务..."); return name; } }
-
启动服务提供者
publicstatic void main(String[] args) throws IOException { ClassPathXmlApplicationContext context =new ClassPathXmlApplicationContext("spring-dubbo.xml"); System.in.read(); }
服务消费方
-
引入依赖同服务方依赖
-
将服务方的接口复制到消费方项目中
publicinterface UserService { public String findName(String name); }
注意: 包结构要与服务提供方严格一致
-
配置文件
<?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://dubbo.apache.org/schema/dubbo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd"> <!--对服务起名字,一般要求服务名唯一--> <dubbo:application name="usercenter-consumer"/> <!--连接zookeer,未来将服务注册到zk中--> <dubbo:registry protocol="zookeeper" address="CentOS:2181"/> <!--引用远程接口,在本地产生代理bean--> <dubbo:reference id="userService" interface="com.baizhi.service.IUserService" /> </beans>
-
调用服务方服务
publicstatic void main(String[] args) { ApplicationContext context = newClassPathXmlApplicationContext("spring-dubbo.xml"); UserService userService = (UserService)context.getBean("userService"); System.out.println(userService.findName("张三")); }
Dubbo+Spring注解版本
服务提供端配置
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.spring.context.annotation.DubboComponentScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
//扫描的是接口实现类,该类上一般会使用@Service注解(dubbo)
@DubboComponentScan(basePackages = {"com.baizhi.service.impl"})
public class Application_Provider {
/*
<dubbo:application name="usercenter-provider"/>
*/
[@Bean](https://my.oschina.net/bean)
public ApplicationConfig applicationConfig(){
ApplicationConfig applicationConfig = new ApplicationConfig();
applicationConfig.setName("usercenter-provider");
return applicationConfig;
}
/*
<dubbo:registry protocol="zookeeper" address="CentOS:2181"/>
* */
@Bean
public RegistryConfig registryConfig(){
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setAddress("CentOS:2181");
registryConfig.setProtocol("zookeeper");
registryConfig.setClient("curator");
return registryConfig;
}
/*
<dubbo:protocol name="dubbo" port="20880"/>
*/
@Bean
public ProtocolConfig protocolConfig(){
ProtocolConfig protocolConfig = new ProtocolConfig();
protocolConfig.setName("dubbo");
protocolConfig.setPort(20880);
return protocolConfig;
}
}
--
ApplicationContext ctx= new AnnotationConfigApplicationContext(Application_Provider.class);
服务消费端
@Configuration
//扫描的是接口,更具接口创建代理
@DubboComponentScan(basePackages = "com.baizhi.service")
public class Application_Consumer {
// <dubbo:reference id=“userService” interface=""/>
@Reference
private IUserService userService;
@Bean
public IUserService userService(){
return userService;
}
/*
<dubbo:application name="usercenter-consumer"/>
*/
@Bean
public ApplicationConfig applicationConfig(){
ApplicationConfig applicationConfig = new ApplicationConfig();
applicationConfig.setName("usercenter-consumer");
return applicationConfig;
}
/*
<dubbo:registry protocol="zookeeper" address="CentOS:2181"/>
* */
@Bean
public RegistryConfig registryConfig(){
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setAddress("CentOS:2181");
registryConfig.setProtocol("zookeeper");
registryConfig.setClient("curator");
return registryConfig;
}
}
---
ApplicationContext ctx= new AnnotationConfigApplicationContext(Application_Consumer.class);
Spring Boot 整合 Dubbo
-
pom.xml
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.17.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties>
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.47</version> </dependency> <dependency> <groupId>com.alibaba.boot</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>0.1.0</version> </dependency> <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.24.Final</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.7</version> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
</dependencies>
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
参考 http://start.dubbo.io/ 自动生成服务提供者和服务消费者
服务方代码
server.port= 8989
dubbo.application.name = dubbo-demo-server
# Base packages to scan Dubbo Component: @com.alibaba.dubbo.config.annotation.Service
dubbo.scan.basePackages = com.example
## RegistryConfig Bean
dubbo.registry.id = my-registry
dubbo.registry.address = CentOS:2181
dubbo.registry.client= curator
dubbo.registry.protocol= zookeeper
## Legacy QOS Config
dubbo.application.qosEnable=true
dubbo.application.qosPort= 22222
dubbo.application.qosAcceptForeignIp=false
-
入口代码
@SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
客户端代码
# Dubbo Config properties
## ApplicationConfig Bean
dubbo.application.name= dubbo-demo-client
## RegistryConfig Bean
dubbo.registry.id = my-registry
dubbo.registry.address = CentOS:2181
dubbo.registry.protocol= zookeeper
dubbo.registry.client = curator
dubbo.application.qosEnable=false
入口代码
@SpringBootApplication
public class DemoApplication {
@Reference
private HelloService demoService;
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@PostConstruct
public void init() {
String sayHello = demoService.sayHello("world");
System.err.println(sayHello);
}
}
- 配置覆盖关系
- 方法级优先,接口次之,全局配置再次之。
- 如果级别一样,则消费方优先,提供方次之。
- 其中服务提供方配置通过URL,经由注册中心传递给消费者。
如下:
<!--全局配置-->
<dubbo:provider timeout="6000"/>
<!--接口配置-->
<dubbo:service interface="com.baizhi.service.UserService" ref="userService" timeout="5000" >
<!--方法配置-->
<dubbo:method name="findName" timeout="4000"/>
</dubbo:service>
启动时检查
-
局部配置
<dubbo:reference interface="xx" check="false" />
-
全局配置
<dubbo:consumer check="false" />
Dubbo中集群的负载均衡
- 搭建服务提供者的集群
只需要将服务提供者代码,复制几份,修改一下的端口,全部启动即可(端口号不能冲突):
server1:<dubbo:protocol name="dubbo" port="20881"/>
server2:<dubbo:protocol name="dubbo" port="20882"/>
server3:<dubbo:protocol name="dubbo" port="20883"/>
-
启动所有的服务提供者集群
-
使用服务消费者进行调用
注意:默认dubbo使用负载均衡算法是random 随机的
-
常见的负载均衡算法
1.在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重 2.RoundRobin LoadBalance 轮循,按公约后的权重设置轮循比率 3.存在慢的提供者累积请求的问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上 4.LeastActive LoadBalance 最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。 5.使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。 6.ConsistentHash LoadBalance 一致性Hash,相同参数的请求总是发到同一提供者。 如果对应的hash值上没有服务提供者,按照就近原则顺时针找离该hash值最近的服务端。
算法参见:http://en.wikipedia.org/wiki/Consistent_hashing
<!--缺省只对第一个参数 Hash,如果要修改,请配置-->
<dubbo:parameterkey="hash.arguments" value="0,1" />
<!--缺省用160份虚拟节点,如果要修改,请配置-->
<dubbo:parameterkey="hash.nodes" value="320" />
<!--当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。-->
a.客户端设置集负载均衡策略
基于权重随机
<!--服务端,默认权重是100-->
<dubbo:service interface="..." weight="100" />
<!--客户端-->
<dubbo:reference interface="..." loadbalance="random" />
基于权重的轮训策略
<dubbo:reference interface="..." loadbalance="roundrobin" />
基于调用次数(导致慢机器接受更少的请求,降低负载)
<dubbo:reference interface="..." loadbalance="leastactive" />
一致性hash(默认使用参数hash)
<dubbo:reference interface="..." loadbalance="consistenthash" />
b . 客户端配置
<dubbo:referenceid="userService" loadbalance="consistenthash"interface="com.baizhi.service.UserService"/>
c. 服务端方法级别
<dubbo:serviceinterface="...">
<dubbo:method name="..." loadbalance="roundrobin"/>
</dubbo:service>
配置优先级: 消费者优先级最高,服务端优先级就近原则,一般优先选择在服务提供方配置
Dubbo中集群的容错
在集群调用失败时,Dubbo 提供了多种容错方案,缺省为 failover 重试。
集群容错模式配置:
<dubbo:servicecluster="failsafe"/>
或
<dubbo:referencecluster="failsafe"/
-
各节点关系:
a. 这里的 Invoker 是 Provider 的一个可调用 Service 的抽象,Invoker 封装了 Provider 地址及 Service 接口信息
Directory 代表多个 Invoker,可以把它看成 List<Invoker> ,但与 List 不同的是,它的值可能是动态变化的,比如注册中心推送变更
b.Cluster 将 Directory 中的多个 Invoker 伪装成一个 Invoker,对上层透明,伪装过程包含了容错逻辑,调用失败后,重试另一个
c.Router 负责从多个 Invoker 中按路由规则选出子集,比如读写分离,应用隔离等
d.LoadBalance 负责从多个 Invoker 中选出具体的一个用于本次调用,选的过程包含了负载均衡算法,调用失败后,需要重选
- Failover Cluster
失败自动切换,当出现失败,重试其它服务器 。通常用于读操作,但重试会带来更长延迟。可通过 retries="2" 来设置重试次数(不含第一次)。
重试次数配置如下:
<dubbo:service retries="2" />
或
<dubbo:referenceretries="2" />
或
<dubbo:reference>
<dubbo:method name="findFoo" retries="2" />
</dubbo:reference>
- Failfast Cluster
快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。
- Failsafe Cluster
失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。
- Failback Cluster
失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。
- Forking Cluster
并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 forks="2" 来设置最大并行数。
- Broadcast Cluster
广播调用所有提供者,逐个调用,任意一台报错则报错 [2]。通常用于通知所有提供者更新缓存或日志等本地资源信息。
Dubbo中线程模型
如果事件处理的逻辑能迅速完成,并且不会发起新的 IO 请求,比如只是在内存中记个标识,则直接在 IO 线程上处理更快,因为减少了线程池调度。
但如果事件处理逻辑较慢,或者需要发起新的 IO 请求,比如需要查询数据库,则必须派发到线程池,否则 IO 线程阻塞,将导致不能接收其它请求。
如果用 IO 线程处理事件,又在事件处理过程中发起新的 IO 请求,比如在连接事件中发起登录请求,会报“可能引发死锁”异常,但不会真死锁。
因此,需要通过不同的派发策略和不同的线程池配置的组合来应对不同的场景:
<dubbo:protocol name="dubbo" dispatcher="all" threadpool="fixed" threads="100" />
-
Dispatcher
-
all 所有消息都派发到线程池,包括请求,响应,连接事件,断开事件,心跳等。
-
direct 所有消息都不派发到线程池,全部在 IO 线程上直接执行。
-
message 只有请求响应消息派发到线程池,其它连接断开事件,心跳等消息,直接在 IO 线程上执行。
-
execution 只请求消息派发到线程池,不含响应,响应和其它连接断开事件,心跳等消息,直接在 IO 线程上执行。
-
connection 在 IO 线程上,将连接断开事件放入队列,有序逐个执行,其它消息派发到线程池。
ThreadPool
-
fixed 固定大小线程池,启动时建立线程,不关闭,一直持有。(缺省)
-
cached 缓存线程池,空闲一分钟自动删除,需要时重建。
-
limited 可伸缩线程池,但池中的线程数只会增长不会收缩。只增长不收缩的目的是为了避免收缩时突然来了大流量引起的性能问题。
-
eager 优先创建Worker线程池。在任务数量大于corePoolSize但是小于maximumPoolSize时,优先创建Worker来处理任务。当任务数量大于maximumPoolSize时,将任务放入阻塞队列中。阻塞队列充满时抛出RejectedExecutionException。(相比于cached:cached在任务数量超过maximumPoolSize时直接抛出异常而不是将任务放入阻塞队列)
-
线程自动dump
当业务线程池满时,我们需要知道线程都在等待哪些资源、条件,以找到系统的瓶颈点或异常点。dubbo通过Jstack自动导出线程堆栈来保留现场,方便排查问题
默认策略:
- 导出路径,user.home标识的用户主目录
- 导出间隔,最短间隔允许每隔10分钟导出一次
指定导出路径:
# dubbo.properties
dubbo.application.dump.directory=/tmp
<dubbo:application ...>
<dubbo:parameter key="dump.directory" value="/tmp" />
</dubbo:application>
直连提供者
在开发及测试环境下,经常需要绕过注册中心,只测试指定服务提供者,这时候可能需要点对点直连,点对点直连方式,将以服务接口为单位,忽略注册中心的提供者列表,A 接口配置点对点,不影响 B 接口从注册中心获取列表。
- 通过 XML 配置
如果是线上需求需要点对点,可在 dubbo:reference 中配置 url 指向提供者,将绕过注册中心,多个地址用分号隔开,配置如下 [1]:
<dubbo:reference id="xxxService" interface="com.alibaba.xxx.XxxService" url="dubbo://localhost:20890" />
- 通过 -D 参数指定
在 JVM 启动参数中加入-D参数映射服务地址 [2],如:
java -Dcom.alibaba.xxx.XxxService=dubbo://localhost:20890
- 通过文件映射
如果服务比较多,也可以用文件映射,用 -Ddubbo.resolve.file 指定映射文件路径,此配置优先级高于 dubbo:reference 中的配置 [3],如:
java -Ddubbo.resolve.file=xxx.properties
然后在映射文件 xxx.properties 中加入配置,其中 key 为服务名,value 为服务提供者 URL:
com.alibaba.xxx.XxxService=dubbo://localhost:20890
注意 为了避免复杂化线上环境,不要在线上使用这个功能,只应在测试阶段使用。
多协议/多版本/多注册中心/服务分组
Dubbo 支持同一服务向多注册中心同时注册,或者不同服务分别注册到不同的注册中心上去,甚至可以同时引用注册在不同注册中心上的同名服务。另外,注册中心是支持自定义扩展的 [1]。也就是注册中心的集群。
比如:中文站有些服务来不及在青岛部署,只在杭州部署,而青岛的其它应用需要引用此服务,就可以将服务同时注册到两个注册中心。
<dubbo:protocol name="dubbo" port="20880"/>
<dubbo:protocol name="rmi" port="20881"/>
<!--暴露本地的bean服务-->
<dubbo:service protocol="dubbo,rmi" interface="" ref="userService" weight="100" />
<!--消费端必须指定一个协议-->
<dubbo:reference interface="..." protocol="rmi" />
<!--多版本-->
<dubbo:service interface="com.foo.BarService" ref="XxBean_V1" version="1.0.0" />
<dubbo:service interface="com.foo.BarService" ref="XxBean_V2" version="2.0.0" />
<dubbo:reference interface="com.foo.BarService" version="2.0.0" />
<!--不关注写*-->
<dubbo:reference interface="com.foo.BarService" version="*" />
<!--服务分组-->
<dubbo:service group="g1" interface="com.xxx.IndexService" ref="xxBean1" />
<dubbo:service group="g2" interface="com.xxx.IndexService" ref="xxBean2"/>
<dubbo:reference interface="com.xxx.IndexService" group="g1" />
<!--如果不关注组,可以写*-->
<dubbo:reference interface="com.xxx.IndexService" group="*" />
<!--多注册中心-->
<dubbo:registry id="reg1" address="" />
<dubbo:registry id="reg2" address="" default="false" />
<dubbo:service interface="" ref="xx" registry="reg1,reg2" />
上下文信息|上下文传参
隐式传参
RpcContext.getContext().setAttachment("index", "1"); // 隐式传参,后面的远程调用都会隐式将这些参数发送到服务器端,类似cookie,用于框架集成,不建议常规业务使用
xxxService.xxx(); // 远程调用
---
public class XxxServiceImpl implements XxxService {
public void xxx() {
// 获取客户端隐式传入的参数,用于框架集成,不建议常规业务使用
String index = RpcContext.getContext().getAttachment("index");
}
}
上下文信息
// 远程调用
xxxService.xxx();
// 本端是否为消费端,这里会返回true
boolean isConsumerSide = RpcContext.getContext().isConsumerSide();
// 获取最后一次调用的提供方IP地址
String serverIP = RpcContext.getContext().getRemoteHost();
// 获取当前服务配置信息,所有配置信息都将转换为URL的参数
String application = RpcContext.getContext().getUrl().getParameter("application");
// 注意:每发起RPC调用,上下文状态会变化
yyyService.yyy();
---
public class XxxServiceImpl implements XxxService {
public void xxx() {
// 本端是否为提供端,这里会返回true
boolean isProviderSide = RpcContext.getContext().isProviderSide();
// 获取调用方IP地址
String clientIP = RpcContext.getContext().getRemoteHost();
// 获取当前服务配置信息,所有配置信息都将转换为URL的参数
String application = RpcContext.getContext().getUrl().getParameter("application");
// 注意:每发起RPC调用,上下文状态会变化
yyyService.yyy();
// 此时本端变成消费端,这里会返回false
boolean isProviderSide = RpcContext.getContext().isProviderSide();
}
}
服务治理
|-dubbo
|
|--com.baizhi.service.IUserService
|-consumers
|-configurators
|-routers
|-providers
|--com.baizhi.service.IOrderService
|-consumers
|-configurators
|-routers
|-providers
dubbo提供一个服务治理的webapp叫做dubboAdmin,由于该应有bug层出不穷,最终被dubbo抛弃。目前使用dubbo公司一般都会选择dubbokeeper第三方提供的服务治理应用管理Dubbo集群。用户可以使用DubboKeeper实现配置规则(动态配置服务端、消费端运行参数例如:权重/容错/屏蔽)、路由规则
1)下载Dubbo-keeper安装包
https://github.com/dubboclub/dubbokeeper/archive/dubbokeeper-1.0.1.tar.gz
2)解压该文件
3)在window是执行install-mysql.bat
4)将Dubbo-keeper目录下的target下的mysql-dubbokeeper-ui/dubbokeeper-ui-1.0.1.war拷贝到tomcat的webapps下
5)启动tomcat ,修改上面的war包解压出来后对其中WEB-INF/classes/dubbo.properties文件中的配置项进行调整。
dubbo.application.name=common-monitor
dubbo.application.owner=bieber
dubbo.registry.address=zookeeper://192.168.128.128:2181
#use netty4
dubbo.reference.client=netty4
#peeper config
peeper.zookeepers=192.168.128.128:2181
peeper.zookeeper.session.timeout=60000
#logger
monitor.log.home=/monitor-log
monitor.collect.interval=6000
6)访问Dubbo-keeper
http://localhost:8080/dubbokeeper-ui-1.0.1
泛化调用
泛化接口调用方式主要用于客户端没有 API 接口及模型类元的情况,参数及返回值中的所有 POJO 均用 Map 表示,通常用于框架集成,比如:实现一个通用的服务测试框架,可通过 GenericService 调用所有服务实现。
通过 Spring 使用泛化调用
-
在 Spring 配置申明 generic="true":
<dubbo:reference id="barService" interface="com.foo.BarService" generic="true" />
-
在 Java 代码获取 barService 并开始泛化调用:
GenericService barService = (GenericService) applicationContext.getBean("barService"); Object result = barService.$invoke("sayHello", new String[] { "java.lang.String" }, new Object[] { "World" });
5.分布式架构
当服务集群规模进一步扩大,带动IT治理结构进一步升级,需要实现动态部署,进行流动计算,现有分布式服务架构不会带来阻力。下图是未来可能的一种架构:
节点角色说明
节点 角色说明
Deployer 自动部署服务的本地代理
Repository 仓库用于存储服务应用发布包
Scheduler 调度中心基于访问压力自动增减服务提供者 Admin 统一管理控制台
Registry 服务注册与发现的注册中心
Monitor 统计服务的调用次数和调用时间的监控中心