分布式系统是若干独立系统的集合,但是用户使用起来像是在使用一套系统
规模的逐步扩大和业务的复杂,单台计算机扛不住双十一那样的流量,俗话说:三个臭皮匠抵一个诸葛亮
当网站流量很小的时候,我们将所有的应用(业务)放到一台服务器上,打包运行公司管理系统/超市收银系统
将大应用拆分成为小应用(一般按照业务拆分),根据不同的访问频率决定各自业务部署的服务器数量
将业务拆分后,用某种方式实现各个业务模块的远程调用和复用,这时一个好的 RPC 框架就决定了你的分布式架构的性能,怎么调用,何时调用,服务器挂了怎么办… 我们需要一个框架来帮我们解决这个问题(当然大大神可以自己写一个,但是应对大流量的成功者莫过于中国的阿里巴巴公司,顶住了淘宝双十一的流量,反观一些学校内部的选课系统,对于大流量时只有两个字——宕机)。
Dubbo是一个高性能的 RPC 框架解决了分布式中的调用问题
高性能要从底层的原理说起,既然是一个 RPC 框架,主要干的就是远程过程(方法)调用,那么提升性能就要从最关键、最耗时的两个方面入手:序列化和网络通信。
序列化:我们学习 Java 网络开发的时候知道,本地的对象要在网络上传输,必须要实现 Serializable 接口,也就是必须序列化。我们序列化的方案很多:xml、json、二进制流… 其中效率最高的就是二进制流(因为计算机就是二进制的)。然而 Dubbo 采用的就是效率最高的二进制。
网络通信:不同于 HTTP 需要进行7步走(三次握手和四次挥手),Dubbo 采用 Socket 通信机制,一步到位,提升了通信效率并且可以建立长连接,不用反复连接,直接传输数据
dubbo之前一直都作为 Alibaba 公司内部使用的框架。
Apache Dubbo(incubating)是一款高性能、轻量级的开源 Java RPC 框架,它提供了三大核心能力:面向接口的远程方法调用,
智能容错和负载均衡,以及服务自动注册和发现。
Dubbo是一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案、服务治理方案。
官网:http://dubbo.apache.org/en-us/
服务容器负责启动,加载,运行服务提供者
服务提供者在启动时,向注册中心注册自己提供的服务
服务消费者在启动时,向注册中心订阅自己所需的服务
注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者
服务消费者,从提供者地址列表中,选台提供者进行调用,如果调用失败,再选另一台调用
服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心
支持多种协议:dubbo、hessian、rmi、http、webservice、thrift、memcached、redis。
dubbo官方推荐使用 dubbo 协议。dubbo 协议默认端口 20880。
使用 dubbo 协议,spring 配置文件加入:
<dubbo:protocol name="dubbo" port="20880" />
通过调用远程方法获取用户信息
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.2.6.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.2.6.RELEASEversion>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>dubboartifactId>
<version>2.6.2version>
dependency>
package cn.edu.huat.domain;
public class User implements Serializable {
private Integer id;
private String username;
private Integer age;
//setter and getter
}
package cn.edu.huat.service;
import cn.edu.huat.domain.User;
public interface UserService {
//根据用户标识获取用户信息
User queryUserById(Integer id);
}
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;
}
}
<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-ch01-link" />
<dubbo:protocol name="dubbo" port="20880"/>
<dubbo:service interface="cn.edu.huat.service.UserService" ref="userService" registry="N/A"/>
<bean id="userService" class="cn.edu.huat.service.impl.UserServiceImpl" />
beans>
<context-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:dubbo-userservice-provider.xmlparam-value>
context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
listener>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.2.6.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.2.6.RELEASEversion>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>dubboartifactId>
<version>2.6.2version>
dependency>
<dependency>
<groupId>cn.edu.huatgroupId>
<artifactId>dubbo-ch01-linkartifactId>
<version>1.0-SNAPSHOTversion>
dependency>
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";
}
}
<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" />
<dubbo:reference id="userService" interface="cn.edu.huat.service.UserService" url="dubbo://localhost:20880" registry="N/A" />
beans>
<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>
<servlet>
<servlet-name>dispatcherServletservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:application.xml,classpath:dubbo-consumer.xmlparam-value>
init-param>
servlet>
<servlet-mapping>
<servlet-name>dispatcherServletservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
用户详情
用户表示:${user.id}
用户名称:${user.username}
用户年龄:${user.age}
注意:需要创建2个 tomcat,分别对应服务提供者以及服务消费者,然后通过服务消费者的 tomcat 进行访问。
建议将服务接口、服务模型等均放在公共包中。
每个接口都应定义版本号,区分同一接口的不同实现,如
<dubbo:service interface="com.xxx.XxxService" version="1.0" />
抽象分散在多个项目中的公共接口,实体类到一个项目中,在其他项目如服务提供者,服务消费者依赖公共的资源。
package cn.edu.huat.service;
import cn.edu.huat.domain.User;
public interface UserService {
User queryUserById(Integer id);
}
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.2.6.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.2.6.RELEASEversion>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>dubboartifactId>
<version>2.6.2version>
dependency>
<dependency>
<groupId>cn.edu.huatgroupId>
<artifactId>dubbo-ch03-link-interfaceartifactId>
<version>1.0-SNAPSHOTversion>
dependency>
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;
}
}
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.2.6.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.2.6.RELEASEversion>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>dubboartifactId>
<version>2.6.2version>
dependency>
<dependency>
<groupId>cn.edu.huatgroupId>
<artifactId>dubbo-ch03-link-interfaceartifactId>
<version>1.0-SNAPSHOTversion>
dependency>
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";
}
}
Dubbo中常用标签。分为三个类别:公用标签、服务提供者标签、服务消费者标签
<dubbo:application/>以及<dubbo:registry/>
<dubbo:registry address="ip:port" protocol="协议" />
配置暴露的服务
配置服务消费者引用远程服务
<dubbo:reference id="服务引用bean的id" interface="服务接口名" />