目录
1、认识微服务
1.1 单体架构
1.2 分布式架构
1.3 微服务
1.4 SpringCloud
2、服务拆分和远程调用
2.1 服务拆分原则
2.2 服务拆分示例
2.2.1 导入Demo
2.2.2 导入SQL
2.1 服务拆分原则
2.2 服务拆分示例
2.2.1 导入Demo
2.2.2 导入SQL
2.3.2 注册RestTemplate
2.3.3 实现远程调用
2.4.提供者与消费者
3、注册中心
3.1 Eureka
3.1.1 创建eureka-server服务
3.1.2 引入eureka依赖
3.1.3 编写启动类
3.1.4 编写配置文件
3.1.5 启动服务
3.1.6 服务注册
3.1.7 服务发现
3.2 Nacos
3.2.1 服务注册到nacos
3.2.2 服务分级存储模型
3.2.3 权重配置
3.2.4 环境隔离
4、Eureka和Nacos的区别
5、本次案例代码仓库地址
1、认识微服务
随着互联网行业的发展,对服务的要求也越来越高,服务架构也从单体架构逐渐演变为现在流行的微服务架构。这些架构之间有怎样的差别呢?
1.1 单体架构
单体架构:将业务的所有功能集中在一个项目中开发,打成一个包部署。
优点:
- 架构简单
- 部署成本低
缺点:
- 耦合度高(维护困难、升级困难)
适合小型项目。例如:学生管理系统
1.2 分布式架构
分布式架构:根据业务功能对系统做拆分,每个业务功能模块作为独立项目开发,称为一服务。
优点:
- 降低服务耦合
- 有利于服务升级和拓展
缺点:
- 服务调用关系错综复杂
适合大型互联网项目,例如:京东、淘宝
分布式架构的出色代表当属Dubbo,大家有兴趣的可以看看我这篇博客:SpringBoot整合Dubbo学习总结【概述,快速入门,高级特性,案例所敲代码】_一切总会归于平淡的博客-CSDN博客
1.3 微服务
微服务的架构特征:
优点:
- 单一职责:微服务拆分粒度更小,每一个服务都对应唯一的业务能力,做到单一职责
- 自治:团队独立、技术独立、数据独立,独立部署和交付
- 面向服务:服务提供统一标准的接口,与语言和技术无关
- 隔离性强:服务调用做好隔离、容错、降级,避免出现级联问题
缺点:
- 架构非常复杂
- 运维、监控、部署难度提高
微服务的上述特性其实是在给分布式架构制定一个标准,进一步降低服务之间的耦合度,提供服务的独立性和灵活性。做到高内聚,低耦合。
因此,可以认为微服务是一种经过良好架构设计的分布式架构方案 。
在Java领域最引人注目的就是SpringCloud提供的方案了。
1.4 SpringCloud
SpringCloud是目前国内使用最广泛的微服务框架。
官网地址:Spring Cloud。
SpringCloud集成了各种微服务功能组件,并基于SpringBoot实现了这些组件的自动装配,从而提供了良好的开箱即用体验。
其中常见的组件包括:
名称 | 组件 |
---|---|
服务注册发现 | Eureka |
| Nacos |
| Consul |
服务远程调用 | OpenFeign |
| Dubbo |
服务链路监控 | Zipkin |
| Sleuth |
统一配置管理 | SpringCloudConfig |
| Nacos |
统一网关路由 | SpringCloudGateway |
| Zuul |
流控、降级、保护 | Hystix |
| Sentinel |
另外,SpringCloud底层是依赖于SpringBoot的,并且有版本的兼容关系,如下:
大家可以根据自己的需求去选择。
2、服务拆分和远程调用
任何分布式架构都离不开服务的拆分,微服务也是一样。
2.1 服务拆分原则
- 单一职责:不同微服务,不要重复开发相同业务。
- 数据独立:不要访问其它微服务的数据库。
- 面向服务:将自己的业务暴露为接口,供其它微服务调用。
2.2 服务拆分示例
cloud-demo:父工程,管理依赖
- order-service:订单微服务,负责订单相关业务
- user-service:用户微服务,负责用户相关业务
2.2.1 导入Demo
Demo工程地址:cloud项目初始化: 初始化项目
不会使用Git的小伙伴可以看这篇文章:Git之远程仓库【码云,命令行操作,IDEA操作】_一切总会归于平淡的博客-CSDN博客
2.2.2 导入SQL
SQL也一起放在Demo工程里了
不过大家记得一定要分开建立数据库,不要建在一个数据库下面。
然后我们做为了方便管理服务的启动。
大家可以看这篇博客:第一次创建微服务项目,如何快速启动多个模块?,idea如何开启Run DashBoard(显示services)_一切总会归于平淡的博客-CSDN博客
任何分布式架构都离不开服务的拆分,微服务也是一样。
2.1 服务拆分原则
- 单一职责:不同微服务,不要重复开发相同业务。
- 数据独立:不要访问其它微服务的数据库。
- 面向服务:将自己的业务暴露为接口,供其它微服务调用。
2.2 服务拆分示例
cloud-demo:父工程,管理依赖
- order-service:订单微服务,负责订单相关业务
- user-service:用户微服务,负责用户相关业务
2.2.1 导入Demo
Demo工程地址:cloud项目初始化: 初始化项目
不会使用Git的小伙伴可以看这篇文章:Git之远程仓库【码云,命令行操作,IDEA操作】_一切总会归于平淡的博客-CSDN博客
2.2.2 导入SQL
SQL也一起放在Demo工程里了
不过大家记得一定要分开建立数据库,不要建在一个数据库下面。
然后我们做为了方便管理服务的启动。
大家可以看这篇博客:第一次创建微服务项目,如何快速启动多个模块?,idea如何开启Run DashBoard(显示services)_一切总会归于平淡的博客-CSDN博客
2.3.2 注册RestTemplate
首先,我们在order-service服务中的OrderApplication启动类中,注册RestTemplate实例:
2.3.3 实现远程调用
修改order-service服务中的com.jie.order.service包下的OrderService类中的queryOrderById方法:
运行查看效果。
2.4.提供者与消费者
在服务调用关系中,会有两个不同的角色:
- 服务提供者:一次业务中,被其它微服务调用的服务。(提供接口给其它微服务)user-service
- 服务消费者:一次业务中,调用其它微服务的服务。(调用其它微服务提供的接口)order-service
但是,服务提供者与服务消费者的角色并不是绝对的,而是相对于业务而言。
如果服务A调用了服务B,而服务B又调用了服务C,服务B的角色是什么?
- 对于A调用B的业务而言:A是服务消费者,B是服务提供者
- 对于B调用C的业务而言:B是服务消费者,C是服务提供者
因此,服务B既可以是服务提供者,也可以是服务消费者。
3、注册中心
假如我们的服务提供者user-service部署了多个实例,如图:
问题随之即来:
- 服务消费者该如何获取服务提供者的地址信息?
- 多个服务提供者,消费者该如何选择?
- 消费者如何得知服务提供者的健康状态?
这些问题都需要利用SpringCloud中的注册中心来解决,其中广为人知的就是Eureka和Nacos了(个人认知)。
注册中心的作用:
消费者该如何获取服务提供者具体信息?
- 服务提供者启动时向注册中心注册自己的信息
- 注册中心保存这些信息
- 消费者根据服务名称向注册中心拉取提供者信息
如果有多个服务提供者,消费者该如何选择?
- 服务消费者利用负载均衡算法,从服务列表中挑选一个
消费者如何感知服务提供者健康状态?
- 服务提供者会每隔多少秒向注册中心发送心跳请求,报告健康状态
- 注册中心会更新记录服务列表信息,心跳不正常会被剔除
- 消费者就可以拉取到最新的信息
3.1 Eureka
注册中心的作用的已经介绍完毕,接下来我们先演示Eureka,后面再演示Nacos。
首先搭建注册中心服务端:eureka-server,这必须是一个独立的微服务。
3.1.1 创建eureka-server服务
在cloud-demo父工程下,创建一个子模块:
3.1.2 引入eureka依赖
引入SpringCloud为eureka提供的starter依赖:(在eureka-server下)
代码语言:javascript复制<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
3.1.3 编写启动类
给eureka-server服务编写一个启动类,一定要添加一个@EnableEurekaServer注解,开启eureka的注册中心功能:
代码语言:javascript复制package com.jie.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
3.1.4 编写配置文件
编写一个application.yml文件,内容如下:
代码语言:javascript复制server:
port: 2022
spring:
application:
name: eureka-server
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:2022/eureka
3.1.5 启动服务
启动微服务,然后在浏览器访问:http://127.0.0.1:2022/
看到下面结果就是成功了:
3.1.6 服务注册
下面,我们将user-service注册到eureka-server中去。
1、引入依赖
在user-service的pom文件中,引入下面的eureka-client依赖:
代码语言:javascript复制<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2、配置文件
在user-service中,修改application.yml文件,添加服务名称、eureka地址:
代码语言:javascript复制application:
name: userservice
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:2022/eureka
3、启动多个user-service实例
为了演示一个服务有多个实例的场景,我们添加一个SpringBoot的启动配置,再启动一个user-service。
首先,复制原来的user-service启动配置:
然后,在弹出的窗口中,填写信息:
现在,SpringBoot窗口会出现两个user-service启动配置,启动两个user-service实例。
查看eureka-server管理页面:
3.1.7 服务发现
下面,我们将order-service的逻辑修改:向eureka-server拉取user-service的信息,实现服务发现。
1、引入依赖
之前说过,服务发现、服务注册统一都封装在eureka-client依赖,因此这一步与服务注册时一致。
在order-service的pom文件中,引入下面的eureka-client依赖:
代码语言:javascript复制<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2、配置文件
服务发现也需要知道eureka地址,因此第二步与服务注册一致,都是配置eureka信息:
在order-service中,修改application.yml文件,添加服务名称、eureka地址:
代码语言:javascript复制spring:
application:
name: orderservice
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:2022/eureka
3、服务拉取和负载均衡
最后,我们要去eureka-server中拉取user-service服务的实例列表,并且实现负载均衡。
不过这些动作不用我们去做,只需要添加一些注解即可。
在order-service的OrderApplication中,给RestTemplate这个Bean添加一个@LoadBalanced注解:
修改order-service服务中的com.jie.order.service包下的OrderService类中的queryOrderById方法。修改访问的url路径,用服务名代替ip、端口:
3.2 Nacos
Nacos是阿里巴巴的产品,现在是SpringCloud中的一个组件。相比Eureka功能更加丰富,在国内受欢迎程度较高。
安装方式可以参考Nacos安装指南Windows和Linux_一切总会归于平淡的博客-CSDN博客_yum 安装nacos
3.2.1 服务注册到nacos
Nacos是SpringCloudAlibaba的组件,而SpringCloudAlibaba也遵循SpringCloud中定义的服务注册、服务发现规范。因此使用Nacos和使用Eureka对于微服务来说,并没有太大区别。
主要差异在于:
- 依赖不同
- 服务地址不同
1、引入依赖
在cloud-demo父工程的pom文件中的<dependencyManagement>中引入SpringCloudAlibaba的依赖:
代码语言:javascript复制<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.6.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
然后在user-service和order-service中的pom文件中引入nacos-discovery依赖:
代码语言:javascript复制<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
注意:如果你跟着前面配置了Eureka不要忘了注释掉Eureka的依赖。
2、配置nacos地址
在user-service和order-service的application.yml中添加nacos地址:
代码语言:javascript复制spring:
cloud:
nacos:
server-addr: localhost:8848
3、重启
重启微服务后,登录nacos管理页面,可以看到微服务信息:
3.2.2 服务分级存储模型
一个服务可以有多个实例,例如我们的user-service,可以有:
- 127.0.0.1:8081
- 127.0.0.1:8082
- 127.0.0.1:8083
假如这些实例分布于全国各地的不同机房,例如:
- 127.0.0.1:8081,在上海机房
- 127.0.0.1:8082,在上海机房
- 127.0.0.1:8083,在杭州机房
Nacos就将同一机房内的实例 划分为一个集群。
也就是说,user-service是服务,一个服务可以包含多个集群,如杭州、上海,每个集群下可以有多个实例,形成分级模型,如图:
微服务互相访问时,应该尽可能访问同集群实例,因为本地访问速度更快。当本集群内不可用时,才访问其它集群。例如:
杭州机房内的order-service应该优先访问同机房的user-service。
1、给user-service配置集群
修改user-service的application.yml文件,添加集群配置:
重启两个user-service实例后,我们可以在nacos控制台看到下面结果:
我们再次复制一个user-service启动配置,添加属性:
代码语言:javascript复制-Dserver.port=8083 -Dspring.cloud.nacos.discovery.cluster-name=SH
启动UserApplication3后再次查看nacos控制台:
2、同集群优先的负载均衡
默认的ZoneAvoidanceRule并不能实现根据同集群优先来实现负载均衡。
因此Nacos中提供了一个NacosRule的实现,可以优先从同集群中挑选实例。
1、给order-service配置集群信息
修改order-service的application.yml文件,添加集群配置:
2、修改负载均衡规则
修改order-service的application.yml文件,修改负载均衡规则:
重新启动order-service。然后发送请求看看。
可以看到1 和 2 都有被访问到,我们看看3.
3.2.3 权重配置
实际部署中会出现这样的场景:
服务器设备性能有差异,部分实例所在机器性能较好,另一些较差,我们希望性能好的机器承担更多的用户请求。
但默认情况下NacosRule是同集群内随机挑选,不会考虑机器的性能问题。
因此,Nacos提供了权重配置来控制访问频率,权重越大则访问频率越高。
在nacos控制台,找到user-service的实例列表,点击编辑,即可修改权重:
注意:如果权重修改为0,则该实例永远不会被访问
3.2.4 环境隔离
Nacos提供了namespace来实现环境隔离功能。
- nacos中可以有多个namespace
- namespace下可以有group、service等
- 不同namespace之间相互隔离,例如不同namespace的服务互相不可见
1 、创建namespace
默认情况下,所有service、data、group都在同一个namespace,名为public:
我们可以点击页面新增按钮,添加一个namespace:
然后,填写表单:
就能在页面看到一个新的namespace:
2、给微服务配置namespace
给微服务配置namespace只能通过修改配置来实现。
例如,修改order-service的application.yml文件:
重启order-service后,访问控制台,可以看到下面的结果:
此时访问order-service,因为namespace不同,会导致找不到userservice,控制台会报错:
4、Eureka和Nacos的区别
- Nacos与eureka的共同点
- 都支持服务注册和服务拉取
- 都支持服务提供者心跳方式做健康检测
- Nacos与Eureka的区别
- Nacos支持服务端主动检测提供者状态:临时实例采用心跳模式,非临时实例采用主动检测模式
- 临时实例心跳不正常会被剔除,非临时实例则不会被剔除
- Nacos支持服务列表变更的消息推送模式,服务列表更新更及时
- Nacos集群默认采用AP方式,当集群中存在非临时实例时,采用CP模式;Eureka采用AP方式
5、本次案例代码仓库地址
springCloud案例演示: springcloud学习演示
若有收获,就点个赞吧