初始Dubbo

初始Dubbo

文章目录

一、前言

1、什么是分布式框架

​ 分布式系统是若干独立系统的集合,但是用户使用起来像是在使用一套系统

2、为什么需要分布式系统?

​ 规模的逐步扩大和业务的复杂,单台计算机扛不住双十一那样的流量,俗话说:三个臭皮匠抵一个诸葛亮

3、应用架构的发展演变
(1)单一架构

​ 当网站流量很小的时候,我们将所有的应用(业务)放到一台服务器上,打包运行公司管理系统/超市收银系统

  • 优点:开发简单,部署简单
  • 缺点:扩展不容易(怎么处理日益增长的流量),谁都改一个,维护不容易,性能提升难
(2)垂直应用架构

​ 将大应用拆分成为小应用(一般按照业务拆分),根据不同的访问频率决定各自业务部署的服务器数量

  • 优点:扩展容易
  • 缺点:页面一改,可能造成整个项目重新部署,业务和界面没有分离开,随着业务种类增加,怎么解决业务之间的互相调用问题,订单服务器和用户服务器交互效率的问题
(3)分布式架构(基于RPC:远程过程调用)

​ 将业务拆分后,用某种方式实现各个业务模块的远程调用和复用,这时一个好的 RPC 框架就决定了你的分布式架构的性能,怎么调用,何时调用,服务器挂了怎么办… 我们需要一个框架来帮我们解决这个问题(当然大大神可以自己写一个,但是应对大流量的成功者莫过于中国的阿里巴巴公司,顶住了淘宝双十一的流量,反观一些学校内部的选课系统,对于大流量时只有两个字——宕机)。

(4)Dubbo

​ Dubbo是一个高性能的 RPC 框架解决了分布式中的调用问题

  • 优点:解决了分布式系统中互相调用的问题
  • 缺点:假设有100台服务器,50台用户业务服务器,50台订单业务服务器,但是在上线后发现,用户服务器使用率很小,但是订单服务器压力很大,最佳配比应该是1:4,这时候就要求我们还有一个统一管理的调度中心

二、初识Dubbo

1、为什么Dubbo说自己性能高

​ 高性能要从底层的原理说起,既然是一个 RPC 框架,主要干的就是远程过程(方法)调用,那么提升性能就要从最关键、最耗时的两个方面入手:序列化和网络通信。

​ 序列化:我们学习 Java 网络开发的时候知道,本地的对象要在网络上传输,必须要实现 Serializable 接口,也就是必须序列化。我们序列化的方案很多:xml、json、二进制流… 其中效率最高的就是二进制流(因为计算机就是二进制的)。然而 Dubbo 采用的就是效率最高的二进制。

​ 网络通信:不同于 HTTP 需要进行7步走(三次握手和四次挥手),Dubbo 采用 Socket 通信机制,一步到位,提升了通信效率并且可以建立长连接,不用反复连接,直接传输数据

2、dubbo的发展过程

​ dubbo之前一直都作为 Alibaba 公司内部使用的框架。

  • 2011年,dubbo 被托管到了 GitHub上(开源)
  • 2014年11月发布 2.4.11 版本后宣布停止更新。此后一段时间很多公司开源了自己基于 Dubbo 的变种版本(例如当当网的 Dubbo X,网易考拉的 Dubbo K)
  • 2017年 SpringCloud 横空出世,Dubbo 感觉到压力后连续更新了几个版本
  • 2018年1月,阿里公司联合当当网将 Dubbo 和 Dubbo X 合并,发布了 2.6 版本
  • 2018年除夕夜阿里将 Dubbo 贡献给了 Apache 基金会
  • 2018除夕夜至今,Apache 维护和更新 Dubbo

三、dubbo框架

1、dubbo概述

​ Apache Dubbo(incubating)是一款高性能、轻量级的开源 Java RPC 框架,它提供了三大核心能力:面向接口的远程方法调用,
智能容错和负载均衡,以及服务自动注册和发现。

​ Dubbo是一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案、服务治理方案。

官网:http://dubbo.apache.org/en-us/

2、基本结构

在这里插入图片描述

(1)结构说明
  • 服务提供者(Provider):暴露服务的服务提供方,服务提供者在启动时,向注册中心注册自己提供的服务
  • 服务消费者(Consumer):调用远程服务的服务消费方,服务消费者在启动时,向注册中心订阅自己所需的服务,服务消费者,从提供者地址列表中,基于软负载均衡算法,选台提供者进行调用,如果调用失败,再选另一台调用
  • 注册中心(Registry):注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者
  • 监控中心(Monitor):服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心
