Dubbo应用

本文详细介绍了Dubbo作为一款高性能的服务框架,其核心功能包括远程方法调用、负载均衡及服务自动注册与发现等。同时对比了Dubbo与其他服务框架的特点,并提供了基于Spring Boot的Dubbo集成示例。

Dubbo

What

[阿里巴巴]开源的一款高性能优秀的服务框架(jar包),通过高性能RPC实现服务治理(整合了一些常见协议主要rpc),可以和Spring框架无缝集成。

他提供了三大核心功能:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。

dubbo:阿里

dubbox:当当(因阿里停更一段时间而产生)

Why

架构从单一进入集群时代并由SOA向下过度后,遇到了一系列问题:

1、服务器越来越多,服务URL配置管理变得复杂困难,F5单点压力也越来越大。

2、服务间依赖错综复杂,甚至分不清哪个应用要在那个应用之前启动,即便架构师也不能准确完整的描述。

3、服务的调用越来越大,服务的容量问题就暴漏出来了,这个服务需要多少机器支撑?什么时候该加服务器?

Dubbo的出现就是为了解决以上问题,他的核心服务治理图示如下:
在这里插入图片描述

应用解耦、有利于工作分工

有利于热点应用集中部署

技术原理:

技术架构:

在这里插入图片描述

Provider:暴漏服务的服务方提供
Consumer:调用远程服务的服务消费方
Registry:服务注册于发现的注册中心(外部提供zookeeper、redis)
Monitor:统计服务的调用次数和调用时间的监控中心
Container:服务运行容器

Dubbo架构简单,实现细节复杂

整体设计
在这里插入图片描述

流程描述:

启动容器-》服务提供者将对外的服务发布到注册中心-》消费者启动时去注册中心订阅自己需要的服务,根据软负载访问服务地址
异常处理:
1、服务提供这地址如发生变更,注册中心根据消费者提供的订阅信息,主动基于长连接将变更数据给消费者
2、消费者根据请求地址+软负载如果第一地址调用失败,再选另一台调用。
3、服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

Dubbo服务治理

特性描述
透明远程调用就像调用本地方法一样调用远程方法;只需简单配置,没有任何API侵入;
负载均衡机制Client端LB,可在内网替代F5等硬件负载均衡器;
容错重试机制服务Mock数据,重试次数、超时机制等;
自动注册发现注册中心基于接口名查询服务提 供者的IP地址,并且能够平滑添加或删除服务提供者;
性能日志监控Monitor统计服务的调用次调和调用时间的监控中心;
服务治理中心路由规则,动态配置,服务降级,访问控制,权重调整,负载均衡,等手动配置。
自动治理中心无,比如:熔断限流机制、自动权重调整等;

Dubbox扩展特性

支持REST风格远程调用(HTTP + JSON/XML);

支持基于Kryo和FST的Java高效序列化实现;

支持基于Jackson的JSON序列化;

支持基于嵌入式Tomcat的HTTP remoting体系;

升级Spring至3.x;

升级ZooKeeper客户端;

支持完全基于Java代码的Dubbo配置;

标品对比

描述DubboDubboXEurekaNacos
who阿里当当Netflix阿里
一致性协议CPCPAPCP+AP
健康检查Keep AliveKeep AliveClient BeatTCP/HTTP/MYSQL/Client Bea
负载均衡策略--Ribbon权重/
metadata/Selector
雪崩保护
自动注销实例支持支持支持支持
访问协议TCPTCPHTTPHTTP/DNS
监听支持支持支持支持支持
多数据中心不支持不支持支持支持
跨注册中心同步不支持不支持支持不支持
SpringCloud集成支持支持支持支持
k8s集成不支持不支持支持不支持

RPC框架功能比较:

功能HessianMontanrpcxgRPCThriftDubboDubboxSpring Cloud
开发语言跨语言JavaGo跨语言跨语言JavaJavaJava
分布式(服务治理)×××
多序列化框架支持hessian√(支持Hessian2、Json,可扩展)× 只支持protobuf)×(thrift格式)
多种注册中心×××
管理中心×××
跨编程语言×(支持php client和C server)××××
支持REST××××××
关注度
上手难度
运维成本
开源机构CauchoWeiboApacheGoogleApacheAlibabaDangdangApache

