初识SpringCloud,SpringCloud简单搭建

1、架构演变过程

单体架构

我们最先接触的单体架构,整个系统就只有一个工程,打包往往是打成了 war 包,然后部署
到单一 tomcat 上面,这种就是单体架构,如图:
在这里插入图片描述
假如系统按照功能划分了,商品模块,购物车模块,订单模块,物流模块等等模块。那么所
有模块都会在一个工程里面,这就是单体架构。

单体架构优点

  1. 结构简单,部署简单
  2. 所需的硬件资源少
  3. 节省成本

单体架构缺点

  1. 版本迭代慢,往往改动一个代码会影响全局
  2. 不能满足一定并发的访问
  3. 代码维护困难,所有代码在一个工程里面,存在被其他人修改的风险

单体架构横向扩展

随着业务的拓展,公司的发展,单体架构慢慢的不能满足我们的需求,我们需要对架构进行
变动,我们能够想到的最简单的办法就是加机器,对应用横向扩展。
如图:
在这里插入图片描述
这种架构貌似暂时解决了我们的问题,但是用户量慢慢增加后,我们只能通过横向加机器来
解决,还是会存在版本迭代慢,代码维护困难的问题。而且用户请求往往是读多写少的情况,
所以可能真正需要扩容的只是商品模块而已,而现在是整个工程都扩容了,这无形中是一种
资源的浪费,因为其他模块可能根本不需要扩容就可以满足需求。所以我们有必要对整个工
程按照模块进行拆分,拆分后的架构图如下:
在这里插入图片描述
模块拆分后,模块和模块之间是需要通过接口调用的方式进行通信,模块和模块之间通过分
流软件进行负载均衡。这个架构解决前面的资源浪费问题和代码管理问题,因为我们是对系
统拆分了,各个模块都有单独的工程,比如我修改商品模块,就不需要担心会不会影响购物
车模块。但是这种架构扩展非常麻烦,一旦需要横向加机器,或者减机器都需要修改 nginx
配置,一旦机器变多了以后,nginx 的配置量就是一个不能完成的工作。OK,这时候 SOA 服
务治理框架就应运而生,架构图如下:
在这里插入图片描述
基于注册中心的 SOA 框架,扩展是非常方便的,因为不需要维护分流工具,但我们启动应
用的时候就会把服务通过 http 的方式注册到注册中心。
在 SOA 框架中一般会有三种角色:1、注册中心 2、服务提供方 3、服务消费方

  1. 注册中心
    在注册中心维护了服务列表
  2. 服务提供方
    服务提供方启动的时候会把自己注册到注册中心
  3. 服务消费方
    服务消费方启动的时候,把获取注册中心的服务列表,然后调用的时候从这个服务列表中选
    择某一个去调用。

微服务工程的特点:

  1. 扩展灵活
  2. 每个应用都规模不大
  3. 服务边界清晰,各司其职
  4. 打包应用变多,往往需要借助 CI 持续集成工具

2、搭建简单的微服务工程

2.1、注册中心搭建

Springcloud 中,我们选择 eureka 作为注册中心,springcloud 工程是基于 springboot 工程的。

pom.xml 中 jar 包依赖:

在这里插入图片描述

Springcloud 的版本

在这里插入图片描述

Eureka 服务端启动器导入

在这里插入图片描述

Springcloud 的依赖仓库导入

在这里插入图片描述

Application.properties 配置文件

在这里插入图片描述

启动类

在这里插入图片描述

2.2、服务提供方

Pom 的 jar 包依赖

其他都跟 eureka 服务端是一样的,只是服务提供方要把服务注册到 eureka
服务端,所以服务提供方就是 eureka 的客户端,所以需要导入 eureka 客户端的启动器。
在这里插入图片描述

bootstrap.properties

在这里插入图片描述

启动类

在这里插入图片描述

服务消费方

pom 和属性配置文件基本上差不多,消费要负责调用服务提供方,所以需要调用客户端
在这里插入图片描述
服务调用的时候就根据服务提供方的服务名称来调用的
在这里插入图片描述
服务提供方的名称,再加上服务提供方的接口名就可以完成调用了。
服务提供方和服务消费启动的时候都会往服务注册中心注册服务,eureka 服务端也可以通过
界面查看到服务注册情况
在这里插入图片描述

3、Eureka 用户认证

连接到 eureka 的时候需要带上连接的用户名和密码

Eureka 服务端改造

添加启动器

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

代码配置,关闭 csrf 验证

@EnableWebSecurity
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //关闭csrf
        http.csrf().disable();
        //开启认证:URL格式登录必须是httpBasic
        http.authorizeRequests().anyRequest().authenticated().and().httpBasic();
    }
}

Application.yml 配置

spring:
  security:
    user:
      name: admin
      password: admin
    basic:
      enabled: true

Eureka 客户端改造