(2)调用关系说明
  • 服务容器负责启动,加载,运行服务提供者

  • 服务提供者在启动时,向注册中心注册自己提供的服务

  • 服务消费者在启动时,向注册中心订阅自己所需的服务

  • 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者

  • 服务消费者,从提供者地址列表中,选台提供者进行调用,如果调用失败,再选另一台调用

  • 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心

3、dubbo支持的协议

​ 支持多种协议:dubbo、hessian、rmi、http、webservice、thrift、memcached、redis。

​ dubbo官方推荐使用 dubbo 协议。dubbo 协议默认端口 20880。

​ 使用 dubbo 协议,spring 配置文件加入:

<dubbo:protocol name="dubbo" port="20880" />
4、直连方式

通过调用远程方法获取用户信息

(1)创建服务提供者
A、配置POM文件
<!--Spring依赖-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.6.RELEASE</version>
</dependency>
<!--springmvc依赖-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.6.RELEASE</version>
</dependency>
<!--dubbo依赖-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>dubbo</artifactId>
    <version>2.6.2</version>
</dependency>
B、创建实体
package cn.edu.huat.domain;

public class User implements Serializable {
    private Integer id;
    private String username;
    private Integer age;
    //setter and getter
}
C、提供服务接口
package cn.edu.huat.service;

import cn.edu.huat.domain.User;

public interface UserService {
    //根据用户标识获取用户信息
    User queryUserById(Integer id);
}
D、实现服务接口
package cn.edu.huat.service.impl;

import cn.edu.huat.domain.User;
import cn.edu.huat.service.UserService;

public class UserServiceImpl implements UserService {
    @Override
    public User queryUserById(Integer id) {
        User user = new User();
        user.setId(1001);
        user.setUsername("zs");
        user.setAge(22);
        return user;
    }
}
E、配置dubbo服务提供者的核心配置文件(spring配置文件)
<?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://dubbo.apache.org/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">

    <!--服务提供者声明名称:必须保证服务名称的唯一性,它的名称是dubbo内部使用的唯一标识-->
    <dubbo:application name="dubbo-ch01-link" />

    <!--访问服务协议的名称及端口号,Dubbo官方推荐使用的是dubbo协议,默认端口号是20880
        name:指定协议的名称
        port:指定协议的端口号(默认为20880)-->
    <dubbo:protocol name="dubbo" port="20880"/>

    <!--暴露服务接口:dubbo:service
        interface:暴露服务接口的全限定类名
        ref:接口引用的实现类在spring容器中的标识
        registry:如果不使用注册中心,则值为N/A-->
    <dubbo:service interface="cn.edu.huat.service.UserService" ref="userService" registry="N/A"/>

    <!--将接口的实现类加载到spring容器中-->
    <bean id="userService" class="cn.edu.huat.service.impl.UserServiceImpl" />
</beans>
F、添加监听器(web.xml)
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:dubbo-userservice-provider.xml</param-value>
</context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
(2)创建服务消费者
A、配置POM文件
<!--Spring依赖-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.6.RELEASE</version>
</dependency>
<!--springmvc依赖-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.6.RELEASE</version>
</dependency>
<!--dubbo依赖-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>dubbo</artifactId>
    <version>2.6.2</version>
</dependency>
<!--依赖服务提供者,需要将服务提供者打成jar包-->
<dependency>
    <groupId>cn.edu.huat</groupId>
    <artifactId>dubbo-ch01-link</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
B、创建控制层
package cn.edu.huat.controller;

import cn.edu.huat.domain.User;
import cn.edu.huat.service.UserService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.annotation.Resource;

@Controller
public class UserController {
    @Resource
    private UserService userService;

    @RequestMapping("/user")
    public String userDetail(Model model, Integer id){
        User user = this.userService.queryUserById(id);
        model.addAttribute("user",user);
        return "userDetail";
    }
}
C、配置dubbo服务提供者的核心配置文件(spring配置文件)
<?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://dubbo.apache.org/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">

    <!--声明服务消费者的名称:保证唯一性-->
    <dubbo:application name="dubbo-ch02-link-consumer" />
    <!--引用远程服务接口:
            id:远程服务接口对象名称
            interface:调用远程接口的全限定类名
            url:访问服务接口的地址
            registry:不使用注册中心,值为:N/A
	-->
    <dubbo:reference id="userService" interface="cn.edu.huat.service.UserService" url="dubbo://localhost:20880" registry="N/A" />
