目录
12.2.3.Zuul 1.0(慢 servlet 2.0 ) zuul2.0 没出来
13.4.1.创建一个gateway微服务模块--此步骤省略
14.2.3.创建一个配置文件--名字是bootstrap.properties
14.2.5.将application配置文件的内容复制到配置中心
14.3.2.将public里面的配置克隆到dev(开发环境下)
14.4.2.将product和order的数据源剪切到新建的配置中
14.4.3.修改bootstrap.properties文件
1.系统架构演变
随着互联网的发展,网站应用的规模也在不断的扩大,进而导致系统架构也在不断的进行变化。 从互联网早起到现在,系统架构大体经历了下面几个过程: 单体应用架构--->垂直应用架构--->分布式架构--->SOA架构--->微服务架构,当然还有悄然兴起的Service Mesh(服务网格化)。
1.1.单体应用架构
互联网早期,一般的网站应用流量较小,只需一个应用,将所有功能代码都部署在一起就可以,这样可以减少开发、部署和维护的成本。比如说一个电商系统,里面会包含很多用户管理,商品管理,订单管理,物流管理等等很多模块, 我们会把它们做成一个web项目,然后部署到一台tomcat服务器上。
1.2.微服务架构
把一个项目拆分成若干个工程,而每一个工程是可以独立运行和部署的,物理进行了拆分,逻辑上还是一个整体---->必须要springboot(独立的系统) 必须依赖于springboot技术。Springcloud如果没有springboot 那么springcloud也无法使用。 springboot可以独立使用。因为springboot里面内置了tomcat
1.3. 单体应用架构和微服务架构的区别
1.3.1.单体应用架构的优点
(1)项目架构简单,小型项目的话,开发成本低。
(2)项目部署在一个节点上,维护方便
1.3.2.单体应用架构的缺点
(1)全部功能集成在一个工程中,对于大型项目来讲不易开发和维护[修改代码]。
(2)项目模块之间紧密耦合,单点容错率低。
(3)无法针对不同模块进行针对性优化和水平扩展
1.3.3.微服务架构的优点
(1)服务原子化拆分,独立打包、部署和升级,保证每个微服务清晰的任务划分,利于扩展
(2)微服务之间采用Restful等轻量级http协议相互调用
1.3.4.微服务架构的缺点
(1)小型项目----微服务架构不合适。仓库系统---微服务。
(2)微服务系统开发的技术成本高《高》(容错、分布式事务等)
2.什么是springCloud
Spring Cloud就是微服务系统架构的一站式解决方案,是各个微服务架构落地技术的集合体,俗称微服务全家桶,在平时我们构建微服务的过程中需要做如服务发现注册、配置中心、负载均衡、断路器、数据监控等操作,而Spring Cloud 为我们提供了一套简易的编程模型,使我们能在 Spring Boot 的基础上轻松地实现微服务项目的构建
3.微服务出现的问题
3.1.这么多小服务,如何管理他们? --概念:服务治理
3.2.这么多小服务,他们之间如何通讯?调用 --概念:服务调用
3.3.这么多小服务,客户端怎么访问他们?前端 --概念:服务网关
3.4.这么多小服务,一旦出现问题了,应该如何自处理? --概念:服务容错
3.5.这么多小服务,一旦出现问题了,应该如何排错? --概念:链路追踪
4.微服务架构的常见概念
4.1.服务治理
服务治理就是进行服务的自动化管理,其核心是服务的自动注册与发现。
4.1.1.服务注册
服务实例将自身服务信息注册到注册中心。
4.1.2.服务发现
服务实例通过注册中心,获取到注册到其中的服务实例的信息,通过这些信息去请求它们提供的服务。
4.1.3.服务剔除
服务注册中心将出问题的服务自动剔除到可用列表之外,使其不会被调用到。
4.2.服务调用
在微服务架构中,通常存在多个服务之间的远程调用的需求。目前主流的远程调用技术有基于HTTP的RESTful接口以及基于TCP的RPC协议。
4.2.1.RESTful接口
这是一种HTTP调用的格式,更标准,更通用,无论哪种语言都支持http协
4.2.2.RPC协议
@Autowire Bservice bservice.方法()
一种进程间通信方式。允许像调用本地服务一样调用远程服务。RPC框架的主要目标就是让远程服务调用更简单、透明。RPC框架负责屏蔽底层的传输方式、序列化方式和通信细节。开发人员在使用的时候只需要了解谁在什么位置提供了什么样的远程服务接口即可,并不需要关心底层通信细节和调用过程。
4.2.3.RESTful接口和RPC协议的区别
4.3.服务网关
随着微服务的不断增多,不同的微服务一般会有不同的网络地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接与各个微服务通信可能出现:
1.客户端需要调用不同的url地址,增加难度
2.在一定的场景下,存在跨域请求的问题
3.每个微服务都需要进行单独的身份认证
针对这些问题,API网关顺势而生。API网关直面意思是将所有API调用统一接入到API网关层,由网关层统一接入和输出。一个网关的基本功能有:统一接入、安全防护、协议适配、流量管控、长短链接支持、容错能力。有了网关之后,各个API服务提供团队可以专注于自己的的业务逻辑处理,而API网关更专注于安全、流量、路由等问题。
4.4. 服务容错
在微服务当中,一个请求经常会涉及到调用几个服务,如果其中某个服务不可用,没有做服务容错的话,极有可能会造成一连串的服务不可用,这就是雪崩效应。 我们没法预防雪崩效应的发生,只能尽可能去做好容错。服务容错的三个核心思想是:
1.不被外界环境影响
2.不被上游请求压垮
3.不被下游响应拖垮
4.5.链路追踪
随着微服务架构的流行,服务按照不同的维度进行拆分,一次请求往往需要涉及到多个服务。互联网应用构建在不同的软件模块集上,这些软件模块,有可能是由不同的团队开发、可能使用不同的编程语言来实现、有可能布在了几千台服务器,横跨多个不同的数据中心。因此,就需要对一次请求涉及的多个服务链路进行日志记录,性能监控即链路追踪
5.微服务架构的解决方案
5.1.SpringCloud-Netflix
springcloud 很多组件都是拿的是Netflix公司,这家公司这些组件停止维护和更新)
Eureka组件解决服务治理
Feign组件解决服务调用的问题
zuul组件解决客户端调用微服务的问题
hystrix组件解决容错
sleuth组件链路追踪
Spring Cloud是一系列框架的集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署.Spring Cloud并没有重复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。已经停更了。Euruka(注册中),feign远程调用,hystrix 容错,zuul网关
5.2. SpringCloud Alibaba
引入springcloud很多组件都更新了-springcloud alibaba
Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用微服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。
nacos组件解决服务治理
openfeign组件解决服务调用
gateway[spring公司]主件解决api网关
sentinel主件解决服务容错
sleuth组件链路追踪--Netflix
6.搭建微服务
本次是使用的电商项目中的商品微服务、订单微服务为案例
6.1.准备条件
6.1.1.技术选型
maven:3.5.0+
数据库:MySQL 5.7 以上
持久层: Mybatis-plus /《Mybatis Mapper Mybatis-plus》
其他: SpringCloud Alibaba /技术栈 / druid
6.1.2.模块设计
创建父工程 ----jar的版本管理 公共jar的引入
创建公共模块【实体类】 《实体类,公共依赖,工具类。》
创建商品微服务 【端口: 8080~8089 搭建集群】
创建订单微服务 【端口: 8090~8099 搭建集群】
6.2.创建父工程
6.2.3.依赖
将自动生成的依赖删除一下,还有他们的版本号要对应,下面地址是其他博客的写的版本对应
springboot,springCloud,springCloudAlibaba各版本之间的对应关系_lwdbcy的博客-CSDN博客
<?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>
<modules>
<module>springcloud-comment</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.12.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.guan</groupId>
<artifactId>springboot-springcloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-springcloud</name>
<description>Demo project for Spring Boot</description>
<!--如果你的工程为父工程那么它的打包方式为pom-->
<packaging>pom</packaging>
<!--定义版本号-->
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF- 8</project.reporting.outputEncoding>
<spring-cloud.version>Hoxton.SR8</spring-cloud.version>
<spring-cloud-alibaba.version>2.2.3.RELEASE</spring-cloud-alibaba.version>
</properties>
<!--dependencyManagement:它只负责jar的版本号管理,不负责jar的下载,交于子模块,子模块在使用时无需指定版本号
:springboot springcloud springcloudalibaba之间版本一定要匹配
-->
<dependencyManagement>
<dependencies>
<!--springcloud的版本管理-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--springcloudalibaba的版本管理-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
6.2.4.隐藏java中的文件--在另一篇博客中
可以将父工程的src给删除,我们不在父工程写代码,其他的不要删除要不然可能会报错
6.3.公共模块代码
6.3.1.创建公共模块
6.3.2.添加依赖
<!--引入lombok依赖-->
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
</dependencies>
6.3.3.添加实体类
@Data
@TableName(value="shop_product")
public class Product {
@TableId(type= IdType.AUTO)
private Integer pid;
private String pname;//商品名称
private Double pprice;//商品价格
private Integer stock;//库存
}
@Data
@TableName("shop_order")
public class Order {
@TableId(type = IdType.AUTO)
private Long oid; //订单id
private Integer uid;//用户id
private String username;//用户名
private Integer pid;//商品id
private String pname;//商品名称
private Double pprice;//商品价格
private Integer number;//购买数量
}
6.4.商品微服务--对商品的各种操作
如果其他微服务也要用到商品的操作,让其他服务调用商品微服务,不要再其他服务在写对商品的操作
6.4.1.创建商品微服务--省略
6.4.2.添加依赖
<dependencies>
<!--引入公共模块-->
<dependency>
<groupId>com.guan</groupId>
<artifactId>springcloud-comment</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!--引入mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--引入web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
6.4.3.创建配置并在配置文件中写入数据源
#为了后期扩展方便微服务的端口号设置为8080-8090之间
server.port=8081
#数据源
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.password=grt081141
spring.datasource.username=root
spring.datasource.url=jdbc:mysql://localhost:3306/springcloud?serverTimezone=Asia/Shanghai
#日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
6.4.4.添加主启动类
package guan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringcloudApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudApplication.class, args);
}
}
6.4.5.controller
@RestController
@RequestMapping("product")
public class ProductController {
@Autowired
private ProductService productService;
@GetMapping("/getById/{pid}")
public Product product(@PathVariable Integer pid){
return productService.findById(pid);
}
}
6.4.6.dao
@Mapper
public interface ProductMapper extends BaseMapper<Product> {
}
6.4.7. ProductService
public interface ProductService {
Product findById(Integer pid);
}
6.4.8.service
@Service
public class ProductServiceImpl implements ProductService {
@Autowired
private ProductMapper productMapper;
@Override
public Product findById(Integer pid) {
return productMapper.selectById(pid);
}
}
6.4.9.运行
可能会出现的错误
6.5.订单微服务
6.5.1.创建订单微服务--省略
6.5.2.添加依赖
<!--引入公共模块-->
<dependency>
<groupId>com.guan</groupId>
<artifactId>springcloud-comment</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!--引入价格模块-->
<dependency>
<groupId>com.guan</groupId>
<artifactId>springcloud-product</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
6.5.3.创建配置文件,并且写入数据源
#为了后期扩展方便订单微服务的端口号设置为8090-8099之间
server.port=8091
#数据源
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.password=grt081141
spring.datasource.username=root
spring.datasource.url=jdbc:mysql://localhost:3306/springcloud?serverTimezone=Asia/Shanghai
#日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
6.5.4.创建主启动类
@SpringBootApplication
public class SpringcloudOrderApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudOrderApplication.class, args);
}
//将RestTemplate交于容器管理
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
6.5.5.controller
@RestController
@RequestMapping("order")
public class OrderController {
@Autowired
private OrderServiceImpl orderService;
//注入工具类 --这个工具类没有交于容器管理,需要自己手动交于容器
@Autowired
private RestTemplate restTemplate;
@GetMapping("buy/{pid}/{num}")
public String buy(@PathVariable Integer pid,@PathVariable Integer num){
System.out.println("=======购买开始===========");
Order order=new Order();
//设置购买的数量
order.setNumber(num);
//设置购买人的名字
order.setUsername("东方青苍");
//设置id
order.setUid(1);
//设置订单中商品的信息
//由于商品的信息在商品微服务中,如果想要用,得调用
//远程调用有两种方法1.http协议的restful风格的调用--适合微服务2.基于TCp协议的RPC--适合SOA分布式
//所以我们用http协议--1.自己写代码完成http的调用
// 2springboot提供一个工具类RestTemplate--属于http协议完成的调用
Product forObject = restTemplate.getForObject("http://localhost:8081/product/getById/" + pid, Product.class);
//获取商品的id
order.setPid(pid);
order.setPprice(forObject.getPprice());
order.setPname(forObject.getPname());
orderService.saveOrder(order);
System.out.println("==========购买结束=========");
return "下单成功";
}
}
6.5.6.service
public interface OrderService {
public int saveOrder(Order order);
}
6.5.7.serviceImpl
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderMapper orderMapper;
@Override
public int saveOrder(Order order) {
//添加,将订单的信息添加到order中
return orderMapper.insert(order);
}
}
6.5.8.dao
@Mapper
public interface OrderMapper extends BaseMapper<Order> {
}
6.5.9.运行
7.服务治理
7.1.为什使用服务治理
上面的代码,因为我们生产者的ip和端口号都写死了,会出现一下的问题
1.如果商品微服务部署的地址发生改变,订单微服务也要跟着修改
2.没有办法使用负载均衡
3.一旦服务变得越来越多,人工维护调用关系困难
解决的方法:使用服务治理主件--所有的微服务都会自动的把自己的信息注册到该主件
7.2.什么是服务治理
服务治理是微服务架构中最核心最基本的模块。用于实现各个微服务的自动化注册与发现。
7.2.1.服务注册
在服务治理框架中,都会构建一个注册中心,每个服务单元向注册中心登记自己提供服务的详细信息。并在注册中心形成一张服务的清单,服务注册中心需要以心跳30s 90s的方式去监测清单中 的服务是否可用,如果不可用,需要在服务清单中剔除不可用的服务
7.2.2.服务发现
服务调用方向服务注册中心咨询服务,并获取所有服务的实例清单,实现对具体服务实例的访问。