SpringCloud 学习笔记(2)- Eureka 服务注册与发现

文章目录

1、Eureka 基础知识

1.1、什么是服务治理?

Spring Cloud 封装了 Netflix 公司开发的 Eureka 模块来实现服务治理。

在传统的 RPC 远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,管理比较复杂,所以需要使用服务治理,管理服务于服务之间依赖关系,可以实现服务调用负载均衡容错等,实现服务发现与注册

1.2、什么是服务注册与发现?

Eureka 采用了 CS 的设计架构,Eureka Sever 作为服务注册功能的服务器,它是服务注册中心。而系统中的其他微服务,使用 Eureka 的客户端连接到 Eureka Sever 并维持心跳连接。这样系统的维护人员就可以通过 Eureka Server 来监控系统中各个微服务是否正常运行。

在服务注册与发现中,有一个注册中心。当服务器启动的时候,会把当前自己服务器的信息比如:服务地址通讯地址等以别名方式注册到注册中心上。另一方(消费者服务提供者),以该别名的方式去注册中心上获取到实际的服务通讯地址,然后再实现本地 NPC 调用 RPC 远程调用框架。

核心设计思想:在于注册中心,因为使用注册中心管理每个服务与服务之间的一个依赖关系(服务治理概念)。在任何 RPC 远程框架中,都会有一个注册中心(存放服务地址相关信息(接口地址))。

在这里插入图片描述

1.3、Eureka 两大组件

Eureka Server 提供服务注册服务

各个微服务节点通过配置启动后,会在 Eureka Server 中进行注册,这样 Eureka Server 中的服务注册表中将会存储所有可用服务节点信息,服务节点的信息可以在界面中直观看到。

Eureka Client 通过注册中心进行访问

是一个 Java 客户端,用于简化与 Eureka Server 的交互,客户端同时也具备一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,将会向 Eureka Server 发送心跳(默认周期为 30 秒)。如果 Eureka Server 在多个心跳周期内没有接收到某个节点的心跳,Eureka Server 将会从服务注册表中把这个服务节点移除(默认 90 秒)。

2、单机 Eureka 构建步骤

2.1、建立 cloud-eureka-server7001 模块

查看父 pom

<!-- 模块说明:这里声明多个子模块 -->
<modules>
    <module>cloud-provider-payment8001</module>
    <module>cloud-consumer-order80</module>
    <module>cloud-api-commons</module>
    <!-- 新加入的模块 -->
    <module>cloud-eureka-server7001</module>
</modules>

2.2、更改 pom 文件

以前老版本(2018)

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

现在新版本(2020.2)

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

更改 pom 文件

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud-parent</artifactId>
        <groupId>com.springcloud-demo</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-eureka-server7001</artifactId>

    <dependencies>

        <!-- eureka-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        
        <!-- 引入自己定义的 api 通用包 -->
        <dependency>
            <groupId>com.springcloud-demo</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

        <!-- web -->
        <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-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- 热部署 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
    </dependencies>

</project>

2.3、写 YML

server:
  port: 7001

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

2.4、主启动类(新建)

注意:@EnableEurekaServer

@SpringBootApplication
@EnableEurekaServer
public class EurekaMain7001 {

    public static void main(String[] args) {
        SpringApplication.run(EurekaMain7001.class);
    }
}

2.5、测试

http://localhost:7001/

在这里插入图片描述

3、EurekaClient 端

3.1、将 cloud-provider-payment8001 注册进 Eureka Server 成为服务提供者 provider

3.1.1、更改 pom 文件(cloud-provider-payment8001)

以前老版本(2018)

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

现在新版本(2020.2)

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

更改 pom 文件

<!-- eureka-client -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
3.1.2、写 YML(添加)
eureka:
  client:
    # 表示是否将自己注册进 Eureka Server, 默认为 true
    register-with-eureka: true
    # 是否从 Eureka Server 抓取已有的注册信息, 默认为 true, 集群必须设置为 true 才能配合 Ribbon 实现负载均衡
    fetchRegistry: true
    service-url:
      defaultZone: http://localhost:7001/eureka
3.1.3、主启动(修改)

注意:@EnableEurekaClient

@SpringBootApplication
@EnableEurekaClient
public class PaymentMain8001 {

    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8001.class);
    }
}
3.1.4、测试

先要(重新)启动 EurekaServer,不然会触发保护机制

http://localhost:7001/
在这里插入图片描述

微服务注册名配置说明

在这里插入图片描述

3.1.5、自我保护机制

在这里插入图片描述

3.2、将 cloud-consumer-order80 注册进 Eureka Server 成为服务消费者 consumer

