赞
踩
早期的服务器状态,安装好一些固定内容,让用户访问。功能单一 ,如果不修改代码,内容是不会变的,只能做信息的呈现或输出。
网页中的数据可能来自数据库,数据库中的数据可以在后台中进行修改
实现不修改页面代码,但是变化页面内容的效果
因为有了数据库的支持,动态网站开始支持登录注册,增删改查功能
随着互联网的普及,个人的社交需求提升
出现了很多由用户贡献内容的网站
微博,抖音,淘宝,大众点评或类似的网站
随着用户的增加,各种并发的增高,要求我们的服务器在繁忙的情况下,也需要快速的做出响应,保证用户体验。
这样就要求我们的项目有下面三个目标
现在市面上常见的java开发的项目可以分为两大类
企业级应用和互联网应用的偏重点不同
一般指一个企业或机构内部使用的网站或服务器应用程序
使用的人群比较固定,并不向全国乃至全世界开放
例如,商业,企事业单位,医疗,金融,军事,政府等
所以这个项目没有代替品,对"三高"没有强烈要求
企业级项目一般会在权限和业务流程方面设计的比较复杂
能够向全国乃至全世界开放的网站或服务器应用程序
我们手机中安装的app大部分都是互联网应用
微信,支付宝,京东,淘宝,饿了么,美团,抖音,qq音乐,爱奇艺,高德地图等
它们因为商业竞争等原因,对服务器的性能有非常高的要求,即高并发、高可用、高性能
但是互联网应用一般没有权限和业务非常复杂的需求
在当今java开发业界中,基本规律如下:
如果开发的是企业级应用,使用单体架构的情况比较多
如果开发的是互联网应用,使用微服务架构的情况比较多
微服务的概念是由Martin Fowler (马丁.福勒)在2014年提出的。
微服务是由以单一应用程序构成的小服务,自己拥有自己的行程与轻量化处理,服务依业务功能设计,以全自动的方式部署,与其他服务使用HTTP API通信。同时服务会使用最小的规模的集中管理能力,服务可以用不同的编程语言与数据库等组件实现。
简单来说微服务就是将一个大型项目的各个业务模块拆分成多个互不相关的小项目,而这些小项目专心完成自己的功能而且可以调用其他小项目的方法,从而完成整体功能
在微服务概念提出之前(2014年),每个厂商都有自己的解决方案
但是Martin Fowler (马丁 福勒)提出了微服务的标准之后,为了技术统一和兼容性很多企业开始支持这个标准
现在我们开发的微服务项目,大多数都是在马丁 福勒标准下的
如果我们自己编写支持这个标准的代码是不现实的,必须通过现成的框架或组件完成满足这个微服务标准的项目结构和格式。
SpringCloud是由Spring提供的一套能够快速搭建微服务架构程序的框架集。
框架集表示SpringCloud不是一个框架,而是很多框架的统称
SpringCloud就是为了搭建微服务架构项目出现的
有人将SpringCloud称之为"Spring全家桶",广义上指代Spring的所有产品。
Spring自己提供的开发出来的框架或软件
Netflix(奈非): 早期的很长一段时间,提供 了大量的微服务解决方案
alibaba(阿里巴巴):新版本的SpringCloudAlibaba正在迅速占领市场(推荐使用)
微服务的注册中心
微服务间的调用
微服务的分布式事务
微服务的限流
微服务的网关
Nacos是Spring Cloud Alibaba提供的一个软件
这个软件主要具有注册中心和配置中心的功能
微服务中所有项目都必须注册到注册中心才能成为微服务的一部分
注册中心和企业中的人力资源管理部门]有相似
https://github.com/alibaba/nacos/releases/download/1.4.3/nacos-server-1.4.3.zip
进入解压后的bin目录下,可以看到:
cmd结尾的文件是windows版本的
sh结尾的文件是linux和mac版本的
startup是启动文件, shutdown是停止文件
Windows下启动Nacos不能直接双击cmd文件,要在dos窗口运行,在当前资源管理器地址栏输入cmd,并输入以下命令
startup.cmd -m standalone
startup.cmd:windows启动nacos的命令文件
-m表示要设置启动参数
standalone:翻译为标准的孤独的,意思是正常的使用单机模式启动
运行成功默认占用8848端口,并且在代码中提示
如果不输入standalone运行会失败
打开浏览器输入地址
http://localhost:8848/nacos
用户名:nacos
密码:nacos
登录之后可以进入后台列表
不能关闭启动nacos的dos窗口
我们要让我们编写的项目注册到Nacos,才能真正是微服务项目
我们微服务开发过程中,一般都会使用一个Idea中包含多个项目的形式
这个形式就是先创建一个"父项目",再向这个父项目中创建多个子项目的操作
删除src
修改pom文件
<!-- 当前项目会以一个pom文件的形式,被子项目继承使用 -->
<packaging>pom</packaging>
我们每次创建一个子项目之后
都要进行"父子相认"
在父项目的pom文件中,编写子项目的存在
<!-- 当前父项目包含的所有模块,要定义在下面的标签中, module就是模块的意思-->
<modluLes>
<moduLe> </module>
</moduLes>
还需要在子项目的pom文件中对父项目进行继承操作
父项目的第11行到第13行
复制到子项目的第6行到第8行
删除子项目src\test
在我们现在使用maven添加依赖的认知中,有些依赖时必须添加版本号才能执行
有些依赖则不必添加版本号,原因是我们继承的SpringBoot(2.5.9)父项目中,定义了一些常用依赖的版本号
如果我们自己编写的父项目想定义我们项目中需要的依赖版本号的话也是可以实现的,这样做可以统一所有子项目的版本,在更新版本时,只需要修改父项目中定义的版本号。
<properties> <java.version>1.8</java.version> <!-- 定义mybatis的版本号(标签名称是自定的)--> <mybatis.version>2.2.2</mybatis.version> </properties> <!-- 下面是父项目中来定义子项指定依赖时选用的版本,也称为"锁版本” --> <!-- dependencyManagement标签中的内容,并不是添加依赖,而是指定依赖的版本--> <dependencyManagement> <dependencies> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>${mybatis.version}</version> </dependency> </dependencies> </dependencyManagement>
子项目中如果需要mybatis的依赖只需要添加如下内容即可,无需再指定版本号
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
因为我们学习微服务的过程中需要很多微服务相关的依赖
这些依赖都需要在父项目中进行版本的管理的
所以建议直接复制
在实际开发中,经常会出现有些类需要在多个微服务项目中使用的情况,为了减少代码的冗余,我们在父项目中创建一个子项目commons专门保存编写这样的类。哪个微服务需要使用,就添加对commons的依赖即可。
当前模块只是编写通用类和代码,实际上不需要运行,所以删除运行相关的文件,删除test测试文件夹,删除resources文件夹,删除SpringBoot启动类。
带大家编写一个我们需要的实体类
创建com.luck.csmall.commons.pojo.cart.dto
DTO:前端收集到数据发送给后端的信息
VO:后端从数据库查询出来要发送给前端的信息
除了实体类多个模块需要使用之外,像异常类和控制器返回的jsonResult类也是多个模块需要使用的类型,它们也要编写在commons中。
创建com.luck.csmall.commons.restful包
在这个包中创建异常响应码枚举。
在restful包中创建用于控制器返回的JsonResult类。
创建com.luck.csmall.commons.exception包
在包中创建XxxException类
我们编写的所有模块控制层发送异常时,也都由SpringMvc的统一异常处理类来处理,所以commons模块编写统一异常处理类也是常规操作。
spring:
profiles:
active: dev
上面的配置含义是让SpringBoot读取额外配置文件yml
我们参数值编写的是dev,是可以随意修改的,这里定义的名称,就是指定配置文件的名称
例如当前我们编写的dev,SpringBoot就会额外加载名称为application-dev.yml文件
并创建CommonsConfigration类,写相关配置。
//只有添加了@Configuration注解的类才能配置当前Spring的环境
@Configuration
//要扫描commons 模块中的统一异常处理类所在的路径,否则异常处理功能不会生效
@ComponentScan("com.luck.csmall.commons.exception")
public class CommonsConfiguration {
}
运行对应sql语句
在application-dev.yml配置数据源、项目名称和Nacos位置
mapper
service
controller
在包下创建对应类
//使用BeanUtils类中给定的方法,将同名属性赋值
BeanUtils.copyProperties(cartAddDTO,cart);
属性私有化,方法公开化
<!--
Dubbo调用过程中,消费者一份添加依赖的特征:
添加要消费的模块的业务逻辑层接口项目的依赖-->
<dependency>
<groupId>cn.tedu</groupId>
<artifactId>csmall-stock-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
消费者Impl中添加的东西
//添加@DubboReference注解, 表示当前业务逻辑层中需要消费其他模块的服务
//声明的接口应该是其他服务提供的业务逻辑层接口
//因为Nacos中注册了业务的实现类,所以声明的接口会自动匹配到实现类对象
@DubboReference
private IStockService stockService;
//在实现类中实现对应的方法
controller/servlet:控制层
service/biz:业务逻辑层
mapper/dao/repository:持久层
entity/model/domain/bean/pojo:实体类包
是java中和类\接口平级的一种文件
它的功能一般是列举一个属性可能出现的值
我们已经讲过一个项目要想成为微服务项目体系的一部分,必须将当前项目的信息注册到Nacos
我们要添加一些配置,实现business模块启动时注册到Nacos的效果。
<!-- 支持项目注册到Nacos注册中心的依赖discovery发现(微服务的发现)-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
spring:
application:
#为当前项目起名,这个名字会被Nacos获取并记录,由于之后的微服务调用
name: nacos-business
cLoud:
nacos:
discovery:
#配置Nacos的位置,用于提交当前项目的信息
server-addr: Localhost:8848
启动之后,重启business模块,如果启动也正常,就应该将当前项目的信息提交给Nacos
在Nacos的服务管理>服务列表中,能看到nacos-business的名称
心跳:周期性的操作,来表示自己是健康可用的机制
注册到Nacos的微服务项目(模块)都是会遵循这个心跳机制的
1.是表单当前微服务模块运行状态正常的手段
2.是表单当前微服务模块和Nacos保持沟通和交换信息的机制
默认情况下,服务启动开始每隔5秒会向Nacos发送一个"心跳包",这个心跳包中包含了当前服务的
基本信息。
Nacos接收到这个心跳包,首先检查当前服务在不在注册列表中,如果不在按新服务的业务进行注册,如果在,表示当前这个服务是健康状态。
如果一个服务连续3次心跳(默认15秒)没有和Nacos进行信息的交互,就会将当前服务标记为不健康的状态。
如果一个服务连续6次心跳(默认30秒)没有和Nacos进行信息的交互,Nacos会将这个服务从注册列表中剔除。
这些时间都可根据配置修改
实际上Nacos的服务类型还有分类
默认每个服务都是临时实例
如果想标记一个服务为永久实例
cloud:
nacos :
discovery:
#ephemeral设置当前项目启动时注册到nacos的类型true(默认) :临时实例false:永久实例
ephemeral: false
持久化实例启动时向nacos注册,nacos会对这个实例进行持久化处理
心跳包的规则和临时实例一致,只是不会将该服务从列表中剔除
一般情况下 我们创建的服务都是临时实例
只有项目的主干业务才会设置为永久实例
RPC是Remote Procedure Call的缩写翻译为:远程过程调用。
目标是为了实现两台(多台)计算机/服务器,相互调用方法/通信的解决方案
RPC只是实现远程调用的一套标准,该标准主要规定了两部分内容
通信协议指的就是远程调用的通信方式。
实际上这个通知的方式可以有多种:
例如:写信,飞鸽传书,发电报
在程序中,通信方法实际上也是有多种的,每种通信方式会有不同的优缺点。
序列化协议指通信内容的格式,双方都要理解这个格式
发送信息是序列化过程,接收信息需要反序列化
程序中,序列化的方式是多种的,每种序列化的方式会有不同的优缺点。
Dubbo是一套RPC框架。我们可以在框架结构高度,定义Dubbo中使用的通信协议,使用的序列化框架技术,而数据格式由Dubbo定义,我们负责配置之后直接通过客户端调用服务端代码。
可以说Dubbo就是RPC概念的实现,Dubbo是SpringCloudAlibaba提供的框架,能够实现微服务相互调用的功能。
在dubbo2012年底停止更新后,国内很多公司在Dubbo的基础上进行修改继续更新,比较知名的修改版本就是当当网的DubboX。
我们学习的Dubbo指的都是2.7之后的版本,是能够和SpringCloudAlibaba配合使用的。
RPC框架分通信协议和序列化协议。
Dubbo框架支持多种通信协议和序列化协议,可以通过配置文件进行修改。
在Dubbo的调用过程中,必须包含注册中心的支持
项目调用服务的模块必须在同一个注册中心中
注册中心推荐阿里自己的Nacos,兼容性好,能够发挥最大性能
但是Dubbo也支持其它软件作为注册中心(例如Redis,zookeeper等)
服务发现,即消费端自动发现服务地址列表的能力,是微服务框架需要具备的关键能力,借助于自动化的服务发现,微服务之间可以在无需感知对端部署位置与IP地址的情况下实现通信。
consumer服务的消费者指服务的调用者(使用者)
provider服务的提供者指服务的拥有者(生产者)
在Dubbo中,远程调用依据是服务的提供者在Nacos中注册的服务名称
一个服务名称,可能有多个运行的实例,任何一个空闲的实例都可以提供服务
1.首先服务的提供者启动服务时,将自己的具备的服务注册到注册中心,其中包括当前提供者的ip地址和端口号等信息,Dubbo会同时注册该项目提供的远程调用的方法
2.消费者(使用者)启动项目,也注册到注册中心,同时从注册中心中获得当前项目具备的所有服务列表
3.当注册中心中有新的服务出现时会通知已经订阅发现的消费者,消费者会更新所有服务列表
4.RPC调用,消费者需要调用远程方法时,根据注册中心服务列表的信息,只需服务名称,不需要ip地址和端口号等信息,就可以利用Dubbo调用远程方法了。
在实际项目中,一个服务基本都是集群模式的,也就是多个功能相同的项目在运行,这样才能承受更高的并发,这时一个请求到这个服务,就需要确定访问哪一个服务器。
Dubbo框架内部支持负载均衡算法,能够尽可能的让请求在相对空闲的服务器上运行在不同的项目中,可能选用不同的负载均衡策略,以达到最好效果
Loadbalance:就是负载均衡的意思
随机生成随机数,在哪个范围内让哪个服务器运行
优点:
算法简单,效率高,长时间运行下,任务分配比例准确
缺点:
偶然性高,如果连续的几个随机请求发送到性能弱的服务器会导致异常甚至宕机
如果几个服务器权重一致,那么就是依次运行
但是服务器的性能权重一致的可能性很小
所以我们需要权重平滑分配
一个优秀的权重分配算法,应该是让每个服务器都有机会运行的
实际运行过程中,每个服务器性能不同
在负载均衡时,都会有性能权重,这些策略算法都考虑权重问题
如果一个集群服务器性能比为5:3:1,服务为A,B,C
无脑分配为:
1>A 2>A 3>A 4>A 5>A
6>B 7>B 8>B
9>C
上面的安排中连续请求一个服务器肯定是不好的,我们希望所有的服务器都能够穿插在一起运行
Dubbo2.7之后更新了这个算法使用"平滑加权算法"优化权重平均分配策略
优点:
能够尽可能的在权重要求的情况下,实现请求的穿插运行(交替运行),不会发生随机策略中的偶发情况
缺点:
服务器较多时,可能需要减权和复权的计算需要消耗系统资源
记录每个服务器处理一次请求的时间
按照时间比例来分配任务数,运行一次需要时间多的分配的请求数较少
根据请求的参数进行hash运算
以后每次相同参数的请求都会访问固定服务器
因为根据参数选择服务器,不能平均分配到每台服务器上
确定调用结构,要想实现Dubbo调用,必须按照Dubbo规定的配置和行业标准的结构来实现。
Dubbo调用的好处是直接将要消费的目标编写在当前消费者的业务逻辑层中,无需编写新的代码结构,开发流程不会因为Dubbo而变化。
生产者方法,需要被别的模块调用,那么其它模块就必须添加当前库存数减少的业务接口支持,为了减少添加这个给当前项目带来的负担,业界通用做法,是将生产者项目拆分为两个。
当消费者需要时只需要添加包含业务逻辑层接口的项目的依赖即可
pom文件不只是将原有的pom文件依赖复制,而且添加了Dubbo和业务逻辑层接口的依赖
yml文件添加如下:
dubbo:
protocol:
# port设置为-1表示当前dubbo框架使用的端口自动寻找
#使用端口的规则是从20880开始寻找可用端口,如果当前端口号占用,就继续加1来使用,直到找到可用的为止
port: -1
#设置连接的名称, 一般固定为dubbo即可
name: dubbo
registry :
#指定当前Dubbo 服务注册中心的类型和位置
address: nacos://localhost:8848
consumer:
#当前项目启动时,是否检查当前项目需要的所有Dubbo服务是否可用
#我们设置它为false,表示不检查,减少启动时出错情况
check: false
//@DubboService 注解,标记的业务逻辑层实现类,其中所有的方法都会注册到Nacos
//在其他服务启动并"订阅"后,就会"发现"当前类中的所有服务,随时可以调用
@DubboService
//如果当前项目,是Dubbo中的生产者,必须添加@EnableDubbo注解
//添加之后,在服务启动时,当前项目的所有服务才能正确注册到Nacos中
@EnableDubbo
https://github.com/seata/seata/releases
https://github.com/seata/seata/releases/download/v1.4.2/seata-server-1.4.2.zip
Seata是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务
也是Spring Cloud Alibaba提供的组件
我们之前学习了单体项目中的事务,使用的技术叫Spring声明式事务,能够保证一个业务中所有对数据库的操作要么都成功,要么都失败来保证数据库的数据完整性。
但是在微服务的项目中,业务逻辑层涉及远程调用,当前模块发生异常,无法操作远程服务器回滚,这时要想让远程调用也支持事务功能,就需要使用分布式事务组件Seata。
Seata保证微服务远程调用业务的原子性。
Seata将为用户提供了AT、TCC、SAGA 和XA事务模式,为用户打造一站式的分布式解决方案。
上面结构是比较典型的远程调用结构
如果account操作数据库失败需要让order模块和storage模块撤销(回滚)操作,声明式事务不能完成这个操作,需要使用Seata来解决。
●事务协调器TC
●事务管理器TM
●资源管理器RM
我们项目使用AT(自动)模式完成分布式事务的解决
先配置Java环境变量,如果已配置,忽略。
\bin目录下cmd输入命令
seata-server.bat -h 127.0.0.1 -m file
pom文件需添加配置如下
<!-- Seata和SpringBoot整合依赖-->
<dependency>
<groupId>io.seatak/groupId>
<artifactId>seata-spring- boot-starter</artifactId>
</dependency>
<!-- Seata 完成分布式事务的两个相关依赖(Seata会自动使用其中的资源) -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
yml文件添加如下
seata:
tx-service-group: csmall_group # 定义事务的分组,一般是以项目为单位的, 方便与其它项目区分
service:
vgroup-mapping :
csmall.group: default #csmalL_ group分组的配置, default会默认配置Seata
grouplist:
default: Localhost :8091 #配置Seata服务器的地址和端口号
添加别的项目的配置以及Impl注解。
因为关系型数据库才支持提交和回滚,其它非关系型数据库都是直接影响数据(例如Redis),所以如果我们在业务过程中有一一个节点操作的是Redis或其它非关系型数据库时,就无法使用AT模式。
除了AT模式之外还有TCC、SAGA 和XA事务模式
简单来说,TCC模式就是自己编写代码完成事务的提交和回滚
在TCC模式下,我们需要为参与事务的业务逻辑编写一组共3个方法
这样的话所有提交或回滚代码都由自己编写
优点:虽然代码是自己写的,但是事务整体提交或回滚的机制仍然可用(仍然由TC来调度)
缺点:每个业务都要编写3个方法来对应,代码冗余,而且业务入侵量大
有多台服务器负责相同的业务
例如stock模块有3台服务器,这3台服务器就是分布式部署的
我们的微服务一个项目有多个模块,每个模块都可以单独运行
当他们都启动时,也是分布式部署的特征。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。