分布式开发之SpringCloud

title: 分布式开发之SpringCloud


苟日新,又日新,日日新。

准备

  • springCloud是一个新的微服务框架。(dubbo为RPC框架)

在微服务架构中,包括 服务注册与发现(eureka), 服务消费(ribben/feign), 负载均衡(feign集成ribben,并实现负载), 熔断器(熔断器防止服务雪崩,hystrix, feign自带hystrix只是需要开启), 智能路由(zuul), 配置管理(springcloud config) 等

工程创建

  1. 创建工程文件夹,用来放所有工程
  2. NEW DIRECTORY
  3. 创建子工程,创建pom,创建applicaton.xml
  4. 目录结构如下:
    在这里插入图片描述

主项目版本控制

  1. springBoot声明
<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.7.RELEASE</version>
        <relativePath/>
    </parent>
  1. 打包方式
<!--注意打包方式为 pom -->
    <packaging>pom</packaging>
  1. springcloud版本
<properties> 
        <spring-cloud.version>Greenwich.SR2</spring-cloud.version>
 </properties>
  1. 全部pom.xml如下
<?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">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.7.RELEASE</version>
        <relativePath/>
    </parent>

    <groupId>com.itic.spring.cloud.itic.dependencies</groupId>
    <artifactId>spring-cloud-itic-dependencies</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>spring-cloud-itic-dependencies</name>
    <description>Spring Cloud Dependencies</description>

    <!--注意打包方式为 pom -->
    <packaging>pom</packaging>

    <!--添加子模块标识 !!!! -->
    <modules>
        <!--声明 spring-cloud-eureka 为当前项目 子模块 ,以后有新的子模块添加也要在此添加-->
       <!-- <module>spring-cloud-hello-eureka</module>-->
    </modules>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR2</spring-cloud.version>
    </properties>

    <dependencies>
        <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-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
    </dependencies>

    <!-- dependencies即使在子项目中不写该依赖项,那么子项目仍然会从父项目中继承该依赖项(全部继承)
         dependencyManagement里只是声明依赖,并不实现引入,因此子项目需要显示的声明需要用的依赖-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <!-- Springboot组件: -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

在这里插入图片描述

服务注册与发现(Eureka)

1.1、创建服务注册中心

在这里插入图片描述

  1. 引入主项目
<parent>
        <groupId>com.itic.spring.cloud.itic.dependencies</groupId>
        <artifactId>spring-cloud-itic-dependencies</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
  1. 引入spring-cloud-starter-netflix-eureka-server的依赖:
<dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>
  1. Application启动类:
package com.itic.spring.cloud.eureka;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }
}
  1. yml
# 本身是注册中心,但是也需要注册,这里可以向自己注册
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
    # 不在页面上显示当前 服务
    register-with-eureka: false
    # 为true时,可以启动,但报异常:Cannot execute request on any known server
    fetch-registry: false
  # 当应用上线率过低时,eureka会启动保护机制,默认确定当前服务是开启的,开发 环境中尽量关闭(设置为false)
  server:
    enable-self-preservation: false
# 服务名 ,很重要 ,后期 config 配置中心会以 服务名为标识找对应的 服务
spring:
  application:
    name: eureka
# 设置当前项目端口号
server:
  port: 8761
  1. 启动程序,访问http://localhost:8761/

1.2、创建服务提供者

在这里插入图片描述

  1. 引入主项目:
<parent>
        <groupId>com.itic.spring.cloud.itic.dependencies</groupId>
        <artifactId>spring-cloud-itic-dependencies</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
  1. pom.xml
<?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">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.itic.spring.cloud.itic.service</groupId>
    <artifactId>spring-cloud-itic-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>spring-cloud-itic-service</name>
    <description></description>

    <parent>
        <groupId>com.itic.spring.cloud.itic.dependencies</groupId>
        <artifactId>spring-cloud-itic-dependencies</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

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

        <dependency>
            <groupId>de.codecentric</groupId>
            <artifactId>spring-boot-admin-starter-client</artifactId>
            <version>2.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jolokia</groupId>
            <artifactId>jolokia-core</artifactId>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>

            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <appendAssemblyId>false</appendAssemblyId>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <archive>
                        <manifest>
                            <!-- 此处指定main方法入口的class -->
                            <mainClass>com.spring.cloud.itic.service.ServiceApplication</mainClass>
                        </manifest>
                    </archive>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>assembly</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

        </plugins>
    </build>

</project>

  1. Application启动类:
package com.spring.cloud.itic.service;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

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

    @Value("${server.port}")
    String port;

    @RequestMapping("/hiHome")
    public String home(@RequestParam String name) {
        return "hhahahah";
    }

}

  1. yml
# 注册到 eureka server 配置
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
server:
  port: 8763
