1)安装zookeeper:
下载源代码zookeeper-3.3.6并解压缩,进入目录zookeeper-3.3.6/conf中修改zoo_sample.conf文件并重新保存为zoo.conf
1.1)单机模式:
tickTime=2000
dataDir= /zookeeper-3.3.6/tmp/zookeeper
dataLogDir=/zookeeper-3.3.6/tmp/zookeeper
clientPort=2181
ltickTime:这个时间是作为 Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳。
ldataDir:顾名思义就是 Zookeeper 保存数据的目录,默认情况下,Zookeeper 将写数据的日志文件也保存在这个目录里。
ldataLogDir: log目录, 同样可以是任意目录. 如果没有设置该参数, 将使用和dataDir相同的设置.
lclientPort:这个端口就是客户端连接 Zookeeper
服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。
1.2)集群模式:
initLimit=5
syncLimit=2
server.1=192.168.136.129:2888:3888
server.2=192.168.136.131:2888:3888
linitLimit:这个配置项是用来配置 Zookeeper 接受客户端(这里所说的客户端不是用户连接 Zookeeper 服务器的客户端,而是 Zookeeper 服务器集群中连接到 Leader 的 Follower 服务器)初始化连接时 最长能忍受多少个心跳时间间隔数。当已经超过 10 个心跳的时间(也就是 tickTime)长度后 Zookeeper 服务器还没有收到客户端的返回信息,那么表明这个客户端连接失败。总的时间长度就是 5*2000=10 秒
lsyncLimit:这个配置项标识 Leader 与 Follower 之间发送消息,请求和应答时间长度,最长不能超过多少个
tickTime 的时间长度,总的时间长度就是 2*2000=4 秒
lserver.A=B:C:D:其中 A 是一个数字,表示这个是第几号服务器;B 是这个服务器的 ip 地址;C 表示的是这个服务器与集群中的 Leader 服务器交换信息的端口;D 表示的是万一集群中的 Leader 服务器挂了,需要一个端口来重新进行选举,选出一个新的 Leader,而这个端口就是用来执行选举时服务器相互通信的端口。如果是伪集群的配置方式,由于 B 都是一样,所以不同的 Zookeeper 实例通信端口号不能一样,所以要给它们分配不同的端口号。
l除了修改 zoo.cfg 配置文件,集群模式下还要配置一个文件 myid,这个文件在 dataDir 目录下,这个文件里面就有一个数据就是 A 的值,Zookeeper 启动时会读取这个文件,拿到里面的数据与 zoo.cfg 里面的配置信息比较从而判断到底是那个 server。
1.3)启动zookeeper:
进入bin目录:
./zkServer.sh start
启动结果如图:
2)dubbo使用
2.1)新建生产者项目
2.1.1)定义接口类:
package provider; /** * 接口类,服务需要实现此类 * @author huangt */ public interface IProcessData { public String deal(String data); } |
2.1.2)实现接口:
package provider; /** * 实现接口 * @author huangt */ public class ProcessDataImpl implements IProcessData { @Override public String deal(String data) { System.out.println("逻辑处理。。。"); return "Finished:" + data; } } |
2.1.3)在spring的配置文件中注册服务接口:
<!-- 注册名称 --> <dubbo:application name="provider" /> <!-- 使用zookeeper注册中心暴露服务地址,这里zookeeper配置为一个集群方式 address=zookeeper服务IP:监听端口 --> <dubbo:registry protocol="zookeeper" check="true" address="192.168.136.129:2181,192.168.136.131:2181"/> <!-- 用dubbo协议在20880端口暴露服务 --> <dubbo:protocol name="dubbo" port="20880"/> <!-- 接口实现类 --> <bean id="demoService"class="provider.ProcessDataImpl" /> <!-- 发布接口--> <dubbo:service interface="provider.IProcessData" ref="demoService" register="true"/> |
dubbo:registry 标签一些属性的说明:
1)register是否向此注册中心注册服务,如果设为false,将只订阅,不注册。
2)check注册中心不存在时,是否报错。
3)address可以Zookeeper集群配置,地址可以多个以逗号隔开等。
dubbo:service标签的一些属性说明:
1)interface服务接口的路径
2)ref引用对应的实现类的Bean的ID
3)register 默认true ,该协议的服务是否注册到注册中心。
启动生产者:
package main; import
org.springframework.context.support.ClassPathXmlApplicationContext; public class DubboProviderMain { public static void main(String[] args) throws Exception { @SuppressWarnings("resource") ClassPathXmlApplicationContext context = new
ClassPathXmlApplicationContext( new String[]{"applicationProvider.xml"}); context.start(); System.out.println("Press any key to exit."); System.in.read(); } } |
2.2.编写消费者工程:
2.2.1)消费者配置:
<dubbo:application name="consumer-of-helloworld-app" /> <!--
<dubbo:registry protocol="zookeeper"
address="127.0.0.1:2181,127.0.0.1:2182" /> --> <dubbo:registry protocol="zookeeper" address="192.168.136.129:2181,192.168.136.131:2181"/> <dubbo:reference id="demoService" interface="provider.IProcessData" /> |
dubbo:reference 的一些属性的说明:
1)interface调用的服务接口
2)check 启动时检查提供者是否存在,true报错,false忽略
3)
loadbalance 负载均衡策略,可选值:random,roundrobin,leastactive,分别表示:随机,轮循,最少活跃调用
2.2.2)编写消费者类:
package consumer; import
org.springframework.context.support.ClassPathXmlApplicationContext; import provider.IProcessData; public class ConsumerThd { public static void main(String[] args) { @SuppressWarnings("resource") ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( new String[]{"applicationConsumer.xml"}); context.start(); IProcessData demoService = (IProcessData) context.getBean("demoService"); String hello = demoService.deal("nihao"); System.out.println("返回结果:" + hello); } } |
启动消费者访问,可以访问到相关的生产者。
3)dubbo集群容错模式容错性和负载均衡
容错性
当客户端访问服务端的时候,服务端出错或者网络出现问题,都会使得远程访问失败,失败是不可避免的,所以Dubbo制定了一些策略:
Failover
Cluster
失败自动切换,当出现失败,重试其它服务器。(缺省)
通常用于读操作,但重试会带来更长延迟。
可通过retries="2"来设置重试次数(不含第一次)。
快速失败,只发起一次调用,失败立即报错。
通常用于非幂等性的写操作,比如新增记录。
失败安全,出现异常时,直接忽略。
通常用于写入审计日志等操作。
失败自动恢复,后台记录失败请求,定时重发。
通常用于消息通知操作。
并行调用多个服务器,只要一个成功即返回。
通常用于实时性要求较高的读操作,但需要浪费更多服务资源。
可通过forks="2"来设置最大并行数。
广播调用所有提供者,逐个调用,任意一台报错则报错。(2.1.0开始支持)
通常用于通知所有提供者更新缓存或日志等本地资源信息。
重试次数配置如:(failover集群模式生效)
<dubbo:service retries="2" />
或:
<dubbo:reference retries="2" />
或:
<dubbo:reference>
<dubbo:method name="findFoo" retries="2" />
</dubbo:reference>
集群模式配置如:
<dubbo:service cluster="failsafe" />
或:
<dubbo:reference cluster="failsafe" />
负载均衡
在集群负载均衡时,Dubbo提供了多种均衡策略,缺省为random随机调用。
随机,按权重设置随机概率。
在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重。
轮循,按公约后的权重设置轮循比率。
存在慢的提供者累积请求问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。
最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。
使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。
一致性Hash,相同参数的请求总是发到同一提供者。
当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。
缺省只对第一个参数Hash,如果要修改,请配置<dubbo:parameter
key="hash.arguments" value="0,1" />
缺省用160份虚拟节点,如果要修改,请配置<dubbo:parameter
key="hash.nodes" value="320" />
配置如:
<dubbo:service interface="..." loadbalance="roundrobin" />
或:
<dubbo:reference interface="..." loadbalance="roundrobin" />
或:
<dubbo:service interface="...">
<dubbo:method name="..." loadbalance="roundrobin"/>
</dubbo:service>
或:
<dubbo:reference interface="...">
<dubbo:method name="..." loadbalance="roundrobin"/>
</dubbo:reference>