一、导入dubbo的starter,主要版本要求
我这里使用的是 2.1.3
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>
//抽取的beans 与 服务接口,供消费端与提供端共同使用
<dependency>
<groupId>com.dubbo.interface</groupId>
<artifactId>StudentService</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
二、工程搭建
- 服务接口抽取,创建一个maven的jar工程
package com.cjy.dubbo.bean;
import java.io.Serializable;
public class Student implements Serializable {
private Integer id;
private String stuName;
private Integer stuAge;
private String stuEamil;
private Double stuHeight;
public Student() {
}
public Student(Integer id, String stuName, Integer stuAge, String stuEamil, Double stuHeight) {
this.id = id;
this.stuName = stuName;
this.stuAge = stuAge;
this.stuEamil = stuEamil;
this.stuHeight = stuHeight;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public Integer getStuAge() {
return stuAge;
}
public void setStuAge(Integer stuAge) {
this.stuAge = stuAge;
}
public String getStuEamil() {
return stuEamil;
}
public void setStuEamil(String stuEamil) {
this.stuEamil = stuEamil;
}
public Double getStuHeight() {
return stuHeight;
}
public void setStuHeight(Double stuHeight) {
this.stuHeight = stuHeight;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", stuName='" + stuName + '\'' +
", stuAge=" + stuAge +
", stuEamil='" + stuEamil + '\'' +
", stuHeight=" + stuHeight +
'}';
}
}
//服务接口
public interface StudentService {
public Student getStudentById(Integer id);
public Student getStudentByName(String name);
}
- 服务提供者
//1.application.properties
server.port=8082
dubbo.application.name=provider--stuService
dubbo.registry.address=106.12.xxx.1:2181
dubbo.registry.protocol=zookeeper
dubbo.protocol.port=20881 //向注册中心注册当前服务,如果起集群的话,这个端口不可重复
dubbo.protocol.name=dubbo
#监控中心,表示从注册中心中查找监控中心的地址
dubbo.monitor.protocol=registry
#dubbo.scan.base-packages=com.cjy.dubbo.service.impl --我测试的这个扫包无效。必须使用@EnableDubbo
//2. 服务实现
package com.cjy.dubbo.service.impl;
import com.alibaba.dubbo.config.annotation.Service;
import com.cjy.dubbo.bean.Student;
import com.cjy.dubbo.service.StudentService;
import org.springframework.stereotype.Component;
@Component //将服务注册进ioc容器
@Service //开启dubbo的服务注解,对外提供服务暴露
public class StudentServiceImpl implements StudentService {
@Override
public Student getStudentById(Integer id) {
return new Student(id,"张三--"+id,16,"zhangsan@126.com",180.1);
}
@Override
public Student getStudentByName(String name) {
return new Student(111,"--"+name,15,"lisiss@126.com",177.45);
}
}
//3. 开启服务,运行
@EnableDubbo //开启dubbo注解服务
@SpringBootApplication
public class TProviderApplication {
public static void main(String[] args) {
SpringApplication.run(TProviderApplication.class, args);
}
}
- 控制管理中心查看服务注册进去没
消费端搭建
- 导入与提供端一样的依赖即可。
- 工程配置
1.配置文件
server.port=9010
dubbo.application.name=consumer--stuService
dubbo.registry.address=zookeeper://106.12.xxx.1:2181
2. 调用服务
public class TestServiceImpl implements TestService {
@Reference //调用服务方实现
StudentService studentService;
@Override
public Student getStudentById(Integer id) {
return studentService.getStudentById(id);
}
@Override
public Student getStudentByName(String name) {
return studentService.getStudentByName(name);
}
}
//消费方做了一层包装
public interface TestService {
public Student getStudentById(Integer id);
public Student getStudentByName(String name);
}
//控制层调用
@RestController
public class TestController {
@Autowired
TestService testService;
@GetMapping("/stu/{id}")
public Student getStuById(@PathVariable("id") Integer id){
return testService.getStudentById(id);
}
@GetMapping("/stu/name/{name}")
public Student getStuById(@PathVariable("name") String name){
return testService.getStudentByName(name);
}
}
//主程序启动
@EnableDubbo
@SpringBootApplication
public class TConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(TConsumerApplication.class, args);
}
}
启动消费方并测试服务调用测试:http://127.0.0.1:9010/stu/1
三、dubbo配置
- 配置原则:
1.1 JVM 启动 -D 参数优先,这样可以使用户在部署和启动时进行参数重写,比如在启动时需改变协议的端口。
1.2 XML 次之,如果在 XML 中有配置,则 dubbo.properties 中的相应配置项无效。
1.3 Properties 最后,相当于缺省值,只有 XML 没有配置时,dubbo.properties 的相应配置项才会生效,通常用于共享公共配置,比如应用名。- SpringBoot与dubbo整合的三种方式:
1、导入dubbo-starter,在application.properties配置属性,使用@Service【暴露服务】使用@Reference【引用服务】,@EnableDubbo 开启基于注解的dubbo功能
2、保留dubbo xml配置文件;
导入dubbo-starter,使用@ImportResource导入dubbo的配置文件即可–>@ImportResource(locations=“classpath:provider.xml”)
3、使用注解API的方式:
将每一个组件手动创建到容器中,让dubbo来扫描其他的组件
//@Configuration
public class MyDubboConfig {
@Bean
public ApplicationConfig applicationConfig() {
ApplicationConfig applicationConfig = new ApplicationConfig();
applicationConfig.setName("provider--stuService"); //服务名称
return applicationConfig;
}
//<dubbo:registry protocol="zookeeper" address="106.12.2.1:2181"></dubbo:registry>
@Bean
public RegistryConfig registryConfig() {
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setProtocol("zookeeper");
registryConfig.setAddress("106.12.2.1:2181");
return registryConfig;
}
//<dubbo:protocol name="dubbo" port="20881"></dubbo:protocol>
@Bean
public ProtocolConfig protocolConfig() {
ProtocolConfig protocolConfig = new ProtocolConfig();
protocolConfig.setName("dubbo");
protocolConfig.setPort(20881);
return protocolConfig;
}
/**
*<dubbo:service interface="com.cjy.dubbo.service.StudentService"
ref="StudentServiceImpl" timeout="1000" version="1.0.0">
<dubbo:method name="getStudentById" timeout="1000"></dubbo:method> //为每个方法配置
</dubbo:service>
*/
@Bean
public ServiceConfig<UserService> userServiceConfig(UserService userService){
ServiceConfig<UserService> serviceConfig = new ServiceConfig<>();
serviceConfig.setInterface(StudentService.class);
serviceConfig.setRef(studentService);
serviceConfig.setVersion("1.0.0");
//配置每一个method的信息
MethodConfig methodConfig = new MethodConfig();
methodConfig.setName("getStudentById");
methodConfig.setTimeout(1000);
//将method的设置关联到service配置中,可配置多个方法
List<MethodConfig> methods = new ArrayList<>();
methods.add(methodConfig);
serviceConfig.setMethods(methods);
return serviceConfig;
}
}
xml 配置方式注意注解需要取消:
- 主程序引入配置:@ImportResource(locations=“classpath:provider.xml”)
- application.properties里面配置取消
- 取消: //@Component
//@Service() //开启dubbo的服务注解,对外提供服务暴露
<?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://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- 1、指定当前服务/应用的名字(同样的服务名字相同,不要和别的服务同名) -->
<dubbo:application name="provider--stuService"></dubbo:application>
<!-- 2、指定注册中心的位置 -->
<!-- <dubbo:registry address="zookeeper://106.12.203.1:2181"></dubbo:registry> -->
<dubbo:registry protocol="zookeeper" address="106.12.203.1:2181"></dubbo:registry>
<!-- 3、指定通信规则(通信协议?通信端口) -->
<dubbo:protocol name="dubbo" port="20882"></dubbo:protocol>
<!-- 4、暴露服务 ref:指向服务的真正的实现对象 -->
<dubbo:service interface="com.cjy.dubbo.service.StudentService"
ref="studentService" timeout="1000" version="1.0.0">
<dubbo:method name="getStudentById" timeout="1000"></dubbo:method> <!--方法调用策略设置-->
<dubbo:method name="getStudentByName" timeout="1000"></dubbo:method>
</dubbo:service>
<!--统一设置服务提供方的规则 -->
<dubbo:provider timeout="1000"></dubbo:provider>
<!-- 服务的实现,注意这里注册服务,注解需要取消 -->
<bean id="studentService" class="com.cjy.dubbo.service.impl.StudentServiceImpl"></bean>
<!-- 连接监控中心 -->
<dubbo:monitor protocol="registry"></dubbo:monitor>
</beans>
3.重试次数,失败自动切换,当出现失败,重试其它服务器,但重试会带来更长延迟。可通过 retries=“2” 来设置重试次数(不含第一次)。
重试次数配置如下:
<dubbo:service retries="2" /> //服务提供端
或
<dubbo:reference retries="2" /> //服务消费端
或
<dubbo:reference>
<dubbo:method name="findFoo" retries="2" /> //消费方,方法设置
</dubbo:reference>
- 超时时间:由于网络或服务端不可靠,会导致调用出现一种不确定的中间状态(超时)。为了避免超时导致客户端资源(线程)挂起耗尽,必须设置超时时间。
4.1 dubbo消费端配置
//1.全局超时配置
<dubbo:consumer timeout="5000" />
//2.指定接口以及特定方法超时配置
<dubbo:reference interface="com.cjy.dubbo.service.StudentService" timeout="2000">
<dubbo:method name="getStudentById" timeout="3000" />
</dubbo:reference>
4.2 dubbo服务端
全局超时配置
<dubbo:provider timeout="5000" />
指定接口以及特定方法超时配置
<dubbo:provider interface="com.cjy.dubbo.service.StudentService" timeout="2000">
<dubbo:method name="getStudentById" timeout="3000" />
</dubbo:provider>
4.3 配置原则:dubbo推荐在Provider上尽量多配置Consumer端属性
1、做服务的提供者,比服务使用方更清楚服务性能参数,如调用的超时时间,合理的重试次数,等等
2、在Provider配置后,Consumer不配置则会使用Provider的配置值,即Provider配置可以作为Consumer的缺省值。否则,Consumer会使用Consumer端的全局设置,这对于Provider不可控的,并且往往是不合理的
4.4 配置的覆盖规则:优先使用权
1) 方法级配置别优于接口级别,即小Scope优先
2) Consumer端配置 优于 Provider配置 优于 全局配置,
3) 最后是Dubbo Hard Code的配置值(见配置文档)
图形展示配置调用规则,从上至下,优先调用
- 版本号:当一个接口实现,出现不兼容升级时,可以用版本号过渡,版本号不同的服务相互间不引用。
可以按照以下的步骤进行版本迁移:在低压力时间段,先升级一半提供者为新版本再将所有消费者升级为新版本然后将剩下的一半提供者升级为新版本
老版本服务提供者配置:
<dubbo:service interface="com.cjy.dubbo.service.StudentService" version="1.0.0" />
新版本服务提供者配置:
<dubbo:service interface="com.cjy.dubbo.service.StudentService" version="2.0.0" />
老版本服务消费者配置:
<dubbo:reference id="studentService" interface="com.cjy.dubbo.service.StudentService" version="1.0.0" />
新版本服务消费者配置:
<dubbo:reference id="studentService" interface="com.cjy.dubbo.service.StudentService" version="2.0.0" />
如果不需要区分版本,可以按照以下的方式配置:
<dubbo:reference id="studentService" interface="com.cjy.dubbo.service.StudentService" version="*" />
- 注解版与xml配置比较:这些配置在注解里面都有对应的属性来配置,但是注解版的配置都是适用于类或者接口级别的,无法为某个方法指定配置,xml则可以
service注解可配置参数, Reference 注解也是一样的效果
package com.alibaba.dubbo.config.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Inherited
public @interface Service {
Class<?> interfaceClass() default void.class;
String interfaceName() default "";
String version() default "";
String group() default "";
String path() default "";
boolean export() default false;
String token() default "";
boolean deprecated() default false;
boolean dynamic() default false;
String accesslog() default "";
int executes() default 0;
boolean register() default false;
int weight() default 0;
String document() default "";
int delay() default 0;
String local() default "";
String stub() default ""; //本地存根
String cluster() default "";
String proxy() default "";
int connections() default 0;
int callbacks() default 0;
String onconnect() default "";
String ondisconnect() default "";
String owner() default "";
String layer() default "";
int retries() default 0;
String loadbalance() default "";
boolean async() default false;
int actives() default 0;
boolean sent() default false;
String mock() default "";
String validation() default "";
int timeout() default 0;
String cache() default "";
String[] filter() default {};
String[] listener() default {};
String[] parameters() default {};
String application() default "";
String module() default "";
String provider() default "";
String[] protocol() default {};
String monitor() default "";
String[] registry() default {};
}
7.本地存根:服务接口客户端本地代理类名,用于在客户端执行本地逻辑,如本地缓存等,该本地代理类的构造函数必须允许传入远程代理对象,构造函数如:public XxxServiceLocal(XxxService xxxService)
//1. 创建一个本地存根对象
package com.cjy.dubbo.service.impl;
import com.cjy.dubbo.bean.Student;
import com.cjy.dubbo.service.StudentService;
public class StudentServiceStub implements StudentService {
private StudentService studentService;
public StudentServiceStub(StudentService studentService){
this.studentService = studentService;
}
@Override
public Student getStudentById(Integer id) {
System.out.println("本地存根--------------");
return studentService.getStudentById(id);
}
@Override
public Student getStudentByName(String name) {
System.out.println("本地存根--------------");
return studentService.getStudentByName(name);
}
}
//2. 引用本地存根:在服务调用端设置
@Reference(stub = "com.cjy.dubbo.service.impl.StudentServiceStub")//指定本地存根
StudentService studentService;
//3. 测试:http://localhost:9010/stu/1
//本地存根--------------