实际场景中的选择

  1. Spring Cloud : Spring全家桶,用起来很舒服,只有你想不到,没有它做不到。可惜因为发布的比较晚,国内还没出现比较成功的案例,大部分都是试水,不过毕竟有Spring作背书,还是比较看好。
  2. Dubbox: 相对于Dubbo支持了REST,估计是很多公司选择Dubbox的一个重要原因之一,但如果使用Dubbo的RPC调用方式,服务间仍然会存在API强依赖,各有利弊,懂的取舍吧。
  3. Thrift: 如果你比较高冷,完全可以基于Thrift自己搞一套抽象的自定义框架吧。
  4. Montan: 可能因为出来的比较晚,目前除了新浪微博16年初发布的,
  5. Hessian: 如果是初创公司或系统数量还没有超过5个,推荐选择这个,毕竟在开发速度、运维成本、上手难度等都是比较轻量、简单的,即使在以后迁移至SOA,也是无缝迁移。
  6. rpcx/gRPC: 在服务没有出现严重性能的问题下,或技术栈没有变更的情况下,可能一直不会引入,即使引入也只是小部分模块优化使用。

HOW

1、api:edu-dubbo-api

 ```java

class:User
public class User implements Serializable {
private Long id;
private String name;
private Date birthday;
private String sex;
private Integer age;

}
interface:IUserService
public interface IUserService {
void save(User user);
}
```

2、provider:edu-dubbo-provider

pom.xml
<dependency>
            <groupId>org.dh</groupId>
            <artifactId>edu-dubbo-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>2.7.8</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>5.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>5.1.0</version>
        </dependency>
class:interface->impl
import com.alibaba.dubbo.config.annotation.Service;
import org.dh.entiy.User;
import org.dh.service.IUserService;

@Service
public class UserServiceImpl implements IUserService {
    @Override
    public void save(User user) {
        System.out.println(user);
    }
}    
application.properties
server.port=8081

dubbo.application.name=edu-dubbo-provider
dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.protocol.port=20880
dubbo.protocol.name=dubbo
dubbo.monitor.protocol=registry

3、edu-dubbo-consumer

pom.xml
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>2.7.8</version>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.6.2</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.75</version>
        </dependency>
        <dependency>
            <groupId>org.dh</groupId>
            <artifactId>edu-dubbo-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>5.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>5.1.0</version>
        </dependency>
controller:UserController
import com.alibaba.dubbo.config.annotation.Reference;
import org.dh.entiy.User;
import org.dh.service.IUserService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;

@RestController
@RequestMapping("user")
public class UserController {
    @Reference
    private IUserService userService;
    @GetMapping("add")
    public boolean add(){
        User user = new User();
        user.setId(1L);
        user.setName("Dcrain");
        user.setAge(25);
        user.setBirthday(new Date(System.currentTimeMillis()));
        user.setSex("男");
        userService.save(user);
        return true;
    }
}
application.properties
server.port=8082

dubbo.application.name=edu-dubbo-consumer
dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.consumer.timeout=3000

4、启动服务

1)启动zookeeper

2)启动provider

3)启动consumer

4)访问:http://localhost:8082/user/add
在这里插入图片描述
在这里插入图片描述

Dubbo遇到的坑

使用过Dubbo如果没有碰到坑证明没有深交Dubbo

dubbo如何解决循环依赖的问题?
    在分布式项目中,A调用B,  B再调用A,或者A调B,B调用C,C再调用A,形成一个环路时,就会出现循环依赖的问题
    当启动A服务时,需要B服务暴露的接口,找不到就会抛异常,B服务启动时,需要同样需要依赖A服务暴露的接口,也会抛异常。
    所以我们经常在reference中配置check=false,这样在服务启动时就不会检查实例是否已经实例化。
   还可以从架构层面进行解决:
1:职责划分,把职责划分更加清晰,只允许A调B,或者B调A,不允许出现循环
2:可以使用中间间代替dubbo调用,A调用B,B异步推送数据到A 
    
为什么重写equals时一定要重写hashcode?
    一个类只重写了equals方法,不重写hashcode,那么对象equals为true(比较内容),但是hashcode为false(因为不同对象,地址不同)
    那么对于hash散列表结构的容器集合,就会出现问题。
新建一个类,重写equals的同时一定要重写hashcode方法,否则使用散列表数据结构的容器时就会出现问题,在重写equals和hashcode后,可以保证equals比较为true,hashcode比较一定为true,但是hashcode相同的两个对象,equals不一定相同。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值