微服务下有provider和consumer,消息生产者提供api,供消费者调用。
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
在父项目下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 # 服务调用重试次数,服务发布者不给重试,让服务调用者自己重试在父项目下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 # 服务调用重试次数,服务发布者不给重试,让服务调用者自己重试该模块只用于解耦,定义一些接口,由provider模块实现,例如
package com.jinbin.service; public interface MessageApiService { String getMessage(String message); }下载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
-启动成功
依次启动provider模块和consumer模块
在浏览器访问 http://127.0.0.1:8082?name=hello dubbo
借助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
