微服务架构
- 想要理解微服务就要知道什么是系统架构设计, 因为微服务架构设计是将系统架构设计进行了分离.
- 系统架构设计描述了在应用系统的内部,如何根据业务、技术、组织、灵活性、可扩展性以及可维护性等多种因素,将应用系统划分成不同的部分,并使这些部分彼此之间相互分工、相互协作,从而为用户提供某种特定的价值的方式。这个整体就是一个系统架构设计的思想
- 前面说到微服务架构设计是将系统架构设计进行了分离,那我们MVC三层架构脸面何从
- 理由就是目前的三层架构存在很多弊端,不满足业务发展的需求了呗。
- 三层架构是指在业务和技术的发展过程中,系统中不同职责的部分被定义在不同的层次,每一层负责的功能更加具体化。三层架构通常包括表示层、业务逻辑层和数据访问层,层与层之间互相连接、互相协作,构成一个整体,并且层的内部可以被替换成其他可以工作的部分,但对整体的影响不大。
- 三层架构的具体内容如下:
1、表示层: 用户使用应用程序时,看到的、听见的、输入的或者交互的部分。
2、业务逻辑层: 根据用户输入的信息,进行逻辑计算或者业务处理的部分。
3、数据访问层: 关注有效地操作原始数据的部分,如将数据存储到存储介质(如数据库、文件系统)及从存储介质中读取数据等。
- 但是虽然现在程序被分成了三层,但只是逻辑上的分层,并不是物理上的分层。也就是说,对不同层的代码而言,经过编译、打包和部署后,所有的代码最终还是运行在同一个进程中。而这,就是所谓的单块架构,也就是all in one, 虽然分了三层但还是一个进程在跑
- 单块架构也是有优点的
1、易于开发: 开发方式简单,IDE 支持好
2、易于测试: 所有功能运行在一个进程中,一旦进程启动,便可以进行系统测试。
3、易于部署: 只需要将打好的一个软件包发布到即可。
4、易于水平伸缩: 只需要创建一个服务器节点,配置好运行时环境,再将软件包发布到新服务器节点即可运行程序(当然也需要采取分发策略保证请求能有效地分发到新节点)。
- 单块架构的缺点
1、维护成本大: 当应用程序的功能越来越多、团队越来越大时,沟通成本、管理成本显著增加。当出现 bug 时,可能引起 bug 的原因组合越来越多,导致分析、定位和修复的成本增加;并且在对全局功能缺乏深度理解的情况下,容易在修复 bug 时引入新的 bug。
2、持续交付周期长: 构建和部署时间会随着功能的增多而增加,任何细微的修改都会触发部署流水线。
3、新人培养周期长: 新成员了解背景、熟悉业务和配置环境的时间越来越长。
4、技术选型成本高: 单块架构倾向于采用统一的技术平台或方案来解决所有问题,如果后续想引入新的技术或框架,成本和风险都很大。
5、可扩展性差: 随着功能的增加,垂直扩展的成本将会越来越大;而对于水平扩展而言,因为所有代码都运行在同一个进程,没办法做到针对应用程序的部分功能做独立的扩展。
- 好, 我们知道单块架构的缺点就可以想, 如何解决这些缺点, 缺点总体而言就是 所有代码都在一个里面,当我们需要维护修改的时候, 必须停下所有的程序, 那我们可不可以做到不停下所有的,只停下我们需要修改的那部分代码, 这就是我们的微服务架构
- 微服务架构是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调、互相配合,为用户提供最终价值。每个服务运行在其独立的进程中,服务于服务间采用轻量级的通信机制互相沟通(通常是基于 HTTP 的 RESTful API)。每个服务都围绕着具体业务进行构建,并且能够被独立地部署到生产环境、类生产环境等。
微服务架构的特点
- 单一职责
微服务架构中的每个服务,都是具有业务逻辑的,符合高内聚、低耦合原则以及单一职责原则的单元,不同的服务通过“管道”的方式灵活组合,从而构建出庞大的系统。
- 轻量级通信
服务之间通过轻量级的通信机制实现互通互联,而所谓的轻量级,通常指语言无关、平台无关的交互方式。
- 独立性
每个服务在应用交付过程中,独立地开发、测试和部署。
在单块架构中所有功能都在同一个代码库,功能的开发不具有独立性;当不同小组完成多个功能后,需要经过集成和回归测试,测试过程也不具有独立性;当测试完成后,应用被构建成一个包,如果某个功能存在 bug,将导致整个部署失败或者回滚。
- 进程隔离
单块架构中,整个系统运行在同一个进程中,当应用进行部署时,必须停掉当前正在运行的应用,部署完成后再重启进程,无法做到独立部署。
- 现在是不是觉得微服务架构好好呀, 那我们是不是完全分离, 完全使用微服务, 答案肯定是不行
- 分布式系统的复杂性
微服务架构是基于分布式的系统,而构建分布式系统必然会带来额外的开销。
1、性能: 分布式系统是跨进程、跨网络的调用,受网络延迟和带宽的影响。
2、可靠性: 由于高度依赖于网络状况,任何一次的远程调用都有可能失败,随着服务的增多还会出现更多的潜在故障点。因此,如何提高系统的可靠性、降低因网络引起的故障率,是系统构建的一大挑战。
3、异步: 异步通信大大增加了功能实现的复杂度,并且伴随着定位难、调试难等问题。
4、数据一致性: 要保证分布式系统的数据强一致性,成本是非常高的,需要在 C(一致性)A(可用性)P(分区容错性) 三者之间做出权衡。
5、运维成本的增加: 运维主要包括配置、部署、监控与告警和日志收集四大方面。微服务架构中,每个服务都需要独立地配置、部署、监控和收集日志,成本呈指数级增长。
总结
-
微服务架构就是把原来的一个service,现在放到额外的服务器上变成一个小模块, 他只为其他服务提供接口
-
使用微服务架构就是为了打破原来All in one 的架构方式(使用all in one虽然易于调试和负载均衡, 但是一旦修改工程浩大), 所以使用微服务架构就会使每个功能独立出来, 把独立出来的功能元素进行动态组合, 需要什么就拿什么进行整合,所以微服务架构是对功能元素的复制, 而没有对整个应用进行复制
-
这样的好处就是: 节省了调度的资源, 所有功能可以实现动态组合, 每一个功能都是可替换的,可独立升级修改的代码块
-
所以构建一个功能独立的微服务应用单元, 可以使用SpringBoot. 大量分布式网络服务的调度, 可以使用SpringCloud实现, 在分布式中间,进行流失计算数据处理,使用SpringCloudData
为什么使用SpringBoot实现微服务是较好的选择?
- 学过javaweb的同学就知道,开发一个web应用,从最初开始接触Servlet结合Tomcat, 跑出一个Hello Wolrld程序, 导包,实现HttpServlet, 配置web.xml,尤其是与其他技术进行结合的时候,是要经历特别多的步骤
- 后来就有了SSM框架的使用, 使用Spring的基于POJO的轻量级和最小侵入性(set)编程,所有东西都是bean、通过IOC,依赖注入(DI)和面向接口实现松耦合、基于切面(AOP)和惯例进行声明式编程使用在整合其他框架和技术的时候,实现了方便和简化
- 随着 Spring 不断的发展,涉及的领域越来越多,项目整合开发需要配合各种各样的文件,慢慢变得不那么易用简单,违背了最初的理念,甚至人称配置地狱。
- Spring Boot 正是在这样的一个背景下被抽象出来的开发框架,目的为了让大家更容易的使用 Spring 、更容易的集成各种常用的中间件、开源软件
- Spring Boot 基于 Spring 开发,Spirng Boot 本身并不提供 Spring 框架的核心特性以及扩展功能,只是用于快速、敏捷地开发新一代基于 Spring 框架的应用程序。也就是说,它并不是用来替代 Spring 的解决方案,而是和 Spring 框架紧密结合用于提升 Spring 开发者体验的工具。Spring Boot 以约定大于配置的核心思想,默认帮我们进行了很多设置,多数 Spring Boot 应用只需要很少的 Spring 配置。同时它集成了大量常用的第三方库配置(例如 Redis、MongoDB、Jpa、RabbitMQ、Quartz 等等),Spring Boot 应用中这些第三方库几乎可以零配置的开箱即用。
- 简单来说就是SpringBoot其实不是什么新的框架,它默认配置了很多框架的使用方式,就像maven整合了所有的jar包,spring boot整合了所有的框架 。
- Spring Boot 出生名门,从一开始就站在一个比较高的起点,又经过这几年的发展,生态足够完善,Spring Boot 已经当之无愧成为 Java 领域最热门的技术。
所有的技术框架的发展似乎都遵循了一条主线规律:从一个复杂应用场景 衍生 一种规范框架,人们只需要进行各种配置而不需要自己去实现它,这时候强大的配置功能成了优点;发展到一定程度之后,人们根据实际生产应用情况,选取其中实用功能和设计精华,重构出一些轻量级的框架;之后为了提高开发效率,嫌弃原先的各类配置过于麻烦,于是开始提倡“约定大于配置”,进而衍生出一些一站式的解决方案。
是的这就是Java企业级应用->J2EE->spring->springboot的过程。
- Spring Boot的主要优点:
- 可以实现快速入门
- 开箱即用, 使用约定大于配置思想系统帮你提供了默认配置来简化项目的配置
- 内涵默认tomcat容器简化web的部署
SpringBoot项目结构分析
- 当我们新建一个SpringBoot项目时, 就会自动生成以下文件。
1、程序的主启动类
2、一个 application.properties 配置文件
3、一个 测试类
4、一个 pom.xml
- 打开pom.xml,看看Spring Boot项目的依赖:
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!--有一个父项目依赖-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.11.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--核心依赖, 内涵tomcat和dispatchServlet和xml配置都是他帮我们做的-->
<!-- web的场景启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--所有的SpringBoot依赖都是使用spring-boot-starter开始-->
<!--单元测试-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<!-- 剔除依赖 -->
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 打包插件 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
- 还有一个启动类
//通过这个注解, 标注这个类是一个SpringBoot的应用
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
//启动SpringBoot, 指定包, 所有代码必须在这个包下
SpringApplication.run(DemoApplication.class, args);
}
}