欢迎大家关注 github.com/hsfxuebao ,希望对大家有所帮助,要是觉得可以的话麻烦给点一下Star哈
1. 大型互联网项目概述
1.1 互联网架构的特点
特点:
- 用户多
- 流量大,并发高
- 海量数据
- 易受攻击
- 功能繁琐
- 变更快
用户体验:
美观、功能、速度、稳定性
衡量一个网站速度是否快:
打开一个新页面一瞬间完成;页面内跳转,-刹那间完成。
1.2 当今大型互联网项目架构目标
衡量网站的性能指标:
响应时间:指执行一个请求从开始到最后收到响应数据所花费的总体时间。并发数:指系统同时能处理的请求数量。并发连接数: 指的是客户端向服务器发起请求,并建立了TCP连接。每秒钟服务器连接的总TCP数量请求数:也称为QPS(Query Per Second)指每秒多少请求.并发用户数:单位时间内有多少用户吞吐量:指单位时间内系统能处理的请求数量。
QPS: Query Per Second每秒查询数。
TPS: Transactions Per Second每秒事务数。 一个事务是指一个客户机向服务器发送请求然后服务器做出反应的过程。客户机在发送请求时开始计时,收到服务器响应后结束计时,以此来计算使用的时间和完成的事务个数。
一个页面的一次访问,只会形成一 个TPS; 但-次页面请求,可能产生多次对服务器的请求,就会有多个QPS
QPS>=并发连接数>= TPS
大型互联网项目架构目标:
- 高性能:访问速度高,用户体验好。
- 高可用:要求服务一直都可以对外使用,一般采用集群方式,即使一个节点宕机了,还有其他节点通过服务。
- 可伸缩:根据具体情况,通过增加/减少硬件,从容提高/降低处理能力。如登录功能模块只使用一台以每秒处理10个请求的服务器,当用户量提升了,现每秒需要处理20个请求,那么可以增加另一台服务器提供登录功能模块的服务。
- 高可扩展:系统间耦合度低,方便通过新增/移除方式,增加/减少新的功能/模块。
- 安全性:保证网站的安全可靠。
- 敏捷性:随需应变,快速响应。
1.3 集群和分布式
正向代理:正向代理的过程,它隐藏了真实的请求客户端,服务端不知道真实的客户端是谁,客户端请求的服务都被代理服务器代替来请求。
反向代理:服务器会帮我们把请求转发到真实的服务器那里去。Nginx就是性能非常好的反向代理服务器,用来做负载均衡。
集群和分布式:
- 集群:很多“人”一起,干一样的事。一个业务模块,部署在多台服务器上。
- 分布式:很多"人”一起,干不一样的事。这些不一样的事, 合起来是一件大事
1.4 架构演进
随着互联网的发展,网站应用的规模不断扩大,架构也在一步步演变,具体请看下图:
1.4.1 单体架构
官网解释:当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。此时,用于简化增删改查工作量的数据访问框架(ORM)是关键。
个人理解:业务或功能模块不拆分,放在同一个服务器上运行,**就如我们一开始学习javaweb,写好全部功能,一起打包放入同一个tomcat上运行。
优点:
- 简单,无论是开发还是部署都很方便,毕竟都是在同一个服务器运行。
缺点:
- 项目启动慢,因为当你的项目业务需要特别多,功能模块特别多,而又是在同一个服务器上运行,服务器资源毕竟有限,需要全部一口气编译运行才能对外提供服务。
- 可靠性差,当系统分别有A,B,C功能模块,突然B模块出现bug挂了,而其他模块也无法对外提供服务了。
- 可伸缩性差,因为全部功能模块都是部署在同一个服务器上,当想要增加某个模块处理能力,也无法为单体功能模块搭建集群,也只能整个服务器增加。
- 扩展性和可维护性差,因为当系统需要增加一个功能模块E时,需要将原服务器停止,并重新打包部署。
- 性能低,因为全部压力都在一台服务器上,当用户量很大时,服务器会出现瓶颈。
1.4.2 垂直架构
官网解释:当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,提升效率的方法之一是将应用拆成互不相干的几个应用,以提升效率。此时,用于加速前端页面开发的Web框架(MVC)是关键。
个人理解:将单体架构中的多个模块拆分为互不交互的独立项目,重点是互不交互,如上图,在app1中的A,B都不跟app2中的C、D模块进行交互,他们跟同一个DB交互就有。
优点:
- 解决了单体架构大部分缺点。项目启动变快,因为功能模块被拆分到两台服务器上运行,不会集中在一台服务器。
- 可靠性变好,由于AB与CD模块是独立在两台服务器上运行,当B模块bug挂了,并不影响app2的应用。
- 可伸缩性变好,比如AB功能模块用户访问量大,可以多搭一个app1的应用服务器。
缺点: - 重复功能(重复代码)太多了,冗余很大。
- 比如:app1是订单功能项目,aap2 是购物车功能项目,那这两个模块都需要用户信息,而app1,跟app2之间是互不交互的,因此可能会导致,在app1中有用户信息相关代码,而app2中也会有,如下图:
- 比如:app1是订单功能项目,aap2 是购物车功能项目,那这两个模块都需要用户信息,而app1,跟app2之间是互不交互的,因此可能会导致,在app1中有用户信息相关代码,而app2中也会有,如下图:
1.4.3 分布式架构
官方解释:当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复用及整合的分布式服务框架RPC是关键。
个人解释:将重复的公共业务模块提取出来成分独立的服务,供其他调用者消费,以实现服务的共享和重用。
如上图,模块E是重复公共的,将它提取出来,给app1,app2调用如下图:
垂直架构跟分布式架构的区别:首先他们都是将一个大系统划分成为各个不同功能模块,部署在不同的服务器上,但是垂直架构之间的应用互不交互,而分布式架构之间的应用是可以相互调用访问的。
优点:
- 解决重复功能(重复代码)太多的问题。
缺点:
-
根据上图来解释,我们知道三个业务模块运行在3个服务器上,而之间要相互调用,必然是使用网络调用,而网络调用有需要三要素,协议,ip,端口,协议不用说了,关键是ip与端口,若一个规定好E服务的IP端口是 192.168.131.129:8000,而app1,app2在代码中就写好这个地址,这样子就可以正常调用,但是如果E服务的IP端口突然改变为192.168.130.128:7000了,那么就需要修改app1,app2相关信息,实在太麻烦了。
-
总结一句话就是:
服务提供方一旦发生变更,则所有消费方都需要变更。
1.4.4 SOA架构
为了解决分布式架构的缺点,而产生的SOA架构,Service- Oriented Architecture,面向服务的架构
ABC是消费方,DEF是服务提供方,而DEF服务将把自己的ip端口信息注册到ESB(服务中介中),如当A想要调用E的服务的时候,先去ESB中索要E服务的端口ip,当A拿到之后,就去通过网络调用E。而当E服务的ip端口发生改变的时候,E服务会重新将ip端口信息注册到ESB中,并通知A消费方,E服务的ip端口发生改变,请获取最新值,之后当A消费方又要调用E服务的时候,则重新去获取最新IP端口,完全不用想当初一样,修改ip端口什么乱七八糟操作。
ESB服务总线(Enterparise Servce Bus),主要是提供了一个服务于服务之间的交互,包含的功能如:负载均衡,流量控制,加密处理,服务监控,异常处理,监控告急等等,dubbo就是做这个任务的。
ESB又叫服务中介,中介嘛,大家都知道很多东西都交给他,他负责搞定大部分事情。
1.4.5 微服务架构
微服务架构是在SOA上做的升华,微服务架构强调的一个重点是
“业务需要彻底的组件化和服务化”,原有的单个业务系统会拆分为多个可以独立开发,设计,运行的小应用,这些小应用之间通过服务完成交互和集成。
业务需要彻底的组件化和服务化,组件化是重点理解,组件故名就是可以重复应用的。其次,单个业务系统会拆分为多个可以独立开发,设计,运行的小应用,独立开发、设计、运行 是重点理解,则说明一个功能模块可以直接在服务器上运行,拥有自己的数据库。
微服务架构= 80%的SOA服务架构思想+ 100%的组件化架构思想+ 80%的领域建模思想
优点:
- 服务实现组件化:开发者可以自由选择开发技术,也不需要协调其他团队,只需要把自己那个服务彻底实现,并对外提供接口即可。
服务之间交互一般使用REST API - 去中心化,每个微服务有自己私有的数据库持久化业务数据。
- 自动化部署:把应用拆分成为一个一个独立的单个服务,方便自动化部署、测试、运维。
2. Dubbo概述
Apache Dubbo 是一款由阿里巴巴公司开发的服务框架,它提供了 RPC 通信与微服务治 理两大关键能力。这意味着,使用 Dubbo 开发的微服务,将具备相互之间的远程发现与通
信能力,同时利用 Dubbo 提供的丰富服务治理能力,可以实现诸如服务发现、负载均衡、 服务降级、集群容错等服务治理诉求。同时 Dubbo 是高度可扩展的,用户几乎可以在任意
功能点去定制自己的实现,以改变框架的默认行为来满足自己的业务需求。
2.0 RPC框架定义
RPC(Remote Procedure Call)—远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。比如两个不同的服务A,B部署在两台不同的机器上,那么服务 A 如果想要调用服务 B 中的某个方法该怎么办呢?使用 HTTP请求 当然可以,但是可能会比较慢而且一些优化做的并不好。 RPC 的出现就是为了解决这个问题。
2.1 阿里的 RPC 框架
- dubbo:阿里巴巴 B2B
- HSF:淘系。要比 dubbo 早 2-3 年。
- SOFA:蚂蚁金服。
2.2 为什么要学好 Dubbo
- 看归属
- 2011 年开源,之后就迅速成为了国内该类开源项目的佼佼者。 2011 年时,优秀的、可在生产环境使用的 RPC 框架很少, Dubbo 的出现迅速给人眼前一亮的感觉,迅速受到了开发者的亲睐。
- 2012 年 10 月之后就基本停止了重要升级,改为阶段性维护。
- 2014 年 10 月 30 日发布 2.4.11 版本后, Dubbo 停止更新。
- 2017 年 10 月云栖大会上,阿里宣布 Dubbo 被列入集团重点维护开源项目,这也就意味着 Dubbo 起死回生,开始重新进入快车道。
- 2018 年 2 月 15 日,大年三十,经过一系列紧张的投票,宣布 Dubbo 正式进入Apache 孵化器。
- 2019 年 5 月 20 日, Dubbo 正式毕业,结束孵化,成为 Apache 的顶级项目。
- 看定位
- Dubbo2 时官方对 Dubbo 的定义为,一款
高性能 RPC 框架。而 Dubbo3 官方对 Dubbo 的定义为,一款高性能、轻量级的开源服务框架。 其定义已经发生了本质上的改变:由原来的通信框架变为了现在的服务框架。
- Dubbo2 时官方对 Dubbo 的定义为,一款
- 用户
- 现在很多大公司在使用 Dubbo,而中小型公司中使用 Dubbo 的不多,使用 Spring Cloud的较多。因为
SC 是开箱即用,其开发成本较 Dubbo 要低。但其通信效率不及 Dubbo。SC采用的是 HTTP,而 Dubbo 则是 RPC。 - 除了以上用户外,还有携程、 瓜子二手车、中通等在内的互联网、传统企业公司。
- 现在很多大公司在使用 Dubbo,而中小型公司中使用 Dubbo 的不多,使用 Spring Cloud的较多。因为
- 看阿里
- 值得一提的是, 2020 年开始,阿里内部正在 Dubbo 替换 HSF 框架,这在很大程度上会引发 Dubbo 的更进一步的热度。
- 性能
- Dubbo3 定义了全新的 PCP 通信协议—Triple,即 Dubbo3 通信协议。比 Dubbo2 通信协议有了很大的性能提升。
- Dubbo3.0 致力于开发云原生应用, 支持与 Kubernetes Native Service 的融合,支持Service Mesh。
- 原来面试时最好问的一个问题是 Dubbo 与 SC 的技术选型问题。现在也不用考虑这个问题了。可以直接使用 Dubbo Spring Cloud。即 SCA 中不再使用 OpenFeign 或 RestTmeplate 作为客户端,而是使用 Dubbo。因为 Dubbo 在稳定性与性能上要比它们高很多。
2.2 官方文档
3. Dubbo架构
3.1 节点角色说明
| 节点 | 角色说明 |
|---|---|
| Provider | 暴露服务的服务提供方 |
| Consumer | 调用远程服务的服务消费方 |
| Registry | 服务注册与发现的注册中心 |
| Monitor | 统计服务的调用次数和调用时间的监控中心 |
| Container | 服务运行容器 |
3.2 调用关系说明
- 服务容器负责启动,加载,运行服务提供者。
- 服务提供者在启动时,向注册中心注册自己提供的服务。
- 服务消费者在启动时,向注册中心订阅自己所需的服务。
- 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
- 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
- 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
4. Dubbo的demo案例
4.1 业务接口工程 demo-interface
业务接口:
public interface DemoService {
String sayHello(String name);
}
4.2 提供者工程 demo-xml-provider
接口实现类:
public class DemoServiceImpl implements DemoService {
private static final Logger logger = LoggerFactory.getLogger(DemoServiceImpl.class);
@Override
public String sayHello(String name) {
logger.info("Hello " + name + ", request from consumer: " + RpcContext.getServiceContext().getRemoteAddress());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Hello " + name + ", response from provider: " + RpcContext.getServiceContext().getLocalAddress();
}
}
定义 dubbo-provider.xml 配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<dubbo:application name="demo-provider">
</dubbo:application>
<dubbo:config-center address="zookeeper://127.0.0.1:2181"/>
<dubbo:metadata-report address="zookeeper://127.0.0.1:2181"/>
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
<dubbo:protocol name="dubbo" port="20881"/>
<bean id="demoService" class="org.apache.dubbo.demo.provider.DemoServiceImpl"/>
</beans>
启动类:
public class ApplicationProvider {
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/dubbo-provider.xml");
context.start();
System.in.read();
}
}
4.3 消费者工程 demo-xml-consumer
定义 dubbo-consumer.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<dubbo:application name="demo-consumer">
</dubbo:application>
<dubbo:metadata-report address="zookeeper://127.0.0.1:2181"/>
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<dubbo:reference id="demoService" check="false"
interface="org.apache.dubbo.demo.DemoService"/>
</beans>
定义消费者类:
public class ApplicationConsumer {
/**
* In order to make sure multicast registry works, need to specify '-Djava.net.preferIPv4Stack=true' before
* launch the application
*/
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/dubbo-consumer.xml");
context.start();
GreetingService greetingService = context.getBean("demoService", GreetingService.class);
// while (true) {
String greetings = greetingService.hello();
System.out.println("result =========================== " + greetings);
Thread.sleep(5000);
// }
}
}
5. dubbo-admin 管理控制台
2019 年初,官方发布了 Dubbo 管理控制台 0.1 版本。结构上采取了前后端分离的方式, 前端使用 Vue 和 Vuetify 分别作为 Javascript 框架和 UI 框架,后端采用 Spring Boot 框架。 目前已经发展到了 0.3 版本。
5.1 下载
Dubbo 管理控制台的下载地址为: github.com/apache/dubb…
5.2 配置
这是一个 Spring Boot 工程, 在下载的 zip 文件的解压目录的如下目录中修改配置文件。
默认的端口为8080,这个端口一般都冲突,我们修改端口号:
文件路径如下:
dubbo-admin\dubbo-admin-server\src\main\resources\application.properties
5.3 打包
在命令行窗口中进入到解压目录根目录,执行打包命令,跳过 test 阶段。
mvn clean package -Dmaven.test.skip=true
打包结束后,进入到解压目录下的 dubbo-admin-distribution 目录下的 target 目录。 该
目录下有个 dubbo-admin-0.3.0-SNAPSHOT.jar 文件。该 Jar 包文件即为 Dubbo 管理控制台的
运行文件,可以将其放到任意目录下运行。
5.4 启动管控台
在启动 zookeeper 后, 将 dubbo-admin-0.3.0-SNAPSHOT.jar 文件存放到任意目录下,例如
D 盘根目录下,直接运行。
5.5 访问
在浏览器地址栏中输入 http://localhost:7777 ,即可看到 Dubbo 管控平台的登录界面。