之前学习了一阵spring cloud,一直没想着写博客,这两天看了看dubbo+zk,先写一下这个相关的内容吧。
才疏学浅,有错误请指正。
首先需要安装zookeeper
找到download,进行下载即可。
下载后,解压到自己想要解压的某个地方。以我的windows系统为例,我解压到:E:\zookeeper-3.4.10
现在我们需要修改一下E:\zookeeper-3.4.10\conf 下的cfg文件名为:zoo.cfg。因为启动时,zookeeper会默认加载zoo.cfg来启动,否则启动不了。然后再文本编辑器打开,修改内容:
dataDir=E:/zookeeper/tmp/zookeeper
dataLogDir=E:/zookeeper/tmp/logs
这个时候,进入E:\zookeeper-3.4.10\bin,双击zkServer.cmd运行。如果出现闪退,那么代表出现了异常,编辑cmd文件,再最后加上 pause ,查看报错原因。 如果没闪退应该是成功的,然后双击zkCli.cmd,如果出现
代表安装并启动成功了。
安装dubbo
下载地址:https://github.com/apache/incubator-dubbo
这里有可以去dubbo的github上下载然后打成war包,放到tomcat下,再修改一下tomcat的默认端口号,8080被zookeeper占用了,所以修改tomcat的默认端口号为8888,启动tomcat。
访问:http://localhost:8888/dubbo-admin-2.5.4/
这时候会出现
账号密码再dubbo项目的配置文件中,
使用root、root登录。
最后是我们的服务提供者和服务消费者
我们这里使用springboot框架进行项目搭建。springboot项目搭建见之前的文章:
服务提供者
1、先引入依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.4.10</version>
<exclusions>
<exclusion>
<artifactId>spring</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.6</version>
<exclusions>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>
2、新建接口及其实现。
package com.wm.dubbo.provider.service;
public interface TestService {
String sayHello(String name);
}
package com.wm.dubbo.provider.service.impl;
import org.springframework.stereotype.Service;
import com.wm.dubbo.provider.service.TestService;
@Service("testService")
public class TestServiceImpl implements TestService {
@Override
public String sayHello(String name) {
return "hello~" + name;
}
}
3、在src/main/resource下新建providers.xml配置文件。
<?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://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="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">
<!-- 服务提供方应用名,用于计算依赖关系 -->
<dubbo:application name="dubbo-provider" />
<!-- 定义 zookeeper 注册中心地址及协议 -->
<dubbo:registry protocol="zookeeper" address="zookeeper://127.0.0.1:2181" />
<!-- 生成远程服务代理,可以和本地bean一样使用demoService -->
<dubbo:service interface="com.wm.dubbo.provider.service.TestService" ref="testService"></dubbo:service>
</beans>
4、启动类,添加加载XML启动。
package com.wm.dubbo.provider;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
@SpringBootApplication
@ImportResource(value = {"classpath:providers.xml"})
public class AppProvider {
public static void main(String[] args) {
SpringApplication.run(AppProvider.class, args);
}
}
服务消费者
1、引入依赖,和服务提供者一样,不在重复粘贴。
2、新建接口,其实应该把服务提供者的接口和实现分离,保证接口是提供者和消费者共同调用的,但示例犯懒就不拆分了。
package com.wm.dubbo.provider.service;
public interface TestService {
String sayHello(String name);
}
3、在src/main/resource下新建consumers.xml配置文件。
<?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://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="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">
<!-- 配置可参考 http://dubbo.io/User+Guide-zh.htm -->
<!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
<dubbo:application name="dubbo-consumer"/>
<!-- 定义 zookeeper 注册中心地址及协议 -->
<dubbo:registry protocol="zookeeper" address="zookeeper://127.0.0.1:2181"/>
<!-- 生成远程服务代理,可以和本地 bean 一样使用 testService -->
<dubbo:reference id="testService" interface="com.wm.dubbo.provider.service.TestService"></dubbo:reference>
</beans>
4、启动类,添加加载XML启动。
package com.wm.dubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.context.annotation.ImportResource;
@SpringBootApplication
@ImportResource(value = { "classpath:consumers.xml" })
public class AppConsumer extends SpringBootServletInitializer implements EmbeddedServletContainerCustomizer {
public static void main(String[] args) {
SpringApplication.run(AppConsumer.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(AppConsumer.class);
}
public void customize(ConfigurableEmbeddedServletContainer container) {
container.setPort(8082);
}
}
5、服务消费者需要一个消费入口,我们再写一个controller
package com.wm.dubbo.provider.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.wm.dubbo.provider.service.TestService;
@Controller
public class TestController {
@Autowired
private TestService testService;
@RequestMapping("/test")
@ResponseBody
public String test(@RequestParam("name")String msg) {
return testService.sayHello(msg);
}
}
启动顺序,先启动zookeeper,再启动服务提供者,再启动服务消费者。
这时候我们可以从dubbo控制台看到:
访问试一哈。
通过消费者,使用到了服务提供者的提供的接口实现。 成功。
对了,有个坑
当我写这个示例写到服务消费者时,启动项目后报错,百度了好久发现有人说是spring的热部署依赖导致的。果然,去掉此依赖启动成功。具体原因我分析和spring-boot-devtools的原理有关,他是把系统分为两个classloader,一个加载那些不会轻易改变的jar包相关内容,一个加载那些我们自己写的java文件。拆分了之后可能存在bug,对dubbo有影响。这个还需要具体去研究一下,现在的解决方式就是dubbo的项目中不要使用devtools热部署,如果需要热部署,可以使用spring loaded试一下。
写到最后
其实写这个示例之前,对dubbo和zookeeper看了很多文章也是不太明白。现在写完之后发现和spring cloud+eureka类似。
dubbo和spring cloud感觉有点像(说的不对请指正哈)。都是代替webservice进行系统间的轻量级通信的。
原来的系统间通信,可能随着系统的复杂度提升越来越不能满足项目需求,所以需要使用dubbo的soa管理系统间通信,通过服务发现与注册对暴露接口进行统一管理。
而zookeeper和eureka就是他们的服务注册和发现中心。并且用轮询。随机等方式进行负责均衡,起到一个类似路由的效果。
dubbo和zookeeper的好处我觉得是一个是dubbo对代码的低侵略性。好像是几乎没有侵略。不需要因为搞了分布式而改动逻辑代码。
zookeeper的好处是他是一个文件系统,当服务被发现注册到注册中心,他们把访问IP写到硬盘并把服务提供者的列表返回给服务消费者,即使这个时候zookeeper挂掉,也不会有影响。
有关分布式还有很多内容需要学习。继续努力吧。