开始时间:2022-03-09
课程链接:Dubbo入门
分布式
单一应用架构
当网站流量很小时, 应用规模小时, 只需一个应用,将所有功能都部署在一起,以减少部署服务器数量和成本。
这种结构的应用适合小型系统,小型网站,或者企业的内部系统,用户较少,请求量不大,对请求的处理时间没有太高的要求。 将所有功能都部署到一个服务器,简单易用。
缺点:
1、性能扩展比较困难
2、不利于多人同时开发
3、不利于升级维护
4、整个系统的空间占用比较大
分布式应用架构
将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,分布式系统将服务作为独立的应用,实现服务共享和重用。
分布式系统
分布式系统是若干独立计算机(服务器) 的集合,这些计算机对于用户来说就像单个相关系统, 分布式系统(distributed system)是建立在网络之上的服务器端一种结构。分布式系统中的计算机可以使用不同的操作系统,可以运行不同应用程序提供服务(微服务),将服务分散部署到多个计算机服务器上。
如果某些业务需要更多的服务器,那就再加上几台服务器。维护更加方便
例如我们自己写的Servlet,部署在Tomcat上,
如果只有一个Project,那么处理的时候url传递不需要写完整路径名
但如果我有不同的project,每个project中布置在一个Tomcat上,在一个project中调用另一个project的Servlet就需要加完整路径名了。
微服务之间的访问,使用Dubbo来实现。
Remote Procedure Call(RPC协议)
RPC 【Remote Procedure Call】 是指远程过程调用, 是一种进程间通信方式,是一种技术思想,而不是规范。 它允许程序调用另一个地址空间(网络的另一台机器上)的过程或函数,而不用开发人员显式编码这个调用的细节。
调用本地方法和调用远程方法一样。
RPC 的特点
- 简单:使用简单,建立分布式应用更容易。
- 高效:调用过程看起来十分清晰,效率高。
- 通用:进程间通讯的方式,有通用的规则。
RPC原理
左边是client客户端,右边是server服务端
- client 调用远程服务,调用client stub将方法和参数组装成可以进行网络传输的消息体(序列化的过程)
- client stub找到提供远程服务的地址,并将消息发送过去
- server stub接受到client stub发过来的数据,然后进行反序列化,根据反序列化中的方法,参数等信息调用本地方法
-
server stub调用方法,拿到执行结果后,将结果序列化发送回client
client的stub再反序列化为Java对象,得到最终结果
Dubbo
Dubbo 是一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案、 服务治理方案。
三大核心能力:
- 面向接口的远程方法调用,(远程调用)
- 智能容错和负载均衡,(负载均衡)
- 服务自动注册和发现(服务管理)
面向接口代理:调用接口的方法,在 A 服务器调用 B 服务器的方法, 由 dubbo 实现对 B 的调用,无需关心实现的细节(透明),就像 MyBatis 访问 Dao 的接口,可以操作数据库一样。不用关心 Dao 接口方法的实现。
Dubbo基本架构
- Container: 服务运行容器,负责加载、运行服务提供者。必须。
- Provider:提供服务,比如我写了一个Servlet,那么这个就是提供者,并向注册中心注册自己提供的服务 必须。
- Registry:相当于目录服务,服务提供者有很多家,注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者 非必须。
- Consumer:消费者,选择调用远程服务的服务消费方, 服务消费者在启动时,向注册中心订阅自己所需的服务, 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。必须。
- Monitor:监控中心,服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心 非必须
底层的实现还是通过了动态代理机制
调用端访问服务提供端的代理对象,代理对象再访问服务端的对象
代理是由Dubbo框架创建的。
Dubbo协议
默认端口号20880 (阿里巴巴0)
采用单一长连接和异步通信,适合于小数据量大并发的服务调用,或者是消费者机器数远大于服务提供者机器数(淘宝本身就是)
网络通信默认使用的是netty
不适合用于传送大数据量的服务,比如传文件和视频
长连接:建好通道,大家都用这一个,适合传数据量小的数据
短连接:随用随建,适合数据量大的数据(用了就释放)
spring配置文件中写
使用公共接口作为独立项目
假设一个公司做生活服务类业务,A部门负责天气资讯,B部门负责影视咨询,需要在公司网站同时提供两种服务,作为网站(公共服务部门)开发人员需要使用A和B两个小组不同服务内容。使用A组和B组两个服务提供者的接口。
这里就不贴代码了,仅仅描述主要步骤
公共部门
设置dubboInterface包,创建实体类beans包:电影和天气对象,定义实体类需要实现序列化接口
创建service包用来定义接口
定义好接口后,我们需要把整个包打包成一个jar包(存放好接口信息)
Provider
创建dubbointerfaceImpl包,用来实现接口(实际中应该是两个部门分别实现接口,这里写成一个project)
Provider实现步骤:
新建web应用-导入jar包(这里没有用maven配置)主要需要的几个包时
- dubbo框架的实现jar:dubbo-2.5.3.jar
- 网络通信的jar:netty.jar
- 动态代理的相关jar:Javassist.jar
- spring相关的jar
- 加入接口的定义jar:dubboInterface.jar
- 定义服务的实现类
- 定义spring的配置文件:声明服务名称;暴露服务提供者的接口;声明服务接口的实现类对象;
我们写dubbo的配置文件
声明服务名称
访问服务的协议名称,端口
暴露服务提供者的接口,消费者就调用此接口的方法
<dubbo:service interface="BUPT.service.WeatherService"
ref="weatherService" registry="N/A"/>
声明服务接口的实现类对象
在电影的工程中再重复上面的声明
- 定义测试类
- 修改web.xml,注册spring的监听器
- 导出接口和相关的类为一个jar包,供给消费者使用
消费者
步骤:
新建Java项目
导入jar包:
dubbo框架的实现jar:dubbo-2.5.3.jar
网络通信的jar:nett.jar
动态代理相关jar:javassist.jar
spring相关的jar:spring-*.jar
服务提供者接口的定义jar:05-dubboInterface.jar
定义spring配置文件:consume.xml
声明服务的名称
<dubbo:reference interface="BUPT.service.WeatherService"
id="remoteWeatherService" url="dubbo://localhost:20880"/>
声明要用的服务
<bean id="invokeService" class="BUPT.client.InvokeService">
<property name="remoteWs" ref="remoteWeatherService"/>
</bean>
常用标签
提供者是dubbo:service
消费者是dubbo:reference
公用标签
A、 配置应用信息
B、 配置注册中心
注册中心
- 对于服务提供方,它需要发布服务,而且由于应用系统的复杂性,服务的数量、类型也不断膨胀;
- 对于服务消费方,它最关心如何获取到它所需要的服务,而面对复杂的应用系统,需要管理大量的服务调用。
- 而且,对于服务提供方和服务消费方来说,他们还有可能兼具这两种角色,即需要提供服务,有需要消费服务。
- 通过将服务统一管理起来,可以有效地优化内部应用对服务发布使用的流程和管理。服务注册中心可以通过特定协议来完成服务对外的统一。
注册中心工作方式
运行顺序:注册中心-dubbo服务(向注册中心进行登记:IP、端口、服务名称【接口名】)-消费者访问注册中心,服务订阅(登记)-注册中心将对应服务的信息发送给消费者-消费者拿到地址(负载均衡机制)-消费者访问dubbo具体服务
注册中心每一段时间会发送请求验证dubbo是否工作,若没有响应,则认为dubbo不能用,会删除对应的dubbo服务登记信息。然后推送新的dubbo服务信息和有问题的dubbo信息推送给消费者,消费者就可以访问新的,可用的dubbo服务地址
zookeeper的使用
provider端
我们安装好zookeeper后,找到两个jar包
zkclient以及zookeeper两个jar包
拷贝到对应的目录下
然后在spring的配置文件中,还需要声明注册中心的位置
暴露服务提供者的接口,现在有了注册中心
<dubbo:service interface="BUPT.service.WeatherService"
ref="weatherService"/>
消费者端
添加相关jar包
配置文件中声明注册中心的地址
配置参考位置
<dubbo:reference interface="BUPT.service.WeatherService"
id="remoteWeatherService"
由于有了zookeeper,所以不需要再加上url地址了
负载均衡
- 集群是一种计算机系统,是一种服务器结构。把一组多个计算机,包括硬件和软件组织在一个网络中。相互连接起来共同完成某个工作。对用户来说使用的是一个计算机,集群对用户是透明的。
- 负载均衡:负载均衡是以集群为前提的。英文名称为Load Balance,其意思就是将负载(工作任务)进行平衡、分摊到多个操作单元上进行执行。
当访问量增大,单个处理单元满足不了负载需求,网络应用流量将要出现瓶颈时,负载均衡才能起到作用。负载均衡就是为了避免单个服务器响应同一请求,容易造成服务器宕机、崩溃等问题
负载均衡两层含义:
- 首先,单个重负载的工作分配到多台服务器做并行处理,每个服务器处理结束后,将结果汇总,返回给用户,系统处理能力大幅度提高,这是集群(cluster)技术带来的优势。
- 第二层含义是:大量的并发访问或数据流量分担到多台服务器分别处理==,减少用户等待响应的时间==。每个访问分配给不同的服务器处理。
Dubbo负载均衡策略
Random LoadBalance
Dubbo默认采用的一种负载均衡策略。
随机,按权重设置随机概率。
在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重。
比如服务器有10台,那么Dubbo随机生成1-10的数字,将业务分配到对应数字的服务器上进行处理
RoundRobin LoadBalance
加权轮询负载均衡,按公约后的权重设置轮询比率。
第一个请求分给1,第二个分给2,第三个分给3,这样轮着来
但存在慢的提供者累积请求问题
比如我一直分,1,4,7,10都在1上,2,5,8,11都在2上,3,6,9,12都在3上
但是2服务器性能不行,处理太慢,久而久之,2 上面积累的请求就越来越多。
三台服务器性能差不多的时候,可以用轮循方式
LeastActive LoadBalance
最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。
使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。
比如1-3服务器,给1了10个请求,5分钟处理了9个,还剩一个
给2了10个,5分钟处理了2个,还剩8个
给3了10个,5分钟处理完了,还剩0个
那么就给2少一点请求,给3多一些请求
ConsistentHash LoadBalance
一致性 Hash,相同参数的请求总是发到同一提供者。
当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。算法参见: http://en.wikipedia.org/wiki/Consistent_hashingo
缺省只对第一个参数 Hash,如果要修改,请配置
配置方式
<dubbo:service interface="..." loadbalance="roundrobin" />
或
<dubbo:reference interface="..." loadbalance="roundrobin"/>
随机:
轮询:
loadbalance=”roundrobin"
最少活跃:
loadbalance=" leastactive”
一致性Hash:
面试考点
服务之间的调用为啥不直接用 HTTP 而用 RPC?
参考JavaGuide
RPC 只是一种概念、一种设计,就是为了解决 不同服务之间的调用问题, 它一般会包含有 传输协议 和 序列化协议 这两个。
但是,HTTP 是一种协议,RPC框架可以使用 HTTP协议作为传输协议或者直接使用TCP作为传输协议,使用不同的协议一般也是为了适应不同的场景。
使用 HTTP请求 当然可以,但是可能会比较慢而且一些优化做的并不好。
结束时间:2022-03-10