spring:
  application:
    ## 需要指明spring.application.name,这个很重要,这在以后的服务与服务之间相互调用一般都是根据这个name
    name: eurekaclient
   ##boot:
     ##admin:
       ##client:
        ## url: http://localhost:8080

服务消费者(Ribbon,Feign)

feign集成了Ribbon,并且默认实现负载均衡

在这里插入图片描述

1.1 Feign实现服务消费

  1. pom.xml
<?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">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.itic.spring.cloud.itic.feign</groupId>
    <artifactId>spring-cloud-itic-feign</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>spring-cloud-itic-feign</name>
    <description></description>

    <parent>
        <groupId>com.itic.spring.cloud.itic.dependencies</groupId>
        <artifactId>spring-cloud-itic-dependencies</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

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

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

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>

            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <appendAssemblyId>false</appendAssemblyId>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <archive>
                        <manifest>
                            <!-- 此处指定main方法入口的class -->
                            <mainClass>com.spring.cloud.itic.service.ServiceApplication</mainClass>
                        </manifest>
                    </archive>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>assembly</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

  1. application.yml
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
server:
  port: 8769
spring:
  application:
    name: service-feign
  sleuth:
    sampler:
      probability: 1.0   #2.0后percentage改为probability
feign:
  hystrix:
    enabled: true

ribbon:
  ReadTimeout: 60000
  ConnectTimeout: 60000
  1. 定义一个feign接口
package com.spring.cloud.itic.feign.service;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

@FeignClient(value = "eurekaclient",fallback = SchedualServiceHiHystric.class)
public interface SchedualServiceHi {

    @RequestMapping(value = "/hi",method = RequestMethod.GET)
    public String sayHiFromClientOne(@RequestParam(value = "name") String name);

}
  1. FeginApplication
package com.spring.cloud.itic.feign;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient //注册到eureka
@EnableFeignClients  //启用Fegin客户端
//@EnableHystrixDashboard //开启熔断器监控
public class FeginApplication {
    public static void main(String[] args) {
        SpringApplication.run(FeginApplication.class, args);
    }

}

熔断器(hystrix)

如果单个服务出现问题,调用这个服务就会出现线程阻塞,此时若有大量的请求涌入,Servlet容器的线程资源会被消耗完毕,导致服务瘫痪。服务与服务之间的依赖性,故障会传播,会对整个微服务系统造成灾难性的严重后果,这就是服务故障的“雪崩”效应。

1.使用熔断器防止服务雪崩
2.feign自带熔断器,需要开启。

  1. Feign是自带断路器的,在D版本的Spring Cloud之后,它没有默认打开。需要在配置文件中配置打开它,在yml最后一行加入
feign:
  hystrix:
    enabled: true
  1. 在FeignClient的SchedualServiceHi接口的注解中加上fallback的指定类就行了
@FeignClient(value = "eurekaclient",fallback = SchedualServiceHiHystric.class)
public interface SchedualServiceHi {

    @RequestMapping(value = "/hi",method = RequestMethod.GET)
    public String sayHiFromClientOne(@RequestParam(value = "name") String name);

}
@Component
public class SchedualServiceHiHystric implements SchedualServiceHi {

    @Override
    public String sayHiFromClientOne(@RequestParam(value = "name")  String name) {
        return "sorry :fallback _" + name;
    }
}

仪表盘监控

使用熔断器仪表盘监控,就是监控熔断情况
断流器Hystrix不仅提供了微服务的错误与延迟处理机制,还提供了仪表盘用于监控各个微服务程序的健康状态

  1. 添加健康监控。对于每个Eureka客户端(微服务应用程序),默认采用心跳机制确认健康状态,通过启用actuator
<dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
  1. 新建dashboard项目管理仪表盘监控
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<!-- 仪表盘服务程序 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>
<!-- 程序质量监控服务,也可忽略,但是 -->       
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
  1. DashboardApplication.java添加注解 @EnableHystrixDashboard //开启熔断器监控
  2. 访问 http://localhost:8766/hystrix
  3. 通过Hystrix Dashboard主页面的文字介绍,我们可以知道,Hystrix Dashboard共支持三种不同的监控方式
☞默认的集群监控:通过URL:http://turbine-hostname:port/turbine.stream开启,实现对默认集群的监控。

☞指定的集群监控:通过URL:http://turbine-hostname:port/turbine.stream?cluster=[clusterName]开启,实现对clusterName集群的监控。

☞单体应用的监控:通过URL:http://hystrix-app:port/hystrix.stream开启,实现对具体某个服务实例的监控。

路由网关(Zuul)

使用路由网关统一访问接口。

在这里插入图片描述
zuul 主要功能是路由转发和过滤器, 以及当路由服务可以访问,但是因为网络或其他原因服务访问失败时,可以配置路由失败回调,不将500,404一些服务问题暴漏给客户端。

