设为首页 收藏本站
查看: 1371|回复: 0

[经验分享] Spring整合Dubbo,使用zookeeper作为注册中心,进行远程调用及负载均衡、自动失效转移(何志雄)

[复制链接]

尚未签到

发表于 2015-11-21 15:29:01 | 显示全部楼层 |阅读模式
  1、Mavn依赖:
  

<span style=&quot;white-space:pre&quot;></span><!-- dubbo begin -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.3</version>
<exclusions>
<exclusion>
<artifactId>spring</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
<scope>runtime</scope>
</dependency>
<!-- dubbo end -->
<!-- zookeeper begin -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.6</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.4</version>
</dependency>
<!-- zookeeper end -->
  2、定义服务端提供方和消费方的通信接口
  IDispatch.java


  

package com.gaojiasoft.test.dubbo;
//服务接口,dubbo服务的提供方及消费方都需要使用
public interface IDispatch
{
/**
* 有返回值,此时异步调用是收不到返回值的,需要在调用方增加回调接口获取返回值。
* @param msg
* @return
*/
String dispatch(String msg);
/**
* 没有返回值的,比较适合异步调用
* @param msg
*/
void noReturn(String msg);
}


3、在服务提供方实现具体的服务(在注销代码中,笔者视图使用多线程来处理客户端的请求,事实证明Dubbo中多此一举,Dubbo是基于NIO的TCP通信,本身已经是线程池)  
  DispatchImpl.java


  

package com.gaojiasoft.test.dubbo.provider;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gaojiasoft.test.dubbo.IDispatch;
public class DispatchImpl implements IDispatch {
public static final Logger log = LoggerFactory
.getLogger(DispatchImpl.class);
/**
*不需要使用多线程处理客户端请求,因为dubbo的服务端是NIO,内部含有多线程复用
*/
private static final ThreadPoolExecutor executor = new ThreadPoolExecutor(
50, 150, 30L, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(),
new BasicThreadFactory.Builder().daemon(true)
.namingPattern(&quot;Dubbo-Provider-%d&quot;).build(),
new ThreadPoolExecutor.CallerRunsPolicy());
@Override
public String dispatch(final String msg) {
//String back = null;
//Future<Object> future = executor.submit(new Callable<Object>() {
//@Override
//public Object call() throws Exception {
//
//log.debug(&quot;Server1 get msg:&quot;+msg);
//Thread.sleep(1);
//return &quot;SERVER 1 retrun:&quot; + msg;
//
//}
//});
//try {
//back = future.get().toString();
//} catch (InterruptedException | ExecutionException e) {
//e.printStackTrace();
//}
//return back;
log.debug(&quot;Server1 get msg:&quot;+msg);
//Thread.sleep(1);
return &quot;SERVER 1 retrun:&quot; + msg;
}
@Override
public void noReturn(String msg) {
}
}


4、服务提供方的Spring配置  
  

<?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?>
<!-- dubbo服务提供方 -->
<beans xmlns=&quot;http://www.springframework.org/schema/beans&quot;
xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xmlns:dubbo=&quot;http://code.alibabatech.com/schema/dubbo&quot;
xsi:schemaLocation=&quot;http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd&quot;>
<!-- 提供方应用信息,用于计算依赖关系 -->
<dubbo:application name=&quot;Server-B&quot; />
<!-- 使用zookeeper对外暴露服务 -->
<dubbo:registry protocol=&quot;zookeeper&quot;
address=&quot;192.168.62.155:2181,192.168.62.153:2181,192.168.62.154:2181&quot; />
<!-- 用dubbo协议在20880端口暴露服务 -->
<!-- 提供服务的线程池固定数量为100,iothreads配置CPU个数+1 -->
<dubbo:protocol name=&quot;dubbo&quot; port=&quot;20880&quot; dispatcher=&quot;message&quot;
threadpool=&quot;fixed&quot; threads=&quot;100&quot; iothreads=&quot;3&quot; />
<!-- 声明需要暴露的服务接口 及实现类-,版本号2.0.0,配置同样版本号的消费者调用同样版本号的生产者,executes=&quot;200&quot;服务提供者线程池线程数,
loadbalance=&quot;leastactive&quot;是负载服务端并发数量最小的,可选值random:随机,roundrobin:轮询,leastactive:最小并发 -->
<dubbo:service interface=&quot;com.gaojiasoft.test.dubbo.IDispatch&quot;
ref=&quot;disPatchImpl&quot; version=&quot;1.0.0&quot; loadbalance=&quot;roundrobin&quot; group=&quot;hs&quot;>
</dubbo:service>
<!-- 和本地bean一样实现服务 -->
<bean id=&quot;disPatchImpl&quot; class=&quot;com.gaojiasoft.test.dubbo.provider.DispatchImpl&quot; />
</beans>

  
  


  


  关于配置文件的介绍:
  1、<dubbo:protocol>中的dispatcher可选择
  0. all 所有消息都派发到线程池,包括请求,响应,连接事件,断开事件,心跳等。

1. direct 所有消息都不派发到线程池,全部在IO线程上直接执行。

2. message 只有请求响应消息派发到线程池,其它连接断开事件,心跳等消息,直接在IO线程上执行。

3. execution 只请求消息派发到线程池,不含响应,响应和其它连接断开事件,心跳等消息,直接在IO线程上执行。

4. connection 在IO线程上,将连接断开事件放入队列,有序逐个执行,其它消息派发到线程池。


  


  2、<dubbo:server>中的group适用于多个系统都有同样名称的服务,此时,通过分组加以区分,此时消费方配置同样名称分组的就会调用同样名称的消费方。
  3、<dubbo:server>中的version使用一个服务有多个版本,此时服务端提供多,可以提供多个名称同样的方法,使用不通的版本号。例如:
  