3.2.1、更改 pom 文件(cloud-consumer-order80)
<!-- eureka-client -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
3.2.2、写 YML(添加)
eureka:
  client:
    # 表示是否将自己注册进 Eureka Server, 默认为 true
    register-with-eureka: true
    # 是否从 Eureka Server 抓取已有的注册信息, 默认为 true, 集群必须设置为 true 才能配合 Ribbon 实现负载均衡
    fetchRegistry: true
    service-url:
      defaultZone: http://localhost:7001/eureka
3.2.3、主启动(修改)

注意:@EnableEurekaClient

@SpringBootApplication
@EnableEurekaClient
public class OrderMain {

    public static void main(String[] args) {
        SpringApplication.run(OrderMain.class);
    }
}
3.2.4、测试
  • 先要(重新)启动 Eureka Server,7001 服务
  • 再启动服务提供者 provider,8001 服务

http://localhost:7001/
在这里插入图片描述
在这里插入图片描述

4、集群 Eureka 构建步骤

4.1、Eureka 集群原理说明

在这里插入图片描述

问题:微服务 RPC 远程服务调用最核心的是什么?

高可用,试想你的注册中心只有一个,它如果出故障了会导致整个为服务环境不可用。

解决办法

搭建 Eureka 注册中心集群,实现负载均衡 + 故障容错。

4.2、Eureka Server 集群环境构建步骤

4.2.1、参考 cloud-eureka-server7001,新建 cloud-eureka-server7002
4.2.2、更改 pom 文件(cloud-eureka-server7002)
4.2.3、修改映射配置
  • 找到 C:\Windows\System32\drivers\etc 路径下的 hosts 文件
    在这里插入图片描述
  • 修改映射配置添加进 hosts 文件
    • 127.0.0.1 eureka7001.com
    • 127.0.0.1 eureka7002.com
      在这里插入图片描述
4.2.4、修改 YML(以前单机)
  1. 7001
server:
  port: 7001

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

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

主启动(复制 cloud-eureka-server7001 的主启动类到 7002 即可)

4.2.6、将支付服务 8001 微服务发布到上面 2 台 Eureka 集群配置中

修改 YML

service-url:
  defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka  # 集群版
4.2.7、将订单服务 80 微服务发布到上面 2 台 Eureka 集群配置中
service-url:
  defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka  # 集群版
4.2.8、测试
  1. 先要启动 Eureka Server,7001/7002 服务
  2. 再要启动服务提供者 provider,8001 服务
  3. 再要启动消费者,80 服务

http://eureka7001.com:7001/
在这里插入图片描述

http://eureka7002.com:7002/
在这里插入图片描述

http://localhost/consumer/listPayment
在这里插入图片描述

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

4.3.1、参考 cloud-provider-payment8001,新建 cloud-provider-payment8002
4.3.2、更改 pom 文件(cloud-provider-payment8002)
4.3.3、修改 YML
server:
  port: 8002
4.3.4、主启动

主启动(复制 cloud-provider-payment8001 的主启动类到 8002 即可)

4.3.5、修改 8001/8002 的 Controller

在这里插入图片描述

4.3.6、测试

在这里插入图片描述

在这里插入图片描述

4.3.7、负载均衡

订单服务访问地址不能写死
在这里插入图片描述

使用 @LoadBalanced 注解赋予 RestTemplate 负载均衡的能力
在这里插入图片描述

4.3.8、测试
  1. 先要启动 Eureka Server,7001/7002 服务
  2. 再要启动服务提供者 provider,8001 服务
  3. 再要启动消费者,80 服务
  4. 用 Postman 访问 http://localhost/consumer/listPayment 测试

测试结果

  • 负载均衡效果达到
  • 8001/8002 端口服务交替执行
  • Ribbon 和 Eureka 整合后 Consumer 可以直接调用服务而不用再关心地址和端口号,且该服务还有负载功能了

5、actuator 微服务信息完善

5.1、主机名称:服务名称修改(不暴露主机名称)

  1. cloud-provider-payment8001
    在这里插入图片描述
  2. cloud-provider-payment8002
    在这里插入图片描述

结果

在这里插入图片描述

5.2、访问信息有 IP 信息提示

  1. cloud-provider-payment8001
    在这里插入图片描述
    1. cloud-provider-payment8002
      在这里插入图片描述

结果

在这里插入图片描述

6、服务发现 Discovery

对于注册进 Eureka 里面的微服务,可以通过服务发现来获得该服务的信息

  1. 修改 cloud-provider-payment8001/8002 的 controller,添加如下代码
/**
 * import org.springframework.cloud.client.discovery.DiscoveryClient;
 */
@Resource
private DiscoveryClient discoveryClient;

