尚硅谷DUBBO笔记
学习链接:https://www.bilibili.com/video/BV1ns411c7jV?spm_id_from=333.337.search-card.all.click
一、MAVEN工程
公共接口 gmall-interface
接口包含bean对象,service接口
例如
Provider
包含接口的实现类,不包含接口,接口写在公共API中
接口和Bean对象的引入在pom.xml中引入实现
<dependency>
<groupId>com.atguigu.gmall</groupId>
<artifactId>gmall-interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
引入dubbo依赖
<!-- https://mvnrepository.com/artifact/com.alibaba/dubbo -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</version>
</dependency>
编写provider.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">
<!-- 1.指定当前服务/应用的名字(同样的服务名字相同,不要和别的服务器同名 -->
<dubbo:application name="userserviceprovider"></dubbo:application>
<!-- 2/指定注册中心的位置-->
<dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry>
<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"></dubbo:registry>
<!-- 3.指定通信规则(通信协议和通信端口)-->
<dubbo:protocol name="dubbo" port="20880"></dubbo:protocol>
<!-- 4.暴露服务 ref:指向服务的真正的实现对象-->
<dubbo:service interface="com.atguigu.gmall.service.UserService"
ref="userServiceImpl"></dubbo:service>
<bean id="userServiceImpl" class="com.atguigu.gmall.service.impl.UserServiceImpl"></bean>
</beans>
实现类无需做改动,正常完成
public class UserServiceImpl implements UserService {
public List<UserAddress> getUserAddressList(String userId) {
System.out.println("UserServiceImpl.....old...");
// TODO Auto-generated method stub
UserAddress address1 = new UserAddress(1, "北京市昌平区宏福科技园综合楼3层", "1", "李老师", "010-56253825", "Y");
UserAddress address2 = new UserAddress(2, "深圳市宝安区西部硅谷大厦B座3层(深圳分校)", "1", "王老师", "010-56253825", "N");
/*try {
Thread.sleep(4000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
return Arrays.asList(address1,address2);
}
}
Consumer
包含接口的实现类,不包含接口,接口写在公共的API中
接口和Bean对象的引入在pom.xml中引入实现
<dependency>
<groupId>com.atguigu.gmall</groupId>
<artifactId>gmall-interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/dubbo -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</version>
</dependency>
编写consumer.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"
xmlns:context="http://www.springframework.org/schema/context"
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://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 扫描包注解-->
<context:component-scan base-package="com.atguigu.gmall.service.impl"></context:component-scan>
<dubbo:application name="userserviceprovider"></dubbo:application>
<dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry>
<!-- 声明需要调用的远程服务的接口:生成远程服务代理-->
<dubbo:reference interface="com.atguigu.gmall.service.UserService"
id="userService" check="false">
</dubbo:reference>
</beans>
实现类
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
UserService userService;
public List<UserAddress> initOrder(String userId) {
System.out.println("用户id,"+userId);
// 1、查询用户的收货地址
List<UserAddress> addressList = userService.getUserAddressList(userId);
return addressList;
}
}
二、SPRINBG-BOOT工程
github网址:https://github.com/apache/dubbo-spring-boot-project
依赖位置
公共接口
UserAddress
public class UserAddress implements Serializable {
private Integer id;
private String userAddress; //用户地址
private String userId; //用户id
private String consignee; //收货人
private String phoneNum; //电话号码
private String isDefault; //是否为默认地址 Y-是 N-否
public UserAddress() {
super();
// TODO Auto-generated constructor stub
}
public UserAddress(Integer id, String userAddress, String userId, String consignee, String phoneNum,
String isDefault) {
super();
this.id = id;
this.userAddress = userAddress;
this.userId = userId;
this.consignee = consignee;
this.phoneNum = phoneNum;
this.isDefault = isDefault;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserAddress() {
return userAddress;
}
public void setUserAddress(String userAddress) {
this.userAddress = userAddress;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getConsignee() {
return consignee;
}
public void setConsignee(String consignee) {
this.consignee = consignee;
}
public String getPhoneNum() {
return phoneNum;
}
public void setPhoneNum(String phoneNum) {
this.phoneNum = phoneNum;
}
public String getIsDefault() {
return isDefault;
}
public void setIsDefault(String isDefault) {
this.isDefault = isDefault;
}
}
OrderService
public interface OrderService {
public List<UserAddress> initOrder(String userId);
}
UserService
public interface UserService {
/**
* 按照用户id返回所有的收货地址
* @param userId
* @return
*/
public List<UserAddress> getUserAddressList(String userId);
}
Provider
pom.xml
<!-- Dubbo Spring Boot Starter -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.8</version>
</dependency>
<dependency>
<groupId>com.atguigu.gmall</groupId>
<artifactId>gmall-interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
application.properties
dubbo.application.name=user-service-provider
dubbo.registry.address=127.0.0.1:2181
dubbo.registry.protocol=zookeeper
dubbo.protocol.name=dubbo
dubbo.protocol.port=20881
dubbo.monitor.protocol=registry
实现类
@DubboService注解的作用:暴露服务,这样就不用在xml文件中配置。
@DubboService
@Service
public class UserServiceImpl implements UserService {
public List<UserAddress> getUserAddressList(String userId) {
System.out.println("UserServiceImpl.....old...");
// TODO Auto-generated method stub
UserAddress address1 = new UserAddress(1, "北京市昌平区宏福科技园综合楼3层", "1", "李老师", "010-56253825", "Y");
UserAddress address2 = new UserAddress(2, "深圳市宝安区西部硅谷大厦B座3层(深圳分校)", "1", "王老师", "010-56253825", "N");
return Arrays.asList(address1,address2);
}
}
springboot主程序
@EnableDubbo注解的作用:开启基于注解的dubbo功能
@EnableDubbo //开启基于注解的dubbo功能
@SpringBootApplication
public class BootUserServiceProviderApplication {
public static void main(String[] args) {
SpringApplication.run(BootUserServiceProviderApplication.class, args);
}
}
Consumer
springboot勾选spring web,导入web相关的依赖
<dependency>
<groupId>com.atguigu.gmall</groupId>
<artifactId>gmall-interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- Dubbo Spring Boot Starter -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.8</version>
</dependency>
application.properties
server.port=8081
dubbo.application.name=consumer
dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.monitor.protocol=registry
实现类
@DubboReference注解的作用:引用服务
@Service
public class OrderServiceImpl implements OrderService {
//@Autowired
@DubboReference
UserService userService;
public List<UserAddress> initOrder(String userId) {
System.out.println("用户id,"+userId);
// 1、查询用户的收货地址
List<UserAddress> addressList = userService.getUserAddressList(userId);
return addressList;
}
}
控制器
@Controller
public class OderController {
@Autowired
OrderService orderService;
@ResponseBody
@RequestMapping("/initOrder")
public List<UserAddress> initOrder(@RequestParam("uid")String userId){
return orderService.initOrder(userId);
}
}
springboot主程序
@EnableDubbo
@SpringBootApplication
public class BootOrderServiceConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(BootOrderServiceConsumerApplication.class, args);
}
}
支持
面向接口代理的高性能RPC调用
只能负载均衡
服务自动注册与发现
高度可拓展能力
运行流量调度
可视化的服务治理和运维
工作原理
三、启动zookeeper
第一次启动会缺少zoo.config
需要将zoo_sample.cfg复制一份改名为zoo.cfg
打开zoo.cfg 修改配置
打开zkServer
启动成功
启动zkCli服务器
四、启动dubbo管理控制台
前提: 打开zookeeper
进入dubbo github网站
https://github.com/apache/dubbo
切换至master-0.2.0
检查该文件中resources目录下的application.properties文件的配置
相同的话,跳到dubbo-admin文件夹目录,在该页面打开cmd ,mvn clean package生成target文件
复制target中的jar包
放在自己想放的目录下,并在该目录下使用cmd命令行运行
java -jar dubbo-admin-0.0.1-SNAPSHOT.jar
浏览器打开localhost:7001
登录账号 root 密码 root
dubbo 2.6是jar包 25.以前是war包
五 、案例
UserService 比较常用,总不能一直把UserService和bean放到别的module中,所以分包
为了使得orderservice调用方法,使用dubbo改造
springboot整合
springboot 暴露服务
用注解来配置
@DubboService 暴露服务
主程序中开启 @EnableDubbo
启动的时候出现了错误,提示缺少包,加入依赖
中间也因为加入依赖等级太高而失败,注意zoo版本和这个的匹配
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.12.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.12.0</version>
</dependency>
使用接口用使用注解的方式
@DubboReference
三大步
1、导入dubbo
2、application.properties中写入dubbo配置
3、暴露服务使用 @DubboService注解 消费服务使用@Reference注入
六 、配置
1、配置优先级
2、启动检查
官方文档:https://dubbo.apache.org/zh/docs/advanced/preflight-check/
正常情况下,当注册中心没有提供者时,启动消费者,消费者程序就会报错。
启动检查便是来解决这个问题的。
- 默认情况下,check=“true”
- 关闭启动检查,check=“false”,消费者跳过检查提供者,只有在调用的时候才去注册中心检查服务
示例:
在xml文件中设置false,为一种服务配置
配置所有的服务都不检查
dubbo:consumer的其他配置
官方文档:https://dubbo.apache.org/zh/docs/references/xml/dubbo-consumer/
主程序
package com.atguigu.gmall;
import com.atguigu.gmall.service.OrderService;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.io.IOException;
public class MainApplication {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("consumer.xml");
System.out.println("调用完成");
try {
System.in.read();
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果为 调用完成
如果不设置check=false ,则报错
设置check=false的方式
springboot中 @DubboReference(version = 1.0.0 , check = false)
3、超时&配置覆盖关系
解决问题:消费方使用提供方的方法,可能提供方的方法要使用很长时间,如果很长时间都没返回,导致大量线程阻塞,会引起性能下降
可以指定超时属性,如果没有反应,就立即终止,不让线程阻塞
超时说明
- 单位毫秒
- 未设置,默认值时1000ms,即1s
消费者配置超时
配置优先级
xml配置官方文档:https://dubbo.apache.org/zh/docs/references/configuration/xml/
- 精准优先:方法级优先,接口级次之,全局配置再次之。
- 消费者设置优先:如果级别一样,则消费方优先,提供方次之。
消费者方法 > 提供者方法 > 消费者接口 > 提供者接口 > 消费者全局 > 提供者全局
4、重试次数
说明
retries=“”,重试次数,不包含第一次调用,0代表不重试
原则
幂等函数设置重试次数【查询、删除、修改,即每次运行都是相同的效果】
非幂等函数不能设置重置次数【新增】
多个提供方
当有多个提供方提供相同的功能的时候,如果重试失败,会换下一次提供方,默认时轮询
5、多版本
官方文档:https://dubbo.apache.org/zh/docs/advanced/multi-versions/
作用
实现灰度发布
实现方式
提供方写多个实现类,并配置版本号
提供方
版本1配置
版本2配置
消费方
调用版本1 version=“1.0.0”
调用版本2 version=“2.0.0”
随机调用版本 *
6、本地存根
官方文档:https://dubbo.apache.org/zh/docs/advanced/local-stub/
7、与Springboot整合的三种方式
1)、导入dubbo-starter,在application.properties配置属性,使用@Service【暴露服务】使用@Reference【引用服务】
前提:开启注解的dubbo功能
1、在启动程序中写@EnableDubbo
2、或者在配置中写 dubbo.scan.base-packages=com.atguigu.gmall
2)、保留dubbo xml配置文件
方法:
导入dubbo-starter。使用@ImportResource导入dubbo配置文件即可
目的:
实现方法级的精准配置
3)使用注解API的方式
将每一个组件手动创建到容器中
API配置官方文档:https://dubbo.apache.org/zh/docs/references/configuration/api/
注解配置官方文档:https://dubbo.apache.org/zh/docs/references/configuration/annotation/
(建议看API文档
七、高可用
高可用:通过设计,减少系统不能提供服务的时间
1、zookeeper宕机和Dubbo直连
问题:
1)zookeeper宕机了,消费者还能不能调用服务提供者?
能,因为有本地缓存保持通讯
2)没有zookeeper,可以调用服务提供者吗?
可以,dubbo可以直连服务提供者
2、负载均衡模式
官方文档:https://dubbo.apache.org/zh/docs/advanced/loadbalance/
缺省为 random
随机调用
1)基于权重的随即负载均衡机制
根据权重值得到每个Provider的概率,进行有概率的调用
2)基于权重的轮询负载均衡机制
根据权重,分配每个provider的概率,并通过轮询的方式科学地实现概率
3)最少活跃数-负载均衡机制
根据上一次provider的反应速度,选择最快的provider
4)一致性hash-负载均衡机制
根据哈希结果进入,
消费端设置
轮询机制配置
加权轮询配置
消费者 @Reference(loadbalance=“random”)
1) 静态设置 在提供者注解中设置@Service(weight= “”)
2) 动态设置 在控制台
3、服务降级
当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理或换种简单的方式处理,从而释放服务器资源以保证核心交易正常运作或高效运作。
可以通过服务降级功能临时屏蔽某个出错的非关键服务,并定义降级后的返回策略。
方法
在消费者配置
屏蔽:消费方对该服务的方法调用都直接返回 null 值,不发起远程调用。
容错:消费方对该服务的方法调用在失败后,再返回 null 值,不抛异常。
4、服务容错&Hystrix
集群容错文档:https://dubbo.apache.org/zh/docs/advanced/fault-tolerent-strategy/
缺省为 failover 重试
集群容错模式
方式
整合hystrix
1、配置spring-cloud-starter-netflix-hystrix
针对 消费者 和 提供者
spring boot官方提供了对hystrix的集成,直接在pom.xml里加入依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId> <version>1.4.4.RELEASE</version>
</dependency>
然后在Application类上增加@EnableHystrix来启用hystrix starter:
@SpringBootApplication
@EnableHystrix
public class ProviderApplication {
2、配置Provider端
在Dubbo的Provider上增加@HystrixCommand配置,这样子调用就会经过Hystrix代理。
@Service(version = "1.0.0")
public class HelloServiceImpl implements HelloService {
@HystrixCommand(commandProperties =
{@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"),
@HystrixProperty(name ="execution.isolation.thread.timeoutInMilliseconds", value = "2000") })
@Override
public String sayHello(String name)
{ // System.out.println("async provider received: " + name);
// return "annotation: hello, " + name;
throw new RuntimeException("Exception to show hystrix enabled.");
}
}
3、配置Consumer端
对于Consumer端,则可以增加一层method调用,并在method上配置@HystrixCommand。当调用出错时,会走到fallbackMethod = "reliable"的调用里。
@Reference(version = "1.0.0")
private HelloService demoService;
@HystrixCommand(fallbackMethod = "reliable")
public String doSayHello(String name) {
return demoService.sayHello(name); }
public String reliable(String name)
{ return "hystrix fallback value";}
原理
待补充…