北京尚学堂2020java_Dubbo
第一节 Dubbo简介
对RPC一个具体实现,高可用,基于Java的开源RPC框架。不仅仅具备RPC访问功能,还包含服务治理功能。
不用再像之前那样,还需要你去手写操作zookeeper的相关代码。
服务治理:哪个服务多,让他强一点,否则弱一点。
第二节 Dubbo架构讲解

Registry:注册中心
先写Provider,启动Container,注册到Registry,然后启动Consumer,订阅代理信息,创建代理对象,通过代理对象调用远程对象。monitor会做一些统计。
实线代表同步,虚线代表异步。
Dubbo完全基于Spring实现
Registry放置所有对外提供的信息,包括ip 端口 访问遵守的协议 对外提供的接口,接口中有哪些方法等等。
Consumer消费者,RPC调用者,SOA(面向服务编程)开发中也是一个项目,编写service和controller。调用远程服务实现XXXXServiceImpl中的方法
第三节 Dubbo支持的协议
1.Dubbo协议(官方推荐协议)
优点:采用NIO单一长连接,并使用线程池做并发处理请求,减少握手和加大并发效率,性能较好。长连接,会做池化处理
缺点:大文件上传时,可能出现问题(不使用Dubbo实现文件传输)
2.RMI协议
优点:JDK自带的能力
缺点:偶尔连接失败
3.Hessian协议
优点:可与原生Hessian互操作,基于HTTP协议
缺点:需要hession.jar支持 http短链接的开销大
第四节 Dubbo支持的注册中心
注册中心:保存发布的服务
- Zookeeper
有点:支持分布式,周边产品多
缺点:受限于zk软件的稳定性,zk专门分布式辅助软件 - Multicast
优点:去中心化,不需要单独安装软件
缺点:Provider、Consumer和Registry不能跨机房(路由)必须处于同一个内网中。这个不太行,有的时候可能要北京调广州的代码。 - redis
优点:支持集群,性能高 所有数据都在内存里
缺点:要求服务器时间同步,否则可能出现集群失败问题 - Simple
优点:标准RPC服务,没有兼容问题
缺点:不支持集群 
第五节 第一个Dubbo的Provider
首先在项目pom中引入需要的包 19_dubbo/rpc_dubbo/pom.xml:
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot</artifactId>
            <version>2.2.5.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.dubbo/dubbo-spring-boot-starter -->
        <!-- dubbo和SpringBoot整合使用的启动器-->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>2.7.5</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.curator/curator-recipes -->
        <!-- dubbo使用zk作为注册时,必须依赖的资源-->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>4.3.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.curator/curator-framework -->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>4.3.0</version>
        </dependency>
    </dependencies>
</dependencyManagement>
在接口中定义好接口19_dubbo/rpc_dubbo/dubbo_serviceapi/src/main/java/com/bjsxt/dubbo/service/UserService.java:
public interface UserService {
    // 保存一个User对象
    int saveUser(User user);
    // 根据姓名找User对象
    User getUserByName(String name);
}
接着在server中写好实现类19_dubbo/rpc_dubbo/dubbo_provider/src/main/java/com/bjsxt/dubbo/service/provider/UserServiceImpl.java:
这里的@Service注解是dubbo包中的,这是这个将该服务通过dubbo发布到了zookeeper上
import org.apache.dubbo.config.annotation.Service;
/**
 * 开始使用dubbo注解,做服务发布注册
 * Service - 可以实现Component注解的功能,创建当前类型的bean对象,让spring容器管理
 *  并且,可以将当前类型实现的接口作为服务,注册到注册中心中。
 */
@Service
public class UserServiceImpl implements UserService {
    @Override
    public int saveUser(User user) {
        // 模拟将user对象保存到数据库
        System.out.println("保存用户对象[" + user + "]");
        // 保存了一条数据
        return 1;
    }
    @Override
    public User getUserByName(String name) {
        // 模拟从数据库中做条件查询
        User user = new User();
        user.setName(name);
        user.setAge(24);
        user.setHobbies(Arrays.asList("开发", "睡觉", "吃"));
        return null;
    }
}
然后在spring配置中配置好zookeeper的地址19_dubbo/rpc_dubbo/dubbo_provider/src/main/resources/application.yml:
dubbo:
  application: #dubbo应用配置
    name: dubbo-first-provider # 为当前的dubbo起一个名字
  registry: #dubbo注册中心
    address: zookeeper://192.168.2.128:2181 #注册中心的访问地址
即可向zookepper自动配置服务信息。
至于zk中记录的内容:
/dubbo  # dubbo框架记录的节点
/com.bjsxt.service.UserService  # 使用dubbo发布的服务的接口名称
/providers  # 发布的服务是什么,服务提供者信息
# 具体的服务内容,下述内容是一个协议信息,只要又良好的数据转换,所有人都可以自我解读。
# 和自定义RPC框架记录rmi协议信息类似。用来描述一个服务的
# %3A -> : %2F -> / %3F -> ? %3D -> = %26 -> & %2C -> ,
/dubbo://
此外在主启动类上需要加上@EnableDubbo注解,这是启动dubbo服务的必由之路19_dubbo/rpc_dubbo/dubbo_provider/src/main/java/com/bjsxt/DubboProviderApp.java:
/**
 * EnableDubbo:会扫描当前类型所在包及所有子孙包,识别Dubbo定义的
 */
