SpringCloud Netflix-springcloudnetflix(二)

本文涉及的产品
传统型负载均衡 CLB,每月750个小时 15LCU
日志服务 SLS,月写入数据量 50GB 1个月
EMR Serverless StarRocks,5000CU*H 48000GB*H
简介: SpringCloud Netflix-springcloudnetflix

SpringCloud Netflix-springcloudnetflix(一)https://developer.aliyun.com/article/1469568


Eureka服务注册与发现

什么是服务治理


springcloud 封装了netflix的Eureka模块实现服务治理
在传统的rpc远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,管理比较复杂所以需要有一个东西去治理他,管理服务与服务之间的依赖关系,负载均衡,容错等 实现服务发现与注册

这个是有人要问了:什么时服务的注册与发现呢???

问得好,

答案:
Eureka采用了CS也就是服务器和客户端的架构模式,Eureka Server作为服务注册中心,来管理微服务,也可以理解成用springboot来开发的一个个微服务,他们在Eureka的位置就是Eureka client,他们用心跳来告诉服务端自己是可以用的
我们可以用Eureka server就可以监控各个微服务的状态,同时也有一系列的保证机制,比如心跳检测,
我们的服务提供者和消费者的例子就是这样的,
服务提供者:在启动后将把自己当前的信息,通讯地址等以别名的方式注册到注册中心也就是Eureka server中
消费者:用别名的的形式,去获取服务的信息和通讯地址,之后实现本地调用RPC调用框架的设计思想
注册中心负责管理服务之间的依赖关系(服务治理),在任何的远程RPC中都会有一个注册中心,通过注册中心来获取服务的信息和接口地址

下图是脑图中对于Eureka两大组件的作用和功能介绍

  • Eureka server
  • Eureka client

单项目Eurekademo

老步骤:

  • 建模块
  • 添加依赖pom
  • yml配置文件
  • 主启动类
  • 业务编码

创建cloud-eureka-server7001模块

之后导入我们要用到的依赖

<dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        <dependency>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web  -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
    </dependencies>

这里Eureka的服务端新老版本也有变化

之后就是配置了yml

server:
  port: 7001
eureka:
  instance:
    hostname: localhost  #eureka服务端的实例名字
  client:
    register-with-eureka: false    #表识不向注册中心注册自己
    fetch-registry: false   #表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务
     service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/    #设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址

之后的主启动类的编写

package com.atguigu.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer
@SpringBootApplication
public class EurekaMain7001 {
    public static void main(String[] args) {
        SpringApplication.run(EurekaMain7001.class,args);
    }
}

@EnableEurekaServer加上个注解就是Eureka的服务端了,我们并不需要写什么业务员,启动之后访问

7001端口就可以看道Eureka的注册中心啦

服务的注册

cloud-provider-payment8001我们的目光回到服务提供者

Eurekashi1 C/S架构


所以我们想要将服务提供者注册道服务中心,还需要导入一个依赖,就是Eureka client的依赖抱

<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kBh2RWke-1648908821908)(https://cdn.jsdelivr.net/gh/Doomwatcher2004/my-image-host@master/ img /image-20210819230600170.png)]

之后就是配置文件了

eureka:
  client:
    register-with-eureka: true
    fetchRegistry: true
    service-url:
      defaultZone: http://localhost:7001/eureka

配置解读:

  1. register-with-eureka:true 表示自己会被注册到服务中心
  2. fetchRegistry:true表示自己不是服务中心,需要检索服务
  3. defaultZone要注册的服务中心的地址

主启动类

package com.atguigu.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@EnableEurekaClient
@SpringBootApplication
public class PaymentMain8001 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8001.class,args);
    }
}

@EnableEurekaClient表示自己的客户端,

之后就是测试了

  1. 先启动注册中心
  2. 之后启动需要注册的注册中心
  3. 访问注册中心即可

微服务名称配置

Eureka的自我保护机制

当Eureka一定时间内没有检测到服务的心跳或者短时间内丢失了多个服务,那么服务端就会认为是网络故障或者是一系列i意外的发生

此时不应该注销任何的服务。同时新的服务也可以继续进来,

设计哲学


好死不如赖活着


