Dubbo
分布式基础理论
分布式系统是若干独立计算机的集合,这些计算机对于用户来说就像单个相关系统
Dubbo是阿里巴巴开源的基于 Java 的高性能 RPC(一种远程调用) 分布式服务框架(SOA),致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。
单一应用架构
当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。此时,用于简化增删改查工作量的数据访问框架(ORM)是关键。
ORM框架:当前ORM框架主要有五种:Hibernate,iBATIS,mybatis,EclipseLink,JFinal。
垂直应用架构
当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,提升效率的方法之一是将应用拆成互不相干的几个应用,以提升效率。此时,用于加速前端页面开发的Web框架(MVC)是关键。
分布式服务架构
当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复用及整合的分布式服务框架(RPC)是关键。
RPC是远程过程调用(Remote Procedure Call)——难点
分布式服务框架
不同的业务部署在同一台服务器上的时候,可以通过进程内调用
当不同的业务在不同的服务器上,A服务器,需要调用B服务器的资源的时候,就需要RPC(远程过程调用)
分布式服务框架(RPC框架)
解决的问题:简化开发
1.拆分服务,很多服务器同时跑同一个项目,这时候可能会出现,资源浪费情况。
访问量大小不同。 部分服务器访问量大,部分服务器访问量小,需要进行负载均衡。
流动计算架构
当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。此时,用于提高机器利用率的资源调度和治理中心(SOA)是关键。
SOA(面向服务的架构)Service-Oriented Architecture
RPC原理
套接字(Socket),就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。
套接字是通信的基石,是支持TCP/IP协议的路通信的基本操作单元。可以将套接字看作不同主机间的进程进行双间通信的端点,它构成了单个主机内及整个网络间的编程界面。
RPC(Remote Procedure Call)远程过程调用,简单的理解是一个节点请求另一个节点提供的服务
本地过程调用:如果需要将本地student对象的age+1,可以实现一个addAge()方法,将student对象传入,对年龄进行更新之后返回即可,本地方法调用的函数体通过函数指针来指定。
远程过程调用:上述操作的过程中,如果addAge()这个方法在服务端,执行函数的函数体在远程机器上,如何告诉机器需要调用这个方法呢?
影响RPC效率的因素:
通信的效率;
序列化和反序列化的效率,
RPC框架:
- Dubbo:国内最早开源的 RPC 框架,由阿里巴巴公司开发并于 2011 年末对外开源,仅支持 Java 语言。
- Motan:微博内部使用的 RPC 框架,于 2016 年对外开源,仅支持 Java 语言。
- Tars:腾讯内部使用的 RPC 框架,于 2017 年对外开源,仅支持 C++ 语言。
- Spring Cloud:国外 Pivotal 公司 2014 年对外开源的 RPC 框架,仅支持 Java 语言
Dubbo特性
负载均衡:寻找访问量小的服务器给用户访问
注册中心:服务的清单,所有服务都记录在注册中心,由注册中心来寻找服务
注册中心参考手册
https://dubbo.apache.org/zh/docs/v2.7/user/references/registry/
ZooKeeper安装
Dubbo推荐使用 Zookeeper 注册中心
Zookeeper 是 Apache Hadoop 的子项目,是一个树型的目录服务,支持变更推送,适合作为 Dubbo 服务的注册中心,工业强度较高,可用于生产环境,并推荐使用 。
Dubbo 支持 zkclient 和 curator 两种 Zookeeper 客户端实现:
注意:在2.7.x的版本中已经移除了zkclient的实现,如果要使用zkclient客户端,需要自行拓展
安装
下载网址:https://downloads.apache.org/zookeeper/zookeeper-3.7.0/
配置网址:https://dubbo.apache.org/zh/docs/v2.7/admin/install/zookeeper/
改配置文件
Zookeeper 的配置文件在 conf 目录下,这个目录下有 zoo_sample.cfg 和 log4j.properties,
将 zoo_sample.cfg 改名为 zoo.cfg,因为 Zookeeper 在启动时会找这个文件作为默认配置文件。
tickTime:这个时间是作为 Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳。
dataDir:顾名思义就是 Zookeeper 保存数据的目录,默认情况下,Zookeeper 将写数据的日志文件也保存在这个目录里。
dataLogDir:顾名思义就是 Zookeeper 保存日志文件的目录
clientPort:这个端口就是客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。
当这些配置项配置好后,你现在就可以启动 Zookeeper 了,启动后要检查 Zookeeper 是否已经在服务,可以通过 netstat – ano 命令查看是否有你配置的 clientPort 端口号在监听服务
Dubbo原理
提供者暴露服务的整体机制:
- 在服务提供者初始化的时候,会通过 Config 组件中的 ServiceConfig 读取服务的配置信息。这个配置信息有三种形式,分别是 XML 文件,注解(Annoation)和属性文件(Properties 和 yaml)。
- 在读取配置文件生成服务实体以后,会通过 ProxyFactory 将 Proxy 转换成 Invoker。
- 此时,Invoker 会被定义 Protocol,之后会被包装成 Exporter。
- 最后,Exporter 会发送到注册中心,作为服务的注册信息
注册中心
其主要作用如下:
- 动态载入服务
- 动态发现服务
- 参数动态调整
- 服务统一配置管理
- 提供者(Provider)启动时,会向注册中心写入自己的元数据信息(调用方式)。
- 消费者(Consumer)启动时,也会在注册中心写入自己的元数据信息,并且订阅服务提供者,路由和配置元数据的信息。
- 服务治理中心(duubo-admin)启动时,会同时订阅所有消费者,提供者,路由和配置元数据的信息。
- 当提供者离开或者新提供者加入时,注册中心发现变化会通知消费者和服务治理中心。
服务消费者首先持有远程服务实例生成的 Invoker,然后把 Invoker 转换成用户接口的动态代理引用,服务引用的入口点在 ReferenceBean
Dubbo+Zookeeper简单示例
分为三部分,interface,provider,consumer
interface
存放实体bean——必须要进行序列化操作和
implements Serializable
public class User implements Serializable {
private String name;
private Integer age;
业务接口
public interface UserService {
User qryUser(int age,String name);
}
provider
依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zengqh</groupId>
<artifactId>dubbo-service-provider</artifactId>
<version>1.0.0</version>
<packaging>war</packaging>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<!--dubbo-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</version>
</dependency>
<!--zookeeper-->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.1.0</version>
</dependency>
<!--接口依赖必须有-->
<dependency>
<groupId>com.zengqh</groupId>
<artifactId>dubbo-service-interface</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</project>
接口实现类
public class UserServiceImpl implements UserService {
@Override
public User qryUser(int age, String name) {
User user = new User(name,age);
return user;
}
}
配置文件dubbo-provider.xml
<?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-service-provider"></dubbo:application>
<!--声明dubbo使用的协议名称和端口号 -->
<dubbo:protocol name="dubbo" port="20880"/>
<!-- 指定注册中心的地址和端口号-->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<!--暴露服务接口-->
<dubbo:service interface="com.zengqh.service.UserService" ref="userService"/>
<!--加载业务接口的实现类到Spring容器中-->
<bean id="userService" class="com.zengqh.service.impl.UserServiceImpl"/>
</beans>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--监听器-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:dubbo-provider.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
consumer
依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zengqh</groupId>
<artifactId>dubbo-service-customer</artifactId>
<version>1.0.0</version>
<packaging>war</packaging>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.46</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.1.0</version>
</dependency>
<!-- 服务接口依赖-->
<dependency>
<groupId>com.zengqh</groupId>
<artifactId>dubbo-service-interface</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</project>
前端控制器
@Controller
public class UserController {
@Autowired
private UserService userService;
@RequestMapping(value = "/userDetail")
@ResponseBody
public String userDetail(Integer age, String name){
User user = userService.qryUser(age,name);
String s = JSONObject.toJSONString(user);
return s;
}
}
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="com.zengqh.controller"/>
<mvc:annotation-driven/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
dubbo-customer.xml
<?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://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<dubbo:application name="dubbo-service-customer"/>
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<!--引用远程接口服务-->
<dubbo:reference id="userService" interface="com.zengqh.service.UserService"/>
</beans>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<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-context.xml, classpath:dubbo-customer.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
Maven编译报错问题解决
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>utf-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
Dubbo理解
分布式、微服务
微服务就是,将整个工作流程划分为若干个微小的服务,各司其职。
分布式:一组独立的计算机展现给用户的是一个统一的整体,就好像是一个系统似的。
例子:餐厅有一个全能大厨,洗菜切菜炒菜一条龙,一个人完成
微服务——请两个人,分别负责洗菜,切菜,大厨只负责炒菜
分布式——再请一个大厨,同样负责洗菜切菜炒菜一条龙,两个人做相同的事情,提供给客户的还是一盘菜
Dubbo是一个RPC框架(Remote Procedure Call)远程过程调用,简单理解就是一个节点请求另外一个节点请求的服务,我们传统开发的项目是单体项目,我们可以很简单的从一个类里面,调用另外一个类的Service层服务,像这样就是一种简单的层间调用,距离很近。
我们自己做的小项目,访问量很小的时候,完全没有问题,如果是企业级的项目,当访问量变得很大的时候,这时候,我们的电脑作为服务器是不可能实现的,有时候甚至一台服务器都不能实现,需要多台服务器。
这样一来,就需要把不同的服务,分别部署到不同的服务器上面,分布式,客户有需要的时候,再从服务器进行服务调用,这就是远程过程调用,RPC,是通过网络Socket进行传输。