现在我们SpringCloud Alibaba比较火,用的比较多是吧,那dubbo是不是过时的呢? 不是啊,以前有人把Dubbo和SpringCloud进行对比,其实两者是不同维度的,不能对比,dubbo就是一个rpc框架,SpringCloud是一个生态,里面包括很多组件,并且dubbo3也可以和SpringCloudAlibaba一些组件进行整合,并且我认为dubbo和SpringCloud alibaba进行整合后能发发挥两个的优势,dubbo的rpc调用的性能会很好,SpringCloudAlibaba服务治理能力很强。微服务中我们经常使用feign,feign是发送http请求而dubbo是rpc,性能要好我们可以dubbo代替feign的http请求是吧。并且他作为一个老牌子的分布式框架用的人还是比较多
《分布式系统原理与范型》定义:
歇后语:“三个臭皮匠赛过诸葛亮”,就是分布式系统的真实写照
单体架构应该是我们最先接触到的架构实现了,在单体架构中使用经典的三层模型,即表现层,业务逻辑层和数据访问层。
单体架构只适合在应用初期,且访问量比较低的情况下使用,
优点:
缺点:
针对单个服务器在访问量越来越大的情况越来越吃力的情况,我们可以考虑服务器的集群话处理。
集群的部署大大提高了服务的处理能力,同时利用Nginx提供的负载均衡机制,来分发请求,使用户的体验没有改变。
上面的集群部署是可以解决一部分的服务器压力,但是随着用户访问量的增多,集群节点增加到一定阶段的时候,其实作用就已经不是太大了,因为将所有的业务都集中在一起,造成耦合度很高,这时我们可以考虑业务的拆分。来提高系统的性能。比如将原来在一个系统里面的业务拆分为用户系统,订单系统和商品系统。也就是我们讲的垂直化拆分如下:
服务垂直化拆分后是可以大大的提高整体的服务处理能力,但是也会出现很多的冗余的代码,比如用户系统要操作订单库,要操作商品库,订单系统也有可能要操作用户库和商品库等。
优点:
缺点:
当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复用及整合的分布式调用是关键。
优点:
缺点:
针对垂直化拆分出现的问题,这时就出现了我们经常听到的SOA(面向服务的架构).什么是SOA呢?在《微服务设计》中有这么一段描述
SOA是一种设计方法,其中包括多个服务,而服务之间通过配合最终会提供一系列功能,一个服务通常以独立的形式存在于操作系统进程中,服务之间通过网络调用,而非采用进程内调用的方式进行通信。
ESB:简单来说ESB就是一根管道,用来连接各个服务节点,为了集成不同的系统,不同协议的服务,ESB要实现消息的转发解释和路由的功能,让不同的服务进行互通
微服务架构就是使用一套小服务来开发单体应用的方式或途径,每个服务都是基于单一业务能力构建,运行在自己的进程中,并且使用轻量级的机制进行通信,通常就是HTTP或者RPC,能够通过自动化部署机制来自动部署环境。这些服务可以使用不同的编程语言,不同的数据库存储 技术,并保持最低限度的集中式管理。
运维困难: 我们这二三十个服务,二三是个服务对应二三是个服务这样部署
分布式事务: 商品、交易的等等这些调用会出现调用失败,如果失败就需要回滚,这个是不是就设计到分布式事务了,本地事务就解决不了问题
定位问题:我们需要定位那个服务出现,并且需要定位具体哪服务的那台机器出现问题
里程碑 | 里程碑内容 |
---|---|
2011年10月 | 阿里巴巴完成Dubbo开源 |
2012年到2014年 | Dubbo开源社区蓬勃发展,多个互联网大厂进行封装使用课 |
2014年10月 | Dubbo停止更新 |
2017年9月 | 阿里巴巴重启Dubbo的维护和更新 |
2018年2月 | Dubbo进入Apache顶级孵化项目 |
2021年3月 | Dubbo 3.x正式进入发布倒计时 |
RPC两个核心模块:通讯(socket),序列化。
节点 | 角色说明 |
---|---|
Provider | 服务的提供方 |
Consumer | 服务的消费方 |
Registry | 服务注册与发现的注册中心 |
Monitor | 监控服务的统计中心 |
Container | 服务运行容器 |
1.服务容器负责启动,加载,运行服务提供者;
2.服务提供者在启动时,向注册中心注册自己提供的服务;
3.服务消费者在启动时,向注册中心订阅自己所需的服务;
4.在注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者;
5.服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用;
6.服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心;
解压
修改zk的配置文件
进入conf,将文件zoo_sample.cfg 改为zoo.cfg
测试zk
启动zookeeper
执行zookeeper根目录下,bin文件中的zkServer.cmd
上面的CMD窗口不要关闭,这样zookeeper就是出于运行状态了
mdb-dubbo-ann
父工程控制版本:
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.6.11
dubbo-consumer
dubbo-provider
dubbo-common
com.michstabe
michstabe-dubbo-ann
0.0.1-SNAPSHOT
michstabe-dubbo-ann
pom
Demo project for Spring Boot
1.8
3.1.8
org.projectlombok
lombok
org.apache.dubbo
dubbo-spring-boot-starter
${dubbo-version}
org.apache.dubbo
dubbo-rpc-dubbo
${dubbo-version}
org.apache.dubbo
dubbo-registry-zookeeper
${dubbo-version}
dubbo-provider
引入依赖:
org.apache.dubbo
dubbo-spring-boot-starter
org.apache.dubbo
dubbo-rpc-dubbo
org.apache.dubbo
dubbo-registry-zookeeper
增加配置
server:
port: 8002
logging:
config: classpath:logback.xml
dubbo:
application:
name: dubbo-provider
protocol:
name: dubbo
#客户端链接20880就可以访问我们的dubbo
port: 20883
registry:
address: zookeeper://127.0.0.1:2181
更改主类
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
// 因为是自动装配也可以不加这个注解
@EnableDubbo(scanBasePackages = "com.michstabe.dubbo.provider.service")
@SpringBootApplication
public class DubboProviderApplication {
public static void main(String[] args) {
SpringApplication.run(DubboProviderApplication.class);
}
}
接着增加通信端口
public interface IUserService {
User getUserById(Long id);
}
@Data
@AllArgsConstructor
@Builder
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private int age;
}
增加实现类
@DubboService// 定义一个dubbo服务
public class UserServiceImpl implements IUserService {
@Override
public User getUserById(Long id) {
User user = User.builder().id(id)
.age(12)
.name("天涯")
.build();
return user;
}
引入依赖
org.apache.dubbo
dubbo-spring-boot-starter
org.apache.dubbo
dubbo-rpc-dubbo
org.apache.dubbo
dubbo-registry-zookeeper
更改配置
server:
port: 8001
logging:
config: classpath:logback.xml
dubbo:
application:
name: dubbo-consumer
registry:
address: zookeeper://127.0.0.1:2181
更改主类
@EnableDubbo
@SpringBootApplication
public class DubboConsumeApplication {
public static void main(String[] args) {
SpringApplication.run(DubboConsumeApplication.class);
}
}
增加调用接口
public interface IUserService {
User getUserById(Long id);
}
@Data
@AllArgsConstructor
@Builder
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private int age;
}
增加业务调用处理
@RestController
public class OrderController {
@Autowired
private OrderService orderService;
@RequestMapping("/createOrder/{userId}")
public String createOrder(@PathVariable("userId") Long userId){
return orderService.createOrder(userId);
}
}
@Slf4j
@Service
public class OrderService {
// 引用对应的dubbo服务
@DubboReference
private IUserService iUserService;
public String createOrder(Long userId){
User user = iUserService.getUserById(userId);
log.info("用户用户信息:{}",user);
return "创建订单成功";
}
}
http://localhost:8001/createOrder/232
dubbo-common 存放IUserService 和User
提供端和消费端
com.michstabe
dubbo-common
0.0.1-SNAPSHOT
http://localhost:8001/createOrder/232
如果我们的服务希望既要支持dubbo协议调用,也要能支持http调用,所以,要么仍然保留SpringMVC那一套,如果不想保留那一套,就可以开启 dubbo中的rest协议。
org.apache.dubbo
dubbo-rpc-rest
dubbo:
application:
name: dubbo-provider
# 这里的协议加了s,所以可以设置多个通信协议
protocols:
p1:
name: dubbo
#客户端链接20883就可以访问我们的dubbo
port: 20883
p2:
name: rest
#客户端链接20884就可以访问我们的rest
port: 20884
@DubboService// 定义一个dubbo服务
@Path("/user")
public class UserServiceImpl implements IUserService {
@GET
@Path("/{userId}")
@Produces(MediaType.APPLICATION_JSON)
@Override
public User getUserById(@PathParam("userId") Long userId) {
User user = User.builder().id(userId)
.age(12)
.name("天涯")
.build();
return user;
}
}
在消费端增加RestTemplate
@EnableDubbo
@SpringBootApplication
public class DubboConsumeApplication {
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(DubboConsumeApplication.class);
}
}
@Slf4j
@Service
public class OrderService {
@DubboReference
private IUserService iUserService;
@Autowired
RestTemplate restTemplate;
public String createOrder(Long userId){
User user = restTemplate.getForObject("http://localhost:20884/user/232",User.class);
log.info("用户用户信息:{}",user);
return "创建订单成功";
}
}
http://localhost:8001/createOrder/232
将rest协议放到common中
修改IUserService
@Path("/user")
public interface IUserService {
@GET
@Path("/{userId}")
@Produces(MediaType.APPLICATION_JSON)
User getUserById(@PathParam("userId") Long id);
}
修改consume里面内容
@Slf4j
@Service
public class OrderService {
// 指定写协议
@DubboReference(protocol = "rest")
private IUserService iUserService;
@Autowired
RestTemplate restTemplate;
public String createOrder(Long userId){
User user = iUserService.getUserById(userId);
log.info("用户用户信息:{}",user);
return "创建订单成功";
}
}
如果我们不能确定是否是走的http,我们可以DispatcherServlet#service 里面打个端点,看是否进入
POST /user HTTP/1.1 // 请求行
Host: www.user.com
Content-Type: application/x-www-form-urlencoded
Connection: Keep-Alive
User-agent: Mozilla/5.0. // 以上是请求头
(此处必须有一空行 | // 空行分割header和请求内容
name=world // 请求体(可选,如get请求时可选)
它会将上面字符转化为字节流,然后发送给对方,对方解析的时候会根据空格、回车、换行符进行解析
这里我们可以知道他的请求头比较大,占用空间比较多。
Magic - Magic High & Magic Low (16 bits)
标识协议版本号,Dubbo 协议:0xdabb
Req/Res (1 bit)
标识是请求或响应。请求: 1; 响应: 0。
2 Way (1 bit)
仅在 Req/Res 为1(请求)时才有用,标记是否期望从服务器返回值。如果需要来自服务器的返回值,则设置为1。
Event (1 bit)
标识是否是事件消息,例如,心跳事件。如果这是一个事件,则设置为1。
Serialization ID (5 bit)
标识序列化类型:比如 fastjson 的值为6。
Status (8 bits)
仅在 Req/Res 为0(响应)时有用,用于标识响应的状态。
Request ID (64 bits)
标识唯一请求。类型为long。
Data Length (32 bits)
序列化后的内容长度(可变部分),按字节计数。int类型。
Variable Part
被特定的序列化类型(由序列化 ID 标识)序列化后,每个部分都是一个 byte [] 或者 byte
dubbo协议在Dubbo框架内使用还是比较舒服的,并且dubbo协议相比于http1.x协议,性能会更好,因为请求中没
有多余的无用的字节,都是必要的字节,所以dubbo协议成为了Dubbo框架中的默认协议。
但是dubbo协议一旦涉及到跨RPC框架,比如一个Dubbo服务要调用gPRC服务,就比较麻烦了,因为发一个dubbo
协议的请求给一个gPRC服务,gPRC服务只会按照gRPC的格式来解析字节流,最终肯定会解析不成功的。
dubbo协议虽好,但是不够通用,所以这就出现了Triple协议,Triple协议是基于HTTP2,没有性能问题,另外HTTP
协议非常通用,全世界都认它,兼容起来也比较简单,而且还有很多额外的功能,比如流式调用。
Triple 协议是 Dubbo3 推出的主力协议。Triple 意为第三代,通过 Dubbo1.0/ Dubbo2.0 两代协议的演进,以及云原生带来的技术标准化浪潮,Dubbo3 新协议 Triple 应运而生。
org.apache.dubbo
dubbo-rpc-triple
${dubbo-version}
org.apache.dubbo
dubbo-rpc-triple
dubbo:
application:
name: dubbo-provider
protocols:
p1:
name: dubbo
#客户端链接20880就可以访问我们的dubbo 20880 是默认端口
port: 20883
p2:
name: rest
#客户端链接20884就可以访问我们的rest
port: 20884
p3:
name: tri
port: 20885
引入依赖
org.apache.dubbo
dubbo-rpc-triple
调用处更改协议
@Slf4j
@Service
public class OrderService {
@DubboReference(protocol = "tri")
private IUserService iUserService;
@Autowired
RestTemplate restTemplate;
public String createOrder(Long userId){
User user = iUserService.getUserById(userId);
log.info("用户用户信息:{}",user);
return "创建订单成功";
}
}
http://localhost:8001/createOrder/232
在一些大文件传输、直播等应用场景中, consumer或provider需要跟对端进行大量数据的传输,由于这些情况下的数据量是非常大的,因此是没有办法可以在一个RPC的数据包中进行传输,因此对于这些数据包我们需要对数据包进行分片之后,通过多次RPC调用进行传输,如果我们对这些已经拆分了的RPC数据包进行并行传输,那么到对端后相关的数据包是无序的,需要对接收到的数据进行排序拼接,相关的逻辑会非常复杂。但如果我们对拆分了的RPC数据包进行串行传输,那么对应的网络传输RTT与数据处理的时延会是非常大的。
为了解决以上的问题,并且为了大量数据的传输以流水线方式在consumer与provider之间传输,因此Streaming RPC的模型应运而生。
common中引入jar
父工程:
org.apache.dubbo
dubbo-common
${dubbo-version}
common中
org.apache.dubbo
dubbo-common
更改服务端代码
@Path("/user")
public interface IUserService {
// UNARY
@GET
@Path("/{userId}")
@Produces(MediaType.APPLICATION_JSON)
User getUserById(@PathParam("userId") Long id);
// SERVER_STREAM 服务端流
default void sayHelloServerStream(String name, StreamObserver<String> response){
}
// CLIENT_STREAM / BI_STREAM 双端流
default StreamObserver<String> sayHelloStream(StreamObserver<String> response){
return response;
}
}
服务端流处理
@DubboService// 定义一个dubbo服务
public class UserServiceImpl implements IUserService {
@Override
public void sayHelloServerStream(String name, StreamObserver<String> response) {
response.onNext("hello 1");
response.onNext("hello 2");
response.onNext("hello 3");
response.onNext("hello 4");
response.onCompleted();
}
}
@Service
public class OrderService {
@DubboReference(protocol = "tri")
private IUserService iUserService;
public String createOrder(Long userId){
iUserService.sayHelloServerStream("李华", new StreamObserver<String>() {
@Override
public void onNext(String data) {
System.out.println("接收到的响应数据:" + data);
}
@Override
public void onError(Throwable throwable) {
System.err.println("异常处理");
}
@Override
public void onCompleted() {
System.out.println("响应数据完成");
}
});
return "创建订单成功";
}
}
双端流
@DubboService// 定义一个dubbo服务
public class UserServiceImpl implements IUserService {
@Override
public User getUserById(Long userId) {
User user = User.builder().id(userId)
.age(12)
.name("天涯")
.build();
return user;
}
@Override
public StreamObserver<String> sayHelloStream(StreamObserver<String> response) {
return new StreamObserver<String>() {
@Override
public void onNext(String data) {
// 接收到客户端发送过来的数据,进行处理,将结果返回
try {
Thread.sleep(3*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("接收到客户端数据:" + data);
response.onNext("服务端影响:" + data);
}
@Override
public void onError(Throwable throwable) {
}
@Override
public void onCompleted() {
System.out.println("服务端处理完毕");
}
};
}
}
public class OrderService {
@DubboReference(protocol = "tri")
private IUserService iUserService;
@Autowired
RestTemplate restTemplate;
public String createOrder(Long userId){
StreamObserver streamObserver = iUserService.sayHelloStream(new StreamObserver() {
@Override
public void onNext(Object data) {
System.out.println("接收到响应数据:" + data);
}
@Override
public void onError(Throwable throwable) {
}
@Override
public void onCompleted() {
System.out.println("接收到响应数据完毕");
}
});
streamObserver.onNext("request hello 1");
streamObserver.onNext("request hello 2");
streamObserver.onNext("request hello 3");
streamObserver.onCompleted();
return "创建订单成功";
}
}
进入application.properties配置文件所在的目录
dubbo-admin-0.5.0\dubbo-admin-server\src\main\resources\application.properties
设置zk地址
登录时候用户名秘密
更改端口
mvn clean package
找到编译后到jar包:
dubbo-admin-0.5.0\dubbo-admin-distribution\target
jar -jar xxx.jar
localhost:10010
注册中心: 127.0.0.1:2181
端口号: 10010
用户名/密码: root/root
Dubbo服务中,接口并不能唯一确定一个服务,只有接口+分组+版本号才能唯一确定一个服务。
使用场景
使用方式
使用 @DubboService 注解,添加 group 参数和 version 参数 本示例中使用"发布和调用" 中示例代码
代码处理
服务端,我们指定组合版本,然后启动两个服务,注意两个服务的端口不能相同
@DubboService(group = "group1",version = "1.0")// 定义一个dubbo服务
public class UserServiceImpl implements IUserService {
@Override
public User getUserById(Long userId) {
User user = User.builder().id(userId)
.age(12)
.name("天涯")
.build();
log.info("服务获取用户信息:{}",user);
return user;
}
修改消费端指定版本
@DubboReference(protocol = "tri",group = "group1",version = "2.0")
private IUserService iUserService;
测试,访问只会达到对应的version=“2.0” 的版本
启动时会在注册中心检查依赖的服务是否可用,不可用时会抛出异常
由于网络或服务端不可靠,会导致调用过程中出现不确定的阻塞状态(超时)
为了避免超时导致客户端资源(线程)挂起耗尽,必须设置超时时间
在服务提供者添加如下配置:
返回结果
配置原则
dubbo推荐在Provider上尽量多配置Consumer端属性:
当出现失败,自动切换并重试其它服务器,dubbo重试的缺省值是2次,我们可以自行设置
在provider提供方配置
在consume配置
并不是所有的方法都适合设置重试次数
备注: 重试是在dubbo协议下重试, tri协议下不会生效, consumer和provider同时设置重试则客户端生效
指定不同方法的重试,这是后我们需要引入xml
增加方法
public interface IUserService {
User getUserById(@PathParam("userId") Long id);
User getUserInfoById(@PathParam("userId") Long id); // 有具体实现类
}
这里用Autowired注入
//这里group就是定义提供者还是消费者
@Activate(group = "provider")
public class MyFilter implements Filter {
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
URL url = invoker.getUrl();
Class<?> anInterface = invoker.getInterface();
String simpleName = anInterface.getSimpleName();
String serviceName = invocation.getServiceName();
String methodName = invocation.getMethodName();
System.out.println("url = " + url.toFullString());
System.out.println("simpleName = " + simpleName);
System.out.println("serviceName = " + serviceName);
System.out.println("methodName = " + methodName);
// 调用下一级
Result result = invoker.invoke(invocation);
return result;
}
}
创建目录
然后在里面创建接口文件
文件内容:对应实现类的全路径
1、Dubbo系统间调用时,想传递一些通用参数,可通过Dubbo提供的扩展如Filter等实现统一的参数传递
2、Dubbo系统间调用时,想传递接口定义之外的参数,可在调用接口前使用setAttachment传递参数。
package com.michstabe.dubbo.consumer.filters;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;
@Activate(group = "consumer")
public class ConsumerContextFilter implements Filter {
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
Result result = null;
RpcContext.getClientAttachment()
.setAttachment("xid","1111111111111");
try {
//执行业务逻辑
result = invoker.invoke(invocation);
}finally {
//清理
RpcContext.getClientAttachment().clearAttachments();
}
return result;
}
}
package com.michstabe.dubbo.provider.filter;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;
import java.util.Map;
@Slf4j
@Activate(group = "provider")
public class ProviderContextFilter implements Filter {
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
//ServerAttachment接收客户端传递过来的参数
Map<String, Object> serverAttachments = RpcContext.getServerAttachment().getObjectAttachments();
log.info("ContextService serverAttachments:" + JSON.toJSONString(serverAttachments));
String xid = (String)serverAttachments.get("xid");
log.info("获取传递数据xid:{}",xid);
//执行业务逻辑
Result result = invoker.invoke(invocation);
return result;
}
}
更改pom
4.0.0
dubbo-provider
dubbo-consumer
dubbo-common
org.springframework.boot
spring-boot-starter-parent
2.5.0
com.michstabe
michstabe-dubbo-xml
0.0.1-SNAPSHOT
michstabe-dubbo-xml
pom
dubbo学习实例
1.8
3.1.8
org.projectlombok
lombok
org.apache.dubbo
dubbo-spring-boot-starter
${dubbo-version}
org.apache.dubbo
dubbo-rpc-dubbo
${dubbo-version}
org.apache.dubbo
dubbo-rpc-rest
${dubbo-version}
org.apache.dubbo
dubbo-rpc-triple
${dubbo-version}
org.apache.dubbo
dubbo-common
${dubbo-version}
org.apache.dubbo
dubbo-registry-zookeeper
${dubbo-version}
引入依赖
org.apache.dubbo
dubbo-spring-boot-starter
org.apache.dubbo
dubbo-rpc-dubbo
org.apache.dubbo
dubbo-registry-zookeeper
org.springframework.boot
spring-boot-starter
application.yml配置
server:
port: 8001
logging:
config: classpath:logback.xml
applicationContext-dubbo.xml
主类配置
@ImportResource(locations = {"classpath:applicationContext-dubbo.xml"})
@SpringBootApplication
public class DubboProviderApplication {
public static void main(String[] args) {
SpringApplication.run(DubboProviderApplication.class);
}
}
服务实现
@Slf4j
public class HelloServiceImpl implements HelloServiceAPI {
@Override
public String sayHello(String message) {
log.info("接收到消息:{}",message );
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "生产者接收到数据:" + message;
}
}
dubbo-common工程以及接口创建
public interface HelloServiceAPI {
String sayHello(String message);
}
更改applicationContext-dubbo.xml
创建工程引入依赖
org.springframework.boot
spring-boot-starter-web
com.michstabe
dubbo-common
0.0.2-SNAPSHOT
org.apache.dubbo
dubbo-spring-boot-starter
org.apache.dubbo
dubbo-rpc-dubbo
org.apache.dubbo
dubbo-registry-zookeeper
org.springframework.boot
spring-boot-starter
org.springframework.boot
spring-boot-starter-test
test
application.yml配置
server:
port: 8002
logging:
config: classpath:logback.xml
applicationContext-dubbo.xml配置
主类创建
@ImportResource(locations = {"classpath:applicationContext-dubbo.xml"})
@SpringBootApplication
public class DubboConsumeApplication {
public static void main(String[] args) {
SpringApplication.run(DubboConsumeApplication.class);
}
}
业务逻辑
@RestController
public class HelloController {
@Autowired
private HelloServiceAPI helloServiceAPI;
@GetMapping("/sayHello")
public String sayHelle(){
return helloServiceAPI.sayHello("hello everyBody");
}
}
http://localhost:8002/sayHello