@SpringBootApplication
@EnableDubbo
public class DubboProviderApp {
    public static void main(String[] args) {
        SpringApplication.run(DubboProviderApp.class, args);
    }
}
第七节 完成Dubbo的Consumer
引入依赖,包括serviceapi、springboot和dubbo的:19_dubbo/rpc_dubbo/dubbo_consumer/pom.xml
<dependencies>
    <dependency>
        <groupId>com.bjsxt</groupId>
        <artifactId>dubbo_serviceapi</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <!-- springboot的核心启动器,可以通过这个资源库实现springboot环境的初始化-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <!-- 就是一套核心启动器,没有tomcat还要维护端口之类乱七八糟的-->
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo-spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.curator</groupId>
        <artifactId>curator-recipes</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.curator</groupId>
        <artifactId>curator-framework</artifactId>
    </dependency>
</dependencies>
在consumser中写控制器类19_dubbo/rpc_dubbo/dubbo_consumer/src/main/java/com/bjsxt/controller/UserController.java:
@Controller
public class UserController {
    @Autowired
    private UserService userService;
    // 新增用户
    @RequestMapping("/saveUser")
    @ResponseBody
    public Object saveUser(User user) {
        // save方法返回map,内部存储code和msg,code=200 成功 其他为失败
        Map<String,Object> result = userService.save(user);
        return result;
    }
    // 根据姓名查询用户
    @RequestMapping("/getUser")
    @ResponseBody
    public User getUserByName(String name) {
        // 服务直接返回查询到的用户对象
        return userService.getUserByName(name);
    }
}
consumer也需要服务的接口,不过这里的接口不是公共的接口,而是SpringMVC中的接口19_dubbo/rpc_dubbo/dubbo_consumer/src/main/java/com/bjsxt/service/UserService.java:
public interface UserService {
    // 保存用户数据
    Map<String, Object> save(User user);
    // 根据用户姓名查询用户对象
    User getUserByName(String name);
}
然后该服务的实现需要用到远程提供的服务19_dubbo/rpc_dubbo/dubbo_consumer/src/main/java/com/bjsxt/service/impl/UserServiceImpl.java:
其中最重要的就是@Reference注解,它代表了项目和dubbo的链接,它表示需要通过dubbo在远程拿到代理对象才能使用。不得不说,太方便了!amazing!
/**
 * 当前类型是consumer消费者的本地服务实现
 * 使用spring提供的service注解,保证当前类型被spring容器管理即可
 * 它不需要去注册服务
 */
@Service
public class UserServiceImpl implements UserService {
    // 服务标准接口,duboo-spring-boot-starter会访问zk,查询远程服务信息,并创建一个proxy代理对象。
    // 说明当前的属性需要dubbo来初始化,代表需要根据当前类型访问zk,查询可使用的服务信息,并创建代理对象,注入。
    @Reference
    private com.bjsxt.dubbo.service.UserService userService;
    /**
     * 调用远程dubbo provider提供的服务,实现用户的保存
     * @param user
     * @return
     */
    @Override
    public Map<String, Object> save(User user) {
        // 调用远程服务逻辑
        int i = userService.saveUser(user);
        Map<String, Object> result = new HashMap<>();
        result.put("code", i > 0 ? 200:500);
        result.put("msg", i > 0 ? "新增用户成功": "新增用户失败");
        return result;
    }
    /**
     * 调用远程dubbo provider提供的服务,实现用户的查询
     * @param name
     * @return
     */
    @Override
    public User getUserByName(String name) {
        return userService.getUserByName(name);
    }
}
然后就是用19_dubbo/rpc_dubbo/dubbo_consumer/src/main/java/com/bjsxt/DubboConsumerApp.java来启动它,千万别忘了@EnableDubbo注解
@SpringBootApplication
@EnableDubbo
public class DubboConsumerApp {
    public static void main(String[] args) {
        SpringApplication.run(DubboConsumerApp.class, args);
    }
}
第八节 负载均衡
8.1 开启两个项目
dubbo:
  application:  # dubbo应用的配置
    name: dubbo-first-provider    # 为当前的dubbo应用起一个名字
  registry:   # dubbo注册中心
    address: zookeeper://192.168.2.129:2181  # 注册中心的方式地址
    timeout: 50000
  protocol:  # dubbo服务发布的时候,协议配置
    port: 20881  # 服务端口, 默认20880,现在新开一个端口叫20881
    name: dubbo  # 使用的协议名称, 默认dubbo协议。
  provider:
    loadbalance: roundrobin
然后新建一个类来启动它19_dubbo/rpc_dubbo/dubbo_consumer/src/main/java/com/bjsxt/DubboConsumerApp20881.java:
@SpringBootApplication
@EnableDubbo
public class DubboConsumerApp20881 {
    public static void main(String[] args) {
        SpringApplication.run(DubboConsumerApp20881.class, args);
    }
}
8.2 负载均衡
所谓负载均衡就是设置集群的访问规则
集群:一模一样的内容部署多次形成的整体称为集群。
roundrobin:轮询
leastActive:一开始全部设置为1,活跃数相同的随机,不同的活跃数高的放前面
consistentHash:一致性hash,相同的参数总是发到一个提供者。
直接在server的service的实现类的注解上加即可:
@Service(loadbalance = "roundrobin", weight = 3) 
public class UserServiceImpl implements UserService {
    @Override
    public int saveUser(User user) {
同样的,消费者的Reference注解也可以19_dubbo/rpc_dubbo/dubbo_consumer/src/main/java/com/bjsxt/service/impl/UserServiceImpl.java:
@Service
public class UserServiceImpl implements UserService {
    // 服务标准接口,duboo-spring-boot-starter会访问zk,查询远程服务信息,并创建一个proxy代理对象。
    // 说明当前的属性需要dubbo来初始化,代表需要根据当前类型访问zk,查询可使用的服务信息,并创建代理对象,注入。
    @Reference(loadbalance = "roundrobin")
    private com.bjsxt.dubbo.service.UserService userService;
然后也可以在配置文件上改:
dubbo
  provider:
    loadbalance: roundrobin
                    
                
                
            
        
浙公网安备 33010602011771号