@GetMapping("/discovery")
public Object discovery() {
    List<String> services = discoveryClient.getServices();
    for (String service : services) {
        log.info("************Application : {}", service);
    }

    List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
    for (ServiceInstance instance : instances) {
        log.info(instance.getServiceId() + "\t"
                + instance.getHost() + "\t"
                + instance.getPort() + "\t"
                + instance.getUri());
    }

    return this.discoveryClient;
}
  1. 8001 主启动类 @EnableDiscoveryClient

在这里插入图片描述

测试

先要启动 EurekaServer,7001/7002 服务
再启动 8001 主启动类,需要稍等一会

http://localhost:8001/discovery
在这里插入图片描述

7、Eureka 自我保护

7.1、概述

保护模式主要用于一组客户端和 Eureka Server 之间存在网络分区场景下的保护。一旦进入保护模式,Eureka Server 将会尝试保护其服务注册表中的信息,不再删除服务注册表中的数据,也就是不会注销任何微服务。

如果在 Eureka Server 的首页看到以下这段提示,则说明 Eureka 进入了保护模式:
在这里插入图片描述

7.2、导致原因

一句话:某时刻某一个微服务不可用了,Eureka 不会立刻清理,依旧会对该微服务的信息进行保存。

属于 CAP 里面的 AP 分支。

7.2.1、为什么会产生 Eureka 自我保护机制?

为了防止 Eureka Client 可以正常运行,但是与 Eureka Server 网络不通情况下,Eureka Server 不会立刻将 Eureka Client 服务剔除。

7.2.2、什么是自我保护模式?

默认情况下,如果 Eureka Server 在一定时间内没有接收到某个微服务实例的心跳,Eureka Server 将会注销该实例(默认90秒)。

但是当网络分区故障发生(延时、卡顿、拥挤)时,微服务与 Eureka Server 之间无法正常通信,以上行为可能变得非常危险了 —— 因为微务本身其实是健康的,此时本不应该注销这个微服务。

Eureka 通过 “自我保护模式” 来解决这个问题 —— 当 Eureka Server 节点在时间内丢失过多客户端时(可能发生了网络分区故障),那么这个节点就会进入自我保护模式。

在自我保护模式中,Eureka Server 会保护服务注册表中的信息,不再注销任何服务实例。

它的设计哲学就是宁可保留错误的服务注册信息,也不盲目注销任何可能健康的服务实例。

综上,自我保护模式是一种应对网络异常的安全保护措施。它的架构哲学是宁可同时保留所有微服务(健康的微服务和不健康的微服务都会保留)也不盲目注销任何健康的微服务。

使用自我保护模式,可以让Eureka集群更加的健壮、稳定。

7.3、怎么禁止自我保护?(一般生产环境中不会禁止自我保护)

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
ava实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),可运行高分资源 Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。下面详细介绍C语言的基本概念和语法。 1. 变量和数据类型 在C语言中,变量用于存储数据,数据类型用于定义变量的类型和范围。C语言支持多种数据类型,包括基本数据类型(如int、float、char等)和复合数据类型(如结构体、联合等)。 2. 运算符 C语言中常用的运算符包括算术运算符(如+、、、/等)、关系运算符(如==、!=、、=、<、<=等)、逻辑运算符(如&&、||、!等)。此外,还有位运算符(如&、|、^等)和指针运算符(如、等)。 3. 控制结构 C语言中常用的控制结构包括if语句、循环语句(如for、while等)和switch语句。通过这些控制结构,可以实现程序的分支、循环和多路选择等功能。 4. 函数 函数是C语言中用于封装代码的单元,可以实现代码的复用和模块化。C语言中定义函数使用关键字“void”或返回值类型(如int、float等),并通过“{”和“}”括起来的代码块来实现函数的功能。 5. 指针 指针是C语言中用于存储变量地址的变量。通过指针,可以实现对内存的间接访问和修改。C语言中定义指针使用星号()符号,指向数组、字符串和结构体等数据结构时,还需要注意数组名和字符串常量的特殊性质。 6. 数组和字符串 数组是C语言中用于存储同类型数据的结构,可以通过索引访问和修改数组中的元素。字符串是C语言中用于存储文本数据的特殊类型,通常以字符串常量的形式出现,用双引号("...")括起来,末尾自动添加'\0'字符。 7. 结构体和联合 结构体和联合是C语言中用于存储不同类型数据的复合数据类型。结构体由多个成员组成,每个成员可以是不同的数据类型;联合由多个变量组成,它们共用同一块内存空间。通过结构体和联合,可以实现数据的封装和抽象。 8. 文件操作 C语言中通过文件操作函数(如fopen、fclose、fread、fwrite等)实现对文件的读写操作。文件操作函数通常返回文件指针,用于表示打开的文件。通过文件指针,可以进行文件的定位、读写等操作。 总之,C语言是一种功能强大、灵活高效的编程语言,广泛应用于各种领域。掌握C语言的基本语法和数据结构,可以为编程学习和实践打下坚实的基础。
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值