1.1 路由转发实现

  1. pom
<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>
  1. application 类入口加入标签 @EnableZuulProxy
  2. yml配置
# 注册到 eureka server 配置
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
server:
  port: 8765
spring:
  application:
    ## 需要指明spring.application.name,这个很重要,这在以后的服务与服务之间相互调用一般都是根据这个name
    name: zuul

zuul:
  routes:
    #    api-a:
    #      path: /api-a/**
    #      serviceId: service-ribbon
    api-b:
      path: /api-b/**
      serviceId: service-feign

1.2. 过滤器实现

  1. 新建MyFilter.java
package com.spring.cloud.itic.zipkin.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

@Component
public class MyFilter extends ZuulFilter {

    /**
     * filterType:返回一个字符串代表过滤器的类型,在zuul中定义了四种不同生命周期的过滤器类型,具体如下:
     * pre:路由之前
     * routing:路由之时
     * post: 路由之后
     * error:发送错误调用
     */
    @Override
    public String filterType() {
        return "pre";
    }

    //过滤的顺序
    @Override
    public int filterOrder() {
        return 0;
    }

    //这里可以写逻辑判断,是否要过滤,本文true,永远过滤。
    @Override
    public boolean shouldFilter() {
        return true;
    }

    //过滤器的具体逻辑。可用很复杂,包括查sql,nosql去判断该请求到底有没有权限访问。
    @Override
    public Object run() throws ZuulException {
        System.out.println("==============================================================");
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        System.out.println(String.format("%s >>> %s", request.getMethod(), request.getRequestURL().toString()));
        Object accessToken = request.getParameter("token");
        if(accessToken == null) {
            System.out.println("token is empty!!!!");
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(401);
            try {
                ctx.getResponse().getWriter().write("token is empty");
            }catch (Exception e){}

            return null;
        }
        System.out.println("ok");
        return null;
    }
}

分布式配置中心(SpringCloud Config)

服务过多,配置文件统一管理
Spring Cloud Config项目是一个解决分布式系统的配置管理方案。它包含了Client和Server两个部分,server提供配置文件的存储、以接口的形式将配置文件的内容提供出去,client通过接口获取数据、并依据此数据初始化自己的应用。

1.1 服务端(端口默认8888)

  1. pom.xml
<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
  1. Application.java入口加入注解 @EnableConfigServer // springcloud config server的注解
  2. yml
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
server:
  port: 8888
spring:
  application:
    name: service-config
#feign:
#  hystrix:
#    enabled: true
  cloud:
    config:
      server:
        git:
          uri: https://github.com/15130125905/spring-cloud-config.git  #git仓库地址,就是刚才创建的git仓库
          skipSslValidation: true #跳过校验
          basedir: E:///config-center///config #从git仓库拉取到的文件在本地存储的位置,可自行修改或删掉,默认存储在C盘
        # bootstrap: true

1.2 客户端

  1. pom.xml
<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
  1. bootstrap.yml
spring:
  application:
    # 对应config server所获取的配置文件的 {application}
    name: application
  cloud:
    config:
      # 指 config server 地址
      uri: http://localhost:8888/
      # 指定 config server 里的 {profile}
      profile: feignDev
      # 指定Git仓库分支,对应config server的{label}
      label: master

服务链路追踪(ZipKin)

调用链分析

  1. 默认端口9411
  2. pom
<properties>
        <zipkin-version>2.11.8</zipkin-version>
    </properties>

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
            <version>2.0.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>io.zipkin.java</groupId>
            <artifactId>zipkin-server</artifactId>
            <version>${zipkin-version}</version>
        </dependency>
        <dependency>
            <groupId>io.zipkin.java</groupId>
            <artifactId>zipkin-autoconfigure-ui</artifactId>
            <version>${zipkin-version}</version>
        </dependency>
  1. yml
# 注册到 eureka server 配置
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
server:
  port: 9411
spring:
  application:
    ## 需要指明spring.application.name,这个很重要,这在以后的服务与服务之间相互调用一般都是根据这个name
    name: zipkin
management:
  metrics:
    web:
      server:
        #避免访问zipkin页面报java.lang.IllegalArgumentException
        auto-time-requests: false
  1. Applicatoin入口 @EnableZipkinServer

服务监控(SpringBoot Admin)

状态收集, 健康检查
Spring Boot Admin是用来管理和监视您的Spring Boot应用程序的。应用程序需要注册为客户端,UI由AngularJs开发。

不写了。推荐一篇文章

启动顺序

  1. 注册与发现
  2. 分布式配置中心
  3. 服务提供者
  4. 服务消费者
  5. API网关

代码

https://github.com/15130125905/springcloud.git

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值