<dubbo:service interface=&quot;com.gaojiasoft.test.dubbo.IDispatch&quot;
ref=&quot;<strong>disPatchImpl</strong>&quot;<strong> version=&quot;1.0.0&quot;</strong> loadbalance=&quot;roundrobin&quot; group=&quot;hs&quot;>
</dubbo:service><dubbo:service interface=&quot;com.gaojiasoft.test.dubbo.IDispatch&quot;
ref=&quot;<strong>disPatchImpl</strong>&quot; <strong>version=&quot;2.0.0&quot;</strong> loadbalance=&quot;roundrobin&quot; group=&quot;hs&quot;>
</dubbo:service>可以看到,服务名称一致,版本号不一直的服务被同时暴露,此时客户端按照自己的需求调用不同的版本号。就使得整个平台的可扩展性大大加强,非常使用整个平台的向下兼容的能力。  
  


  



5、服务提供方的启动类  DubboTest.java
  

package com.gaojiasoft.test.dubbo;
import java.io.IOException;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class DubboTest {
private static ConfigurableApplicationContext contextProvider;
private static ConfigurableApplicationContext contextConsumer;
private Logger logger = LoggerFactory.getLogger(&quot;DubboTest&quot;);
private static final ThreadPoolExecutor executor = new ThreadPoolExecutor(
50, 150, 30L, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(),
new BasicThreadFactory.Builder().daemon(true)
.namingPattern(&quot;Dubbo-Consumer-%d&quot;).build(),
new ThreadPoolExecutor.CallerRunsPolicy());
@Test
public void test() throws IOException, InterruptedException {
// String []list = new
// String[]{&quot;classpath:conf/dubbo/spring-dubbo-provider.xml&quot;,&quot;classpath:conf/dubbo/spring-dubbo-consumer.xml&quot;};
// contextProvider = new ClassPathXmlApplicationContext(list,true,null);
contextProvider = new ClassPathXmlApplicationContext(
&quot;classpath:conf/dubbo/spring-dubbo-provider.xml&quot;);
while (true) {
Thread.sleep(1);
}
//contextConsumer = new ClassPathXmlApplicationContext(
//&quot;classpath:conf/dubbo/spring-dubbo-consumer.xml&quot;);
//
//IDispatch service = (IDispatch) contextConsumer.getBean(&quot;disPatcher&quot;);
//
//int i = 1;
//while (true) {
//try {
//// 多线程消费
//mulitThreadConsumer(service, &quot;&quot; + i);
//} catch (Exception e) {
//logger.error(&quot;exception,dubbo provider error!&quot;);
//}
//Thread.sleep(1000);
//i++;
//}
}
/**
* 多线程消费者
*
* @param keyvalue
*/
private void mulitThreadConsumer(final IDispatch service,
final String message) {
executor.execute(new Runnable() {
@Override
public void run() {
try {
String revice = service.dispatch(message);
logger.debug(&quot;通过dubbo调用服务,返回的消息是:&quot; + revice);
Thread.sleep(1);
} catch (Throwable th) {
// 防御性容错,避免高并发下的一些问题
logger.error(&quot;&quot;, th);
}
}
});
}
}


6、服务端消费方的Spring配置  
  

<?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?>
<!-- dubbo服务消费方 -->
<beans xmlns=&quot;http://www.springframework.org/schema/beans&quot;
xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xmlns:dubbo=&quot;http://code.alibabatech.com/schema/dubbo&quot;
xsi:schemaLocation=&quot;http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd&quot;>
<!-- 消费方应用信息,用于计算依赖关系,与提供方不要一样 -->
<dubbo:application name=&quot;Server-A&quot; />
<!-- 使用zookeeper注册中心暴露服务地址 -->
<dubbo:registry protocol=&quot;zookeeper&quot; address=&quot;192.168.62.155:2181,192.168.62.153:2181,192.168.62.154:2181&quot; />
<!-- 生成远程服务代理,与服务提供者建立3个TCP连接,并采用异步调用(非阻塞) -->
<dubbo:reference id=&quot;disPatcher&quot; connections=&quot;3&quot;
interface=&quot;com.gaojiasoft.test.dubbo.IDispatch&quot; version=&quot;1.0.0&quot; sent=&quot;false&quot;
async=&quot;true&quot; group=&quot;hs&quot;>
<!-- active是消费方请求线程池线程数,可针对不同的方法声明不同的线程数-->
<dubbo:method name=&quot;dispatch&quot; return=&quot;false&quot; actives=&quot;50&quot;></dubbo:method>
</dubbo:reference>
</beans>

  
  



7、服务消费方的启动类  DubboConsumerStart.java
  

package com.study.dubbo.consumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.gaojiasoft.test.dubbo.IDispatch;
public class DubboConsumerStart
{
public static final Logger log = LoggerFactory.getLogger(DubboConsumerStart.class);
public static void main(String[] args) throws Exception
{
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(&quot;conf/spring-dubbo-consumer.xml&quot;);
context.start();
IDispatch service = (IDispatch) context.getBean(&quot;dispatcher&quot;);
int i =1;
while(true)
{
try
{
String revice = service.dispatch(&quot;&quot;+i);
log.debug(&quot;通过dubbo调用服务,返回的消息是:&quot; + revice);
Thread.sleep(1);
i++;
}catch(Exception e)
{
log.debug(&quot;调用异常:&quot; + e.getClass().getName());
}
}
// System.in.read(); //为保证服务一直开着,利用输入流的阻塞来模拟
}
}



  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-141909-1-1.html 上篇帖子: 2.zookeeper原理解析-数据存储之Snapshot 下篇帖子: zookeeper应用——集中配置管理系统的实现
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表