注意:springcloudAlibaba兼容前两种
SpringCloud
SpringCloud集成了各种微服务功能组件,并基于SpringBoot实现了这些组件的自动装配,从而提供了良好的开箱即用体验:
服务拆分
- 微服务需要根据业务模块拆分,做到单一职责,不要重复开发相同务
- 微服务可以将业务暴露为接口,供其它微服务使用
- 不同微服务都应该有自己独立的数据库
微服务案例
项目结构
cloud-demo作为父工程,负责管理整个项目的依赖;下面有两个模块,分别代表订单服务和用户服务,只做对应的功能。每一个服务拥有独立的数据库。(虽然订单表依赖用户id,但是用户表和订单表不在一个数据库,不能直接连表查询)
可以同时启动这两个服务,然后通过访问结构获取服务。
例如:
通过user服务查询用户信息
http://localhost:8081/user/1
通过order服务查询订单信息
http://localhost:8080/order/101
微服务远程调用
那么如何根据订单id查询订单的同时,把订单所属的用户信息一起返回?
这需要用到微服务远程调用
很容易想到让order服务访问http://localhost:8081/user/+id通过user服务获取到对应的用户信息。
java发送http请求访问远程服务
如何让java代码发起http请求访问user服务呢?
spring提供了一个工具来发http请求:RestTemplate (不常用)
Eureka注册中心
介绍
作用:用来管理各种服务的,服务提供者将自己的ip端口等信息告诉注册中心,消费者通过注册中心获取想要服务的ip端口信息,这样就不需要将ip和端口在代码中硬编码了。
Eureka分类:
Eureka-server:是Eureka的服务端,即注册中心
Eureka-client:是Eureka的客户端,所有要使用注册中心的微服务都是客户端
问题解释:
- 消费者该如何获取服务提供者具体信息?
- 服务提供者启动时向eureka注册自己的信息
- eureka保存这些信息
- 消费者根据服务名称向eureka拉取提供者信息
- 如果有多个服务提供者,消费者该如何选择?
- 服务消费者利用负载均衡算法,从服务列表中挑选一个
- 消费者如何感知服务提供者健康状态?
- 服务提供者会每隔30秒向EurekaServer发送心跳请求,报告健康状态
- eureka会更新记录服务列表信息,心跳不正常会被剔除
- 消费者就可以拉取到最新的信息
Eureka的使用
搭建Eureka-server(注册中心)
第一步: 创建一个新的项目模块(Eureka注册中心服务也是一个微服务)
第二步:引入spring-cloud-starter-netflix-eureka-server的依赖
第三步:编写启动类,添加@EnableEurekaServer注解
第四步:添加application.yml文件,编写下面的配置:
然后访问:http://127.0.0.1:10086即可访问注册中心
注册服务到 Eureka-server
以user-service为例
第一步:在user-service项目引入spring-cloud-starter-netflix-eureka-client的依赖
第二步:在application.yml文件,编写下面的配置:
启动服务后,将自动注册到 Eureka-server
服务拉取/服务发现(以order-service从注册中心拉取user-service为例)
服务拉取是基于服务名称获取服务列表,然后在对服务列表做负载均衡
第一步:修改OrderService的代码,修改访问的url路径,用服务名代替ip、端口:
第二步:在order-service项目的启动类OrderApplication中的RestTemplate添加负载均衡注解:
@LoadBalanced的意思是,ResTemplate发起的请求要被负载均衡组件拦截和处理。
这样就直接能获取到对应的服务
Ribbon负载均衡
负载均衡流程
order服务通过一个不正常的链接发起http请求,会被ribbon负载均衡拦截器拦截,由它通过服务名称在注册中心进行服务拉取,获取到服务列表后,再通过某一种负载均衡策略选择其中一个作为最终的目标服务。
负载均衡策略
Ribbon的负载均衡规则是一个叫做IRule的接口来定义的,每一个子接口都是一种规则:
如何修改负载均衡策略?
方式一:码方式:在order-service中的OrderApplication类中,定义一个新的IRule:(全局策略)
方式二:配置文件方式:在order-service的application.yml文件中,添加新的配置也可以修改规则:(针对某一个微服务的策略)
Ribbon饥饿加载
Ribbon默认是采用懒加载,即第一次访问时才会去创建LoadBalanceClient,请求时间会很长。
而饥饿加载则会在项目启动时创建,降低第一次访问的耗时,通过下面配置开启饥饿加载:
Nacos注册中心
nacos安装与启动:csdn教程
docker安装:
docker pull nacos/nacos-server:1.2.0
docker run --env MODE=standalone --name nacos --restart=always -d -p 8848:8848 nacos/nacos-server:1.2.0
- MODE=standalone 单机版
- –restart=always 开机启动
- -p 8848:8848 映射端口
- -d 创建一个守护式容器在后台运行
http://localhost:8848/nacos/
服务注册到Nacos
第一步:在cloud-demo父工程中添加spring-cloud-alilbaba的管理依赖:
第二步:在各自服务模块中添加nacos的客户端依赖包:(删除掉eureka的)
第三步:修改user-service和order-service中的applicationyml文件,注释eureka地址,添加nacos地址:
其他是一样的,比如,负载均衡的访问其他服务。
Nacos服务分级存储模型
为了使得微服务具有抗灾能力,会将一个服务的多个实例部署到不同地方的机房集群中。一个服务消费者会首先选择同集群的服务,同集群不能用时再访问其他集群。
Nacos服务分级存储模型:
- 一级是服务,例如userservice
- 二级是集群,例如杭州或上海
- 三级是实例,例如杭州机房的某台部署了userservice的服务器
给服务实例添加集群属性
修改application.yml,添加如下内容:
一个服务要部署到不同集群,需要修改cluster-name后再运行新的实例。
Nacos的负载均衡策略NacosRule
在配置了集群实例后,要让order-service优先访问本地集群的user-service服务,需要对负载均衡策略进行调整。采用Nacos的NacosRule策略。
NacosRule负载均衡策略
- 优先选择同集群服务实例列表
- 本地集群找不到提供者,才去其它集群寻找,并且会报警告
- 确定了可用实例列表后,再采用随机负载均衡挑选实例
Nacos加权负载均衡
实例的权重控制
- Nacos控制台可以设置实例的权重值,0~1之间
- 同集群内的多个实例,权重越高被访问的频率越高
- 权重设置为0则完全不会被访问
Nacos环境隔离
Nacos中服务存储和数据存储的最外层都是一个名为namespace的东西,用来做最外层隔离。
命名空间会将服务和数据完全隔离开,无法相互访问。
可以将相关度比较高的服务放到一个组,例如,订单和支付。
Nacos环境隔离配置:
- 在Nacos控制台可以创建namespace,用来隔离不同环境
- 然后填写一个新的命名空间信息:
- 保存后会在控制台看到这个命名空间的id:
- 修改order-service的application.yml,添加namespace
Nacos和Eureka对比
-
nacos注册中心中的服务实例有着临时实例和非临时实例之分。
-
临时实例会定时发送心跳信息给nacos,若超时未收到心跳信息,就将该服务实例剔除。
-
而,nacos会主动询问非临时实例,是否存活,若未存活,nacos会一直等待非临时实例恢复。
-
服务消费者回每隔30s拉取一次服务列表bin缓存在内存中。
-
若在30s未到,就出现了服务实例崩溃,nacos会主动发送服务列表变更给消费者。
如何注册成临时或非临时实例?
进行如下配置:
共同点
- 都支持服务注册和服务拉取
- 都支持服务提供者心跳方式做健康检测
区别
- Nacos支持服务端主动检测提供者状态:临时实例采用心跳模式,非临时实例采用主动检测模式
- 临时实例心跳不正常会被剔除,非临时实例则不会被剔除
- Nacos支持服务列表变更的消息推送模式,服务列表更新更及时
- Nacos集群默认采用AP方式,当集群中存在非临时实例时,采用CP模式;Eureka采用AP方式(CAP原理,Nacos支持模式切换)