跟 eureka 连接的时候要带上用户名密码

eureka:
  client:
    serviceUrl:
      defaultZone: http://admin:admin@localhost:8763/eureka/

4、服务续约保活

当客户端启动想 eureka 注册了本身服务列表后,需要隔段时间发送一次心跳给 eureka 服务
端来证明自己还活着,当 eureka 收到这个心跳请求后才会知道客户端还活着,才会维护该
客户端的服务列表信息。一旦因为某些原因导致客户端没有按时发送心跳给 eureka 服务端,
这时候 eureka 可能会认为你这个客户端已经挂了,它就有可能把该服务从服务列表中删除
掉。

有关续约保活的配置客户端配置

#服务续约,心跳的时间间隔
eureka.instance.lease-renewal-interval-in-seconds=30
#如果从前一次发送心跳时间起,90 秒没接受到新的心跳,讲剔除服务
eureka.instance.lease-expiration-duration-in-seconds=90
#表示 eureka client 间隔多久去拉取服务注册信息,默认为 30 秒
eureka.client.registry-fetch-interval-seconds=30

服务端配置

#自我保护模式,当出现出现网络分区、eureka 在短时间内丢失过多客户端时,
会进入自我保护模式,即一个服务长时间没有发送心跳,eureka 也不会将其删
除,默认为 true
eureka.server.enable-self-preservation=true
#Eureka Server 在运行期间会去统计心跳失败比例在 15 分钟之内是否低
于 85%,如果低于 85%,Eureka Server 会将这些实例保护起来
eureka.server.renewal-percent-threshold=0.85
#eureka server 清理无效节点的时间间隔,默认 60000 毫秒,即 60 秒
eureka.server.eviction-interval-timer-in-ms=60000

5、Eureka 健康检测

Eureka 默认的健康检测只是你校验服务连接是否是 UP 还是 DOWN 的,然后客户端只会调用
状态为 UP 状态的服务,但是有的情况下,虽然服务连接是好的,但是有可能这个服务的某
些接口不是正常的,可能由于需要连接 Redis,mongodb 或者 DB 有问题导致接口调用失败,
所以理论上服务虽然能够正常调用,但是它不是一个健康的服务。所以我们就有必要对这种
情况做自定义健康检测。

Application.properties 配置

#开启健康检测
#健康检测
eureka.client.healthcheck.enabled=true

自定义健康检测代码


public static boolean canVisitDb = true;
    /*
    * 这个接口只为了检测db连接是否ok
    * */
    @RequestMapping("/db/{can}")
    public void setDb(@PathVariable boolean can) {
        canVisitDb = can;
    }


@Configuration
public class MyHealthIndicator implements HealthIndicator {
 
	@Override
	public Health health() {
		if(ProviderController.isCanLinkDb){
			return new Health.Builder(Status.UP).build();
		}else{
			return new Health.Builder(Status.DOWN).build();
		}
	}
 
}

@Configuration
public class MyHealthCheckHandler implements HealthCheckHandler {
 
	@Autowired
	private MyHealthIndicator myHealthIndicator;
	
	@Override
	public InstanceStatus getStatus(InstanceStatus instanceStatus) {
		Status status = myHealthIndicator.health().getStatus();
		if(status.equals(Status.UP)){
			return InstanceStatus.UP;
		}else{
			return InstanceStatus.DOWN;
		}
	}
 
}

我们可以在 health 方法里面去连接数据库,如果连接异常了则返回 DOWN,如果没异常则
方法 UP,这个 health 方法是线程去掉的,隔一段时间掉一次

检测检测依赖的 jar 包

	    <dependency>
	        <groupId>org.springframework.boot</groupId>
	        <artifactId>spring-boot-starter-actuator</artifactId>
	    </dependency>

6、服务下线

比如有些情况是服务主机意外宕机了,也就意味着服务没办法给 eureka 心跳信息了,但是
eureka 在没有接受到心跳的情况下依赖维护该服务 90s,在这 90s 之内可能会有客户端调用
到该服务,这就可能会导致调用失败。所以我们必须要有一个机制能手动的立马把宕机的服
务从 eureka 服务列表中清除掉,避免被服务调用方调用到。

调用服务下线的接口:

这个接口是调用 eureka 服务端的接口
http://localhost:8763/eureka/apps/MICRO-ORDER/localhost:micro-order:8084
在这里插入图片描述

7、Eureka 高可用

Eureka 热备份的架构图如下

在这里插入图片描述
整个微服务中存在多个 eureka 服务,每个 eureka 服务都是相互复制的,会把客户端注册进
来的服务复制到 eureka 集群中的其他节点里面来。其实简单来说就是 eureka 每个节点相互
复制。

具体配置如下:

端口为 8761 的 eureka 服务端把自己注册到 8762 的 eureka 服务端
在这里插入图片描述
同样的道理,8762 注册到 8761
在这里插入图片描述
配置存在在两个配置文件中
在这里插入图片描述

