dubbo+zookeeper+springboot
微服务下有provider和consumer,消息生产者提供api,供消费者调用。
1、创建父项目
idea创建springboot工程,作为父级工程,所以删掉无用的文件,只保留.idea和pom.xml,在pom.xml中引入项目所需的依赖:
<!-- https://mvnrepository.com/artifact/com.gitee.reger/spring-boot-starter-dubbo -->
<dependency>
<groupId>com.gitee.reger</groupId>
<artifactId>spring-boot-starter-dubbo</artifactId>
<version>1.1.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.6.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.101tec/zkclient -->
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.11</version>
</dependency>
注意:zookeeper包和zkclient包都不能少
缺少zookeeper的pom依赖会报错:java.lang.NoClassDefFoundError: org/apache/zookeeper/Watcher E v e n t Event EventKeeperState
缺少zkclient的pom依赖会报错:java.lang.NoClassDefFoundError: org/I0Itec/zkclient/IZkStateListener
2、创建provider模块
在父项目下new一个maven项目provider作为生产者,并且添加两个类,一个是springboot的启动类ProviderApplication.java,另一个是提供api服务的service类MessageApiServiceImpl.java
package com.jinbin;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ProviderApplication {
public static void main(String[] args) throws InterruptedException {
SpringApplication.run(ProviderApplication.class, args);
}
}
package com.jinbin.service;
import com.alibaba.dubbo.config.annotation.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Service() //注意:这里的service是dubbo的注解com.alibaba.dubbo.config.annotation.Service
public class MessageApiServiceImpl implements MessageApiService {
private final static Logger logger = LoggerFactory.getLogger(MessageApiServiceImpl.class);
@Override
public String getMessage(String message) {
logger.info("这是服务提供者, 服务消费者远程调用了getMessage(), 参数为message={}", message);
return "这是服务提供者, 服务消费者远程调用了getMessage(), 参数为message="+message;
}
}
说明:该类实现的 BookService 接口,目的是模块与模块之间解耦,单独建一个接口模块 interface,详见4
provoder的配置文件中配置zookeeper注册中心的 ip+port
server:
port: 8081 #tomcat 启动端口号
spring:
dubbo:
application:
name: service-provider
base-package: com.jinbin.service # dubbo服务发布者实现类注解所在的包
registry:
address: 127.0.0.1 # zookeeper注册中心的地址
port: 2181 # zookeeper注册中心的端口
protocol:
name: dubbo
provider:
retries: 0 # 服务调用重试次数,服务发布者不给重试,让服务调用者自己重试
3、创建consumer模块
在父项目下new一个maven项目consumer作为消费者,并且添加两个类,一个是springboot的启动类ConsumerApplication.java,另一个是接口类MessageApiController.java,调用生产者的服务。
package com.jinbin;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* 实现CommandLineRunner这个接口是为了重写它的run方法,
* 启动完成以后会自动执行run方法的内容。
*/
@SpringBootApplication
public class ConsumerApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
System.err.println("服务调用者------>>启动完毕");
}
}
package com.jinbin.controller;
import com.jinbin.service.MessageApiService;
import com.reger.dubbo.annotation.Inject;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Component
public class MessageApiController implements CommandLineRunner {
// @Reference() //远程调用
// public MessageApiService service;
// 使用兼容注入,可以使用dubbo原生注解@Reference注入
@Inject
public MessageApiService service;
@Override
public void run(String... args){
String message="初始message";
System.out.println(service.getMessage(message));
System.out.println("调用完成");
}
@RequestMapping(value = "/", method = RequestMethod.GET)
public String getMessage(String message){
message = message== null ? "初始message" : message;
return service.getMessage(message);
}
}
consumer的配置文件中配置zookeeper注册中心的 ip+port
server:
port: 8082 #tomcat端口号
spring:
dubbo:
application:
name: service-consumer
base-package: com.jinbin # dubbo服务发布者实现类注解所在的包
registry:
address: 127.0.0.1 # zookeeper注册中心的地址
port: 2181 # zookeeper注册中心的端口
protocol:
name: dubbo
provider:
retries: 0 # 服务调用重试次数,服务发布者不给重试,让服务调用者自己重试
4、interface模块
该模块只用于解耦,定义一些接口,由provider模块实现,例如
package com.jinbin.service;
public interface MessageApiService {
String getMessage(String message);
}
5、zookeeper下载启动
下载bin的压缩包并解压,在bin目录下有zkServer.cmd和zkServer.sh,分别是win和linux下的启动脚本,启动
-启动闪退:打开启动脚本,左后一行添加pause即可
-报错:zookeeper需要读取conf下的配置文件zoo.cfg
解决:将conf/zoo_sammple.cfg复制为zoo.cfg,修改其中的配置,一般仅需修改dataDir,例如修改为dataDir=E:\JAVA\zookeeper\apache-zookeeper-3.5.8-bin\data
-启动成功
6、项目启动
依次启动provider模块和consumer模块
在浏览器访问 http://127.0.0.1:8082?name=hello dubbo
7、负载均衡
借助zookeeper实现的负载均衡,只需启动多个服务生产者即可
启动两个ProviderApplication,一个端口为8081,另一个为8083,启动一个ConsumerApplication,端口为8082
为了验证负载均衡是否成功,对ProviderApplication中的service修改为:
package com.jinbin.service;
import com.alibaba.dubbo.config.annotation.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
@Service() //注意:这里的service是dubbo的注解com.alibaba.dubbo.config.annotation.Service
public class MessageApiServiceImpl implements MessageApiService {
private final static Logger logger = LoggerFactory.getLogger(MessageApiServiceImpl.class);
@Value("${server.port}")
private String port;
@Override
public String getMessage(String message) {
logger.info("这是服务提供者, port={}, 服务消费者远程调用了getMessage(), 参数为message={}", port, message);
return "这是服务提供者, port=" + port + ", 服务消费者远程调用了getMessage(), 参数为message="+message;
}
}
在浏览器访问 http://127.0.0.1:8082
关闭8081端口对应的服务之后再访问,port变为8083