Eureka宁可保护错误的服务信息,也不会去轻易的注销服务

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KVWJjlqP-1648908821910)(https://cdn.jsdelivr.net/gh/Doomwatcher2004/my-image-host@master/ img /image-20210819233339779.png)]

Eureka集群原理

Eureka集群原理说明:

搭建注册中心集群

参考我们的注册中心7001,搭建一个一模一样的注册中心

在搭建之前请去修改一下映射文件,

找到C:\Windows\System32\drivers\etc路径下的hosts文件,修改

因为我们之前使用都是一个单机的项目,我们要集群那么不能使用 localhost,他会被识别成一样的路径

我们修改一些映射

如:

  1. 127.0.0.1  eureka7001.com
  2. 127.0.0.1  eureka7002.com

本质还是localhost但是却是两个不一样的映射

导入和7001相同的依赖

之后分别修改

7001配置文件

server:
  port: 7001
eureka:
  instance:
    hostname: eureka7001.com    #eureka服务端的实例名字
  client:
    register-with-eureka: false    #表识不向注册中心注册自己
    fetch-registry: false   #表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务
    service-url:
      defaultZone: http://eureka7002.com:7002/eureka/    #设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址

7002

server:
  port: 7002
eureka:
  instance:
    hostname: eureka7002.com #eureka服务端的实例名字
  client:
    register-with-eureka: false    #表识不向注册中心注册自己
    fetch-registry: false   #表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/     #设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址

集群其实就是一句话:相互守望,

之后我们还要修改一下 服务提供者 8001的注册地址,他现在同时需要注册到两个注册中心去

service-url:
  defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka  #集群版

测试:

  1. 先要启动EurekaServer,7001/7002服务
  2. 再要启动服务提供者provider,8001服务
  3. 再要启动消费者,80
  4. http://localhost/consumer/payment/get/1

查看结果即可

支付服务提供者8001集群环境构建

同上搭建一个除了端口号和8001一抹一样的模块

cloud-provider-payment8002

Ribbon 负载均衡

现在的RIbbon已经进入维护模式了

现有他的代替解决方案是

LB(负载均衡)

负载均衡分类

集中式LB

即在服务的消费方和提供方之间使用独立的LB设施,(可以是硬件,如f5,也可以是软件,如nginx),由该设施负责把访问请求通过某种请求策略转发至服务的提供方;

进程内LB

将L B逻辑集成在消费方,消费方从服务注册中心获取那些地址可用,让后自己再从这些地址选择出一个合适的服务器.

Ribbon 就是属于进程内LB,他只是一个类库,集成于消费房的进程,消费房通过他来获取到服务器的提供方地址

Ribbon能够做些什么

就是在消费者中对服务提供者进行负载均衡操作,

默认是轮询的方式,

1   2   3  再来一遍   1  2  3

负载均衡+RestTemplate调用架构说明

总结:


Ribbon其实就是一个软负载均衡的客户端组件,他可以和其他所需请求的客户端结合使用,和eureka结合只是其中的一个实例。

我们之前导入的 Netflix-Eureka的jar包中包含了 ribbon 新版本不包含,

现在的最新版本 h12 Ribbon 以被上图提到的 lb给代替了(之前全部最新版的时候踩到的坑)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s1Y5cCOF-1648908821913)(https://cdn.jsdelivr.net/gh/Doomwatcher2004/my-image-host@master/ img /image-20210831160552808.png)]

再次复习RestTemplate 的使用

官网连接:https://docs.spring.io/spring-framework/docs/5.2.2.RELEASE/javadoc-api/org/springframework/web/client/RestTemplate.html

getForObject方法/getForEntity方法

postForObject/postForEntity

开启负载均衡

默认的开启负载均衡操作就一个注解

在你的消费者config中的restTemoplate上添加一个注解

@Configuration
public class orderConfig {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

这样就开启的Ribbon的默认轮询的负载均衡

IRule:根据特定算法从服务列表中选取一个要访问的服务,用哪一种方式做负载均衡

我们首先要强调一下配置细节

如果我们想改变默认的负载均衡算法我们需要在 这样建立一个新包

主启动类在cloud的中,所以他会扫描cloud下所有的子包

接下来是自定义负载均衡的规则编写(使用起来越方便的,他的底层就越精妙)

@SpringBootApplication
@EnableEurekaClient
@RibbonClient(value = "CLOUD-PAYMENT-SERVICE",configuration = Myselgrule.class )
public class orderMain {
    public static void main(String[] args) {
        SpringApplication.run(orderMain.class,args);
    }
}

添加了这个之后我们要使用自己设置的规则我们需要使用到注解@RibbonClient

在主启动类上添加这个注解 ,并且设置两个参数

value:需要负载均衡的服务名

configuration : 要使用的规则类 Myselgrule.class

即可

Ribbon负载均衡算法(这里由于算法实在不是咱的擅长就跳过了手写算法那个一节课)

轮询算法原理

openFeign

链接:https://github.com/spring-cloud/spring-cloud-openfeign

Feign是什么?

Feign是一个声明式的web服务客户端,让编写web服务客户端变得非常容易,只需创建一个接口并在接口上添加注解即可.

Feign能干什么?

使用Feign可以让我们在编写java HTTP客户端的时候变得更加的容易

我们在之前的项目中使用的是Ribbon + Resttemplate的时候,利用Resttemplate对请求的封装处理,形成了一套模版话的调用方法,但是实际开发中,由于对服务的依赖调用可能不止一处,往往一个接口要被多处调用,所以通常都会针对每个微服务自行封装一些客户端类来包装.这个依赖服务的调用.所以,Feign在此基础上,做了进一步的封装,由他来帮助我们定义和实现依赖服务接口的定义.在Feign的实现下,我们只需要创建一个接口并使用注解的方式来配置他(以前是dao接口上面标注mapper注解,现在是一个微服务接口上面标注一个Feign注解即可),即可完成对服务提供方的接口绑定,简化了使用spring cloud ribbon 时候,自动封装服务调用客户端的开发量

同时Feign集成了Ribbon

利用Ribbon维护了Payment的服务列表信息,并且通过轮询实现了客户端的负载均衡.而与Ribbon不同的是.通过feign只需要定义服务绑定的接口且以声明式的方法,简单的实现了服务的调用

这个时候有人要提问了


我们学习openFeign和Feign有什么区别嘛,


区别如下

也就是说,我们要使用openFeign需要使用

接口+注解的方式来开发:微服务调用接口+@FeignClient

使用之前强调一点,也是官方文档说的,fegin 在消费端使用

前置知识强调完之后我们开始编码吧!

老规矩,新建一个模块: cloud-consumer-feign-order80

导入相关的依赖

<!--openfeign-->
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

底下的依赖是平常的使用的,主要是第一个依赖

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

之后编写配置文件:编写端口和Eureka的相关配置

server:
  port: 80
eureka:
  client:
    register-with-eureka: false
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka, http://eureka7002.com:7002/eureka

我们可以学习的时候就发现,我们每次接触到新的组件,主启动类就会多一个新的注解@EnableFeignClients

@SpringBootApplication
@EnableFeignClients
public class feignOrder80Main {
    public static void main(String[] args) {
        SpringApplication.run(feignOrder80Main.class,args);
    }
}

之后就编写业务类就可以了

业务逻辑接口+@FeignClient配置调用provider服务

新建服务层接口

@Component
@FeignClient(value = "CLOUD-PAYMENT-SERVICE")
public interface PaymentFeignService {
    @GetMapping("/payment/get/{id}")
    public CommonResult getPaymentByid(@PathVariable("id") long id);
    @GetMapping(value = "/payment/feign/timeout")
    public String paymentFeignTimeout();
}

@FeignClient(value = "CLOUD-PAYMENT-SERVICE")这里是我们需要使用fegin来调用的服务提供者的,服务名称

编写控制层之后测试

@RestController
public class openFeginController {
    @Resource
    private PaymentFeignService paymentFeignService;
    @GetMapping("/consumer/payment/get/{id}")
    public CommonResult getPaymentByid(@PathVariable("id") long id){
        System.out.println(id);
        return paymentFeignService.getPaymentByid(id);
    }
    @GetMapping(value = "/consumer/payment/feign/timeout")
    public String paymentFeignTimeout(){
        return paymentFeignService.paymentFeignTimeout();
    }
}

测试

这里是调用的服务名称的对应和服务调用的地址

OpenFeign超时控制

场景演示

超时设置,故意设置超时演示出错情况

服务提供方8001故意写暂停程序

@GetMapping(value = "/payment/feign/timeout")
public String paymentFeignTimeout(){
    try { TimeUnit.SECONDS.sleep(3); }catch (Exception e) {e.printStackTrace();}
    return serverPort;
}

服务消费方80添加超时方法PaymentFeignService

@GetMapping(value = "/payment/feign/timeout")
public String paymentFeignTimeout();

服务消费方80添加超时方法OrderFeignController

@GetMapping(value = "/consumer/payment/feign/timeout")
public String paymentFeignTimeout(){
   return paymentFeignService.paymentFeignTimeout();
}

测试方法

访问延时方法:http://localhost/consumer/payment/feign/timeout

错误页面:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7cjtDIAK-1648908821916)(https://cdn.jsdelivr.net/gh/Doomwatcher2004/my-image-host@master/ img /image-20210905153649722.png)]

OpenFeign默认等待一秒钟,超过后报错,因为集成了ribbon,默认超过一秒钟就会超时

怎么配置呢 ? :我们在yml中配置ribbon的超时即可

ribbon:
  ReadTimeout:  5000
  ConnectTimeout: 5000

OpenFeign日志打印功能

feign支持日志打印功能

我们可以通过日志来获取到feign的http请求中的细节

对使用了feign的接口调用情况监控和输出

opnefeign的日志级别

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Jm7bL43A-1648908821917)(https://cdn.jsdelivr.net/gh/Doomwatcher2004/my-image-host@master/ img /image-20210905154015536.png)]

要使用opnefeign的日志

我们需要去配置config

package com.atguigu.springcloud.config;
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FeignConfig {
    @Bean
    Logger.Level feignLoggerLevel(){
        return Logger.Level.FULL;
    }
}

之后在yml配置日志的级别

logging:
  level:
    com.hyc.springcloud.service.PaymentFeignService: debug

之后查看日志内容


SpringCloud Netflix-springcloudnetflix(三)https://developer.aliyun.com/article/1469570

相关实践学习
Serverless极速搭建Hexo博客
本场景介绍如何使用阿里云函数计算服务命令行工具快速搭建一个Hexo博客。
目录
相关文章
|
6月前
|
消息中间件 Java 中间件
SpringCloud Netflix-springcloudnetflix(五)
SpringCloud Netflix-springcloudnetflix
69 1
|
6月前
|
Java API 微服务
SpringCloud Netflix-springcloudnetflix(四)
SpringCloud Netflix-springcloudnetflix
67 1
|
6月前
|
运维 监控 Java
SpringCloud Netflix-springcloudnetflix(三)
SpringCloud Netflix-springcloudnetflix
70 1
|
6月前
|
Dubbo Java 应用服务中间件
SpringCloud Netflix-springcloudnetflix(一)
SpringCloud Netflix-springcloudnetflix
74 1
|
2月前
|
SpringCloudAlibaba API 开发者
新版-SpringCloud+SpringCloud Alibaba
新版-SpringCloud+SpringCloud Alibaba
|
3月前
|
资源调度 Java 调度
Spring Cloud Alibaba 集成分布式定时任务调度功能
定时任务在企业应用中至关重要,常用于异步数据处理、自动化运维等场景。在单体应用中,利用Java的`java.util.Timer`或Spring的`@Scheduled`即可轻松实现。然而,进入微服务架构后,任务可能因多节点并发执行而重复。Spring Cloud Alibaba为此发布了Scheduling模块,提供轻量级、高可用的分布式定时任务解决方案,支持防重复执行、分片运行等功能,并可通过`spring-cloud-starter-alibaba-schedulerx`快速集成。用户可选择基于阿里云SchedulerX托管服务或采用本地开源方案(如ShedLock)
122 1
|
1月前
|
JSON SpringCloudAlibaba Java
Springcloud Alibaba + jdk17+nacos 项目实践
本文基于 `Springcloud Alibaba + JDK17 + Nacos2.x` 介绍了一个微服务项目的搭建过程,包括项目依赖、配置文件、开发实践中的新特性(如文本块、NPE增强、模式匹配)以及常见的问题和解决方案。通过本文,读者可以了解如何高效地搭建和开发微服务项目,并解决一些常见的开发难题。项目代码已上传至 Gitee,欢迎交流学习。
125 1
Springcloud Alibaba + jdk17+nacos 项目实践
|
22天前
|
消息中间件 自然语言处理 Java
知识科普:Spring Cloud Alibaba基本介绍
知识科普:Spring Cloud Alibaba基本介绍
55 2
|
30天前
|
Dubbo Java 应用服务中间件
Dubbo学习圣经:从入门到精通 Dubbo3.0 + SpringCloud Alibaba 微服务基础框架
尼恩团队的15大技术圣经,旨在帮助开发者系统化、体系化地掌握核心技术,提升技术实力,从而在面试和工作中脱颖而出。本文介绍了如何使用Dubbo3.0与Spring Cloud Gateway进行整合,解决传统Dubbo架构缺乏HTTP入口的问题,实现高性能的微服务网关。
|
2月前
|
人工智能 前端开发 Java
Spring Cloud Alibaba AI,阿里AI这不得玩一下
🏀闪亮主角: 大家好,我是JavaDog程序狗。今天分享Spring Cloud Alibaba AI,基于Spring AI并提供阿里云通义大模型的Java AI应用。本狗用SpringBoot+uniapp+uview2对接Spring Cloud Alibaba AI,带你打造聊天小AI。 📘故事背景: 🎁获取源码: 关注公众号“JavaDog程序狗”,发送“alibaba-ai”即可获取源码。 🎯主要目标:
83 0