启动的时候按照指定配置文件启动

java -jar springcloud-eureka.jar --spring.profiles.active=8761

在这里插入图片描述

8、Ribbon API

Ribbon 是一个独立的组件,是用来进行远程接口调用的,代码如下
在这里插入图片描述
通过 getForObject 方法可以掉到用 micro-order 服务的,queryUser 接口。然后在调用期间会
存在负载均衡,micro-order 服务对应有几个服务实例就会根据负载均衡算法选择某一个去
调用。

Get 请求
getForEntity:此方法有三种重载形式,分别为:

getForEntity(String url, Class<T> responseType)
getForEntity(String url, Class<T> responseType, Object... uriVariables)
getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables)
getForEntity(URI url, Class<T> responseType)

注意:此方法返回的是一个包装对象 ResponseEntity其中 T 为 responseType 传入类型,
想拿到返回类型需要使用这个包装类对象的 getBody()方法

getForObject:此方法也有三种重载形式,这点与 getForEntity 方法相同:

getForObject(String url, Class<T> responseType)
getForObject(String url, Class<T> responseType, Object... uriVariables)
getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables)
getForObject(URI url, Class<T> responseType)

注意:此方法返回的对象类型为 responseType 传入类型

Post 请求
post 请求和 get 请求都有ForEntity 和ForObject 方法,其中参数列表有些不同,除了这两个
方法外,还有一个 postForLocation 方法,其中 postForLocation 以 post 请求提交资源,并返
回新资源的 URI

postForEntity:此方法有三种重载形式,分别为:

postForEntity(String url, Object request, Class<T> responseType, Object... uriVariables)
postForEntity(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables)
postForEntity(URI url, Object request, Class<T> responseType)

注意:此方法返回的是一个包装对象 ResponseEntity其中 T 为 responseType 传入类型,
想拿到返回类型需要使用这个包装类对象的 getBody()方法

postForObject:此方法也有三种重载形式,这点与 postForEntity 方法相同:

postForObject(String url, Object request, Class<T> responseType, Object... uriVariables)
postForObject(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables)
postForObject(URI url, Object request, Class<T> responseType)

注意:此方法返回的对象类型为 responseType 传入类型

postForLocation:此方法中同样有三种重载形式,分别为:

postForLocation(String url, Object request, Object... uriVariables)
postForLocation(String url, Object request, Map<String, ?> uriVariables)
postForLocation(URI url, Object request)

注意:此方法返回的是新资源的 URI,相比 getForEntity、getForObject、postForEntity、
postForObject 方法不同的是这个方法中无需指定返回类型,因为返回类型就是 URI,通过
Object… uriVariables、Map<String, ?> uriVariables 进行传参依旧需要占位符,参看 postForEntity
部分代码

9、负载均衡算法

在这里插入图片描述

//线性轮训
new RoundRobinRule();
//可以重试的轮训
new RetryRule();
//根据运行情况来计算权重
new WeightedResponseTimeRule();
//过滤掉故障实例,选择请求数最小的实例
new BestAvailableRule();
//随机
new RandomRule();

10、Ribbon 配置

Application.properties 配置

#点对点直连测试配置
# 关闭 ribbon 访问注册中心 Eureka Server 发现服务,但是服务依旧会注
册。
#true 使用 eureka false 不使用
ribbon.eureka.enabled=true
spring.cloud.loadbalancer.retry.enabled=true
#指定调用的节点
micro-order.ribbon.listOfServers=localhost:8001
#单位 ms ,请求连接超时时间
micro-order.ribbon.ConnectTimeout=1000
#单位 ms ,请求处理的超时时间
micro-order.ribbon.ReadTimeout=2000
micro-order.ribbon.OkToRetryOnAllOperations=true
#切换实例的重试次数
micro-order.ribbon.MaxAutoRetriesNextServer=2
#对当前实例的重试次数 当 Eureka 中可以找到服务,但是服务连不上时将会
重试
micro-order.ribbon.MaxAutoRetries=2
micro-order.ribbon.NFLoadBalancerRuleClassName=com.netfli
x.loadbalancer.RandomRule
micro-order.ribbon.NFLoadBalancerPingClassName=com.netfli
x.loadbalancer.PingUrl

代码配置

使用@RibbonClients 加载配置

在这里插入图片描述
这个配置类只针对 micro-order 服务,微服务系统里面有很多服务,这就可以区别化配置。

配置 configuration 配置类的时候,一定要注意,配置类不能陪@ComponentScan 注解扫描到,
如果被扫描到了则该配置类就是所有服务共用的配置了。
在这里插入图片描述

11、Ribbon 单独使用

Ribbon 是一个独立组件,可以脱离 springcloud 使用的
在这里插入图片描述
需要依赖两个 jar
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一名技术极客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值