</beans>
D、配置spring配置文件
<?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:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd 
       http://www.springframework.org/schema/context 
       https://www.springframework.org/schema/context/spring-context.xsd 
       http://www.springframework.org/schema/mvc 
       https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--扫描组件-->
    <context:component-scan base-package="cn.edu.huat.controller" />
    <!--配置注解驱动-->
    <mvc:annotation-driven />
    <!--视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/" />
        <property name="suffix" value=".jsp" />
    </bean>
</beans>
E、添加中央调度器(web.xml)
<servlet>
  <servlet-name>dispatcherServlet</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:application.xml,classpath:dubbo-consumer.xml</param-value>
  </init-param>
</servlet>

<servlet-mapping>
  <servlet-name>dispatcherServlet</servlet-name>
  <url-pattern>/</url-pattern>
</servlet-mapping>
F、显示页面
<h2>用户详情</h2>
用户表示:${user.id}<br>
用户名称:${user.username}<br>
用户年龄:${user.age}<br>

注意:需要创建2个 tomcat,分别对应服务提供者以及服务消费者,然后通过服务消费者的 tomcat 进行访问。
在这里插入图片描述

5、dubbo服务化最佳实践
(1)分包

建议将服务接口、服务模型等均放在公共包中。

(2)粒度
  • 服务接口尽可能大粒度,每个服务方法应代表一个功能,而不是某功能的一个步骤
  • 服务接口建议以业务场景为单位划分,并对相近业务做抽象,防止接口数量爆炸
  • 不建议使用过于抽象的通用接口,如:Map query(Map),这样的接口没有明确语义,会给后期维护带来不便
(3)版本

每个接口都应定义版本号,区分同一接口的不同实现,如

<dubbo:service interface="com.xxx.XxxService" version="1.0" />
6、直边方式(改造案例)

​ 抽象分散在多个项目中的公共接口,实体类到一个项目中,在其他项目如服务提供者,服务消费者依赖公共的资源。

(1)创建公共资源项目
A、添加User实体类
B、提供服务接口
package cn.edu.huat.service;

import cn.edu.huat.domain.User;

public interface UserService {
    User queryUserById(Integer id);
}
(2)创建服务提供者
A、配置POM文件
<!--Spring依赖-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.6.RELEASE</version>
</dependency>
<!--springmvc依赖-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.6.RELEASE</version>
</dependency>
<!--dubbo依赖-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>dubbo</artifactId>
    <version>2.6.2</version>
</dependency>
<!--接口依赖-->
<dependency>
    <groupId>cn.edu.huat</groupId>
    <artifactId>dubbo-ch03-link-interface</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
B、实现服务接口
package cn.edu.huat.service.impl;

import cn.edu.huat.domain.User;
import cn.edu.huat.service.UserService;

public class UserServiceImpl implements UserService {
    @Override
    public User queryUserById(Integer id) {
        User user = new User();
        user.setId(id);
        user.setUsername("dubbo");
        return user;
    }
}
C、配置dubbo服务提供者的核心配置文件(spring配置文件),同上案例
D、添加监听器(web.xml),同上案例
(3)创建服务消费者
A、配置POM文件
<!--Spring依赖-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.6.RELEASE</version>
</dependency>
<!--springmvc依赖-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.6.RELEASE</version>
</dependency>
<!--dubbo依赖-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>dubbo</artifactId>
    <version>2.6.2</version>
</dependency>
<!--接口依赖-->
<dependency>
    <groupId>cn.edu.huat</groupId>
    <artifactId>dubbo-ch03-link-interface</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
B、创建控制层
package cn.edu.huat.controller;

import cn.edu.huat.domain.User;
import cn.edu.huat.service.UserService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.annotation.Resource;

@Controller
public class UserController {
    @Resource
    private UserService userService;
    @RequestMapping("/userDetail")
    public String userDetail(Integer id, Model model){
        User user = userService.queryUserById(id);
        model.addAttribute("user",user);
        return "userDetail";
    }
}
C、配置dubbo服务提供者的核心配置文件(spring配置文件),同上案例
D、配置spring配置文件,同上案例
F、添加中央调度器(web.xml),同上案例
E、显示页面,同上案例

在这里插入图片描述

7、dubbo常用标签

​ Dubbo中常用标签。分为三个类别:公用标签、服务提供者标签、服务消费者标签

(1)公用标签
<dubbo:application/>以及<dubbo:registry/>
A、配置应用信息
<dubbo:application name ="服务的名称" />
B、配置注册中心
<dubbo:registry address="ip:port" protocol="协议" />
(1)服务提供者标签

配置暴露的服务

<dubbo:service interface="服务接口名” ref="服务实现对象bean" />
(3)服务消费者

配置服务消费者引用远程服务

<dubbo:reference id="服务引用bean的id" interface="服务接口名" />
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值