springCloud搭建、zuul、feign、hystrix、ribbon(内部培训)

简介: springCloud搭建、zuul、feign、hystrix、ribbon(内部培训)

一、搭建过程

1.1 创建方式

所有模块的创建均为空的maven项目,父项目中的src文件夹可直接删除

1.2 依赖管理

dependencies:当前项目与其子项目中都会添加改依赖(子项目会从父项目中继承)

dependencyManagement:只声明依赖,并不实先引入,然后子项目中添加该依赖不写版本号,则继承父项目中所声明的版本,若子项目有指定版本,则优先使用自己的;

ps: 我们可以再父项目中声明依赖,而不引入,做到版本集中统一管理;

1.3 按项目结构图创建出各个模块

对于其他模块的,可以选择直接复制一个模块文件夹,然后修改文件夹名称以及pom.xml中相关项目名,最后在父项目pom中添加一行module元素指向本模块即可;

1.4 将maven构建成springboot项目,父项目/pom.xml中

(可以构建一个springboot项目来参考一下):

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.15.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

<packaging>pom</packaging>

<properties>
    <java.version>1.8</java.version>
</properties>

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

1.5 父项目中声明SpringCloud相关依赖

<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>

1.6 Eureka

1.6.1 eureka-server中:

  • 依赖:
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
  • 添加springBoot启动类,并增加注解
@EnableEurekaServer
  • yml配置:
eureka:
  instance:
    hostname: ${EUREKA_HOSTNAME:${spring.cloud.client.ip-address}}
  #    ip-address: ${eureka.instance.hostname}
  server:
    enable-self-preservation: false    #关闭服务器自我保护(生产环境开启)
    eviction-interval-timer-in-ms: 30000 #清理间隔(单位毫秒,默认是60*1000)5秒将客户端剔除的服务在服务注册列表中剔除#
    response-cache-update-interval-ms: 30000  #eureka server刷新readCacheMap的时间,注意,client读取的是readCacheMap,这个时间决定了多久会把readWriteCacheMap的缓存更新到readCacheMap上 #eureka server刷新readCacheMap的时间,注意,client读取的是readCacheMap,这个时间决定了多久会把readWriteCacheMap的缓存更新到readCacheMap上默认30s
    response-cache-auto-expiration-in-seconds: 180   #eureka server缓存readWriteCacheMap失效时间,这个只有在这个时间过去后缓存才会失效,失效前不会更新,过期后从registry重新读取注册服务信息,registry是一个ConcurrentHashMap。
    renewal-percent-threshold: 0.85  #  指定每分钟需要收到的续约次数的阈值,默认值就是:0.85
  client:
    service-url:
      defaultZone: ${EUREKA_URL:http://${eureka.instance.hostname}:${server.port}/eureka}
    register-with-eureka: false  #是否将自己注册到Eureka服务中,默认为true
    fetch-registry: false       #是否从Eureka中获取注册信息,默认为true

1.6.2 eureka-client中:

  • 依赖:
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
  • 启动类添加注解:
@EnableDiscoveryClient
  • yml配置:
eureka:
  instance:
    hostname: ${HOSTNAME:${spring.cloud.client.ip-address}}
    #    hostname: ${HOSTNAME:127.0.0.1}
    ip-address: ${eureka.instance.hostname}
    prefer-ip-address: true
    instance-id: ${spring.application.name}:${eureka.instance.hostname}:${server.port}
    #    instance-id: ${spring.application.name}:${docker.ipAddress}:${spring.application.instance_id:${server.port}}
    lease-renewal-interval-in-seconds: 30    #续约间隔时间 s
    lease-expiration-duration-in-seconds: 90 #续约超时时间 s
  client:
    serviceUrl:
      defaultZone: ${DEFAULTZONE:http://admin:123456@${eureka.instance.hostname}:9001/eureka/}
    registry-fetch-interval-seconds: 30                  # 间隔多久去拉取服务注册信息,默认为30秒

二、zuul的配置与使用

2.1 配置

  • 依赖
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
  • 启动类添加注解
@EnableZuulProxy
  • yml配置(包含重试)
######## zuul的配置  start ########
ribbon:
  eager-load:
    enabled: true
  ReadTimeout: ${READ_TIMEOUT:30000}            # 获取到响应内容的超时时间
  ConnectTimeout: ${CONNECTION_TIMEOUT:1000}          # 连接超时时间
  MaxAutoRetries: 0             # 在当前服务重试的次数
  MaxAutoRetriesNextServer: 1   # 默认轮询去重选列表中服务的次数
  OkToRetryOnAllOperations: ${ALLRETRY:false}  #是否所有操作都重试  (默认false)
# 使用okhttp: (还需要引入相关依赖,且okhttp默认开启重试)
#  http:
#    client:
#      enabled: false
#  okhttp:
#    enabled: true
hystrix:
  command:
    default:
      execution:
        timeout:
          enabled: true
        isolation:
          thread:
            timeoutInMilliseconds: ${THREAD_TIMEOUT:30000}

zuul:
  host: # routes使用url时走这个超时配置
    socket-timeout-millis: 30000
    connect-timeout-millis: 1000
    max-per-route-connections: 100      # 适用于ApacheHttpClient,如果是okhttp无效。每个服务的http客户端连接池最大连接,默认是200
    max-total-connections: 500          # 适用于ApacheHttpClient,如果是okhttp无效。每个route可用的最大连接数,默认值是20
  ribbon:
    eager-load:
      enabled: true
  # 开启自动重试
  retryable: true
  # 自定义路由转发规则
  routes:
    user:
      path: /uc/**
      #url: http://server-b-3:9006
      sensitiveHeaders:
      service-id: admin-user
    ebankpay:
      path: /pay/**
      #url: http://server-b-3:9008
      sensitiveHeaders:
      service-id: admin-ebankpay
    product:
      path: /product/**
      #url: http://server-b-3:9011
      sensitiveHeaders:
      service-id: admin-product
  add-proxy-headers: true
  #因为zuul有默认的隐射机制,如果没有以下的配置,那么访问http://ip:gatewayPort/c/也可以访问到你的c服务,如果你不想向外界暴露除你配置的隐射之外的服务,可以加上zuul.ignored-services:*
  ignoredServices: '*'
######## zuul的配置  end ########

2.2 Zuul重试配置需要添加依赖

依赖:

<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
</dependency>

yml配置(重试次数配置见上方zuul的配置,这里不再全部重复写了):

zuul:
  retryable: true     # 开启自动重试

2.3 动态路由

    @Bean
    public PatternServiceRouteMapper patternServiceRouteMapper() {
   
   
        // servicePattern 决定是哪个微服务eureka-client
         // routePattern 怎么样的访问形式  http://localhost/eureka-client/info
        return new PatternServiceRouteMapper("(?<name>.*)-service", "${name}");
    }

//main方法测试路由配置是否正确
    public static void main111(String[] args) {
   
   
        PatternServiceRouteMapper patternServiceRouteMapper = new PatternServiceRouteMapper("(?<name>.*)-service", "${name}");
        String apply = patternServiceRouteMapper.apply("user-service"); //user
        System.out.println(apply);
    }

2.4 ZuulFilter的使用

  • 自定义filter相关类,继承ZuulFilter,重写4个方法:
@Slf4j
@Component
public class TokenZuulFilter2 extends ZuulFilter {
   
   
    @Override
    public String filterType() {
   
   
        //指定过滤器类型
        // 4种过滤器类型,分别为pre(路由之前调用),route(路由时调用),error(发生异常时调用),post(routing和error之后调用)
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
   
   
        //过滤器优先级,数值越小优先级越高
        return FilterConstants.SEND_ERROR_FILTER_ORDER + 1;
    }

    @Override
    public boolean shouldFilter() {
   
   
        // 这里也可以做一些判断,决定是否开启这个filter
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        //判断登录接口设置放行
        StringBuffer requestURL = request.getRequestURL();
        log.info("requestURL:{}", requestURL);
        if (requestURL.toString().endsWith("/uc/userLogin/login")){
   
   
            //请求登录的接口,放行
            return false;
        }
        return true;
    }

    @Override
    public Object run() throws ZuulException {
   
   
        // 具体的过滤逻辑,比如对token的判断等
        log.info("进入tokenZuulFilter2");

        /*
        // 放行方式,都可以:
        return null;
        return true;
        return false;
        ctx.setSendZuulResponse(true);

        // 不放行并设置响应内容
        ctx.setSendZuulResponse(false);
        ctx.setResponseBody("xxxx");
        */
        return null;
    }

}

2.5 Zuul的降级处理

实现此接口(FallbackProvider)中的方法,详细见项目中 【GatewayFallbackProvider】 类

三、feign的配置与使用

3.1 服务的消费者(示例:order-server 调用 user-server)

  • 依赖
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
  • 启动类注解
@EnableFeignClients
  • @FeignClient 的使用
@FeignClient(name = "user-server", fallback = UserTestFeignClientFallback.class) 
public interface UserTestFeignClient {
   
   
    @GetMapping("/adminUser/findByUsername/{username}")
    ResultVo<Object> findByUsernameGet(@PathVariable("username") String username) ;

    @PostMapping("/adminUser/findByUsername/{username}")
    ResultVo<Object> findByUsernamePost(@PathVariable("username") String username);
}
  • yml配置
######## feign的配置  start ########
feign:
  hystrix:
    enabled: true          # 开启hystrix,使@FeignClient注解中fallback的指定降级处理生效
  httpclient:              #默认就使用httpclient,在pom里面添加就是httpclient,不添加就实现HttpUrlConnection
    enabled: true
    max-connections: 200
    max-connections-per-route: 50
  okhttp:
    enabled: false
#  client:
#    config:
#      default:
#        readTimeout: 5000
#        connectTimeout: 200

ribbon:
  eager-load:
    enabled: true
  ReadTimeout: ${READ_TIMEOUT:30000}            # 获取到响应内容的超时时间
  ConnectTimeout: ${CONNECTION_TIMEOUT:1000}          # 连接超时时间
  MaxAutoRetries: 0             # 在当前服务重试的次数
  MaxAutoRetriesNextServer: 1   # 默认轮询去重选列表中服务的次数
  OkToRetryOnAllOperations: ${ALLRETRY:false}  #是否所有操作都重试  (默认false)

hystrix:
  command:
    default:
      execution:
        timeout:
          enabled: true
        isolation:
          thread:
            timeoutInMilliseconds: ${THREAD_TIMEOUT:30000}
######## feign的配置  end ########
  • 优化

Feign 的底层 构建了一个RestTemplate 对象,而RestTemplate对象并没有直接发起请求的能力,其内部使用HttpURLConnection 来实际发请求的 。Feign 里面RestTemplate 利用的使用JDK的HttpUrlConenction 发请求。 HttpUrlConnection 它的性能比较好,但是它不支持连接池特性,在并发量特别大时,需要频繁的创建连接。若没有池对象,则会创建大量的对象,导致性能下降,所以我们选有池的好一点

使用httpclient连接池,在pom里面添加依赖

<!--feign调用的httpclient连接池支持-->
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
</dependency>

3.2 服务的提供者

提供对应访问路径的Controller即可

3.3 feign-API 的抽取

image

  • 给每个服务提供者创建对应的 feign api 模块,抽取其FeignController
  • 注意:服务提供者中对api的实现,方法注解可以继承下来,但是参数注解需要加上去(不能漏)

四、重试机制、负载均衡

feign中默认使用的是RestTemplate,底层还是HttpURLConnection;
Zuul默认使用的是HttpClient,但是zuul没有开启重试,要引入其他依赖并添加配置开启重试机制;

4.1 HttpClient VS OKHttp

  • 1、都可以使用连接池,达到优化的目的;2、ribbon都支持;

  • OkHttp是一个Http-client,它的主要优势:

·HTTP/2 支持允许所有访问同一主机的请求共享一个socket
·支持GZIP压缩
·响应缓存减少重复请求
OkHttp多例模式下性能更好
  • HttpClient:
如果是在单例模式下,推荐使用HttpClient效率更高;原因是httpClient的创建相对来说慢一些,在单例情况下,httpClient的速度更有优势

4.2 feign使用HttpClient

  • 添加依赖:
<!--feign调用的httpclient连接池支持-->
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
</dependency>
  • 在添加依赖的服务中添加配置
feign:
  httpclient:
    enabled: true          #默认就是开启的,只要引入了HttpClient的依赖,就会加载并使用httpClient
    max-connections: 200   # 默认连接池最大200个
    max-connections-per-route: 50    #默认单个路由请求上最大连接数50个

4.3 feign使用OKHttp

  • 依赖
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-okhttp</artifactId>
</dependency>
  • yml配置
feign:
  httpclient:
    enabled: false              #关闭httpClient
    max-connections: 200        #okhttp也是从这里取值 和httpclient一样
    max-connections-per-route: 50  #okhttp也是从这里取值 和httpclient一样
  okhttp:
    enabled: true              #开启okhttp

ps:部分源码信息可以查看此类 OkHttpFeignConfiguration

4.4 zuul 使用默认httpClient时,需要手动开启重试机制

  • 依赖
<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
</dependency>
  • yml配置
zuul:
  retryable: true       # 添加retry依赖后,开启重试
ribbon:
  ReadTimeout: 30000
  connectTimeout: 2000
  MaxAutoRetries: 0             # 在当前服务重试的次数
  MaxAutoRetriesNextServer: 1   # 默认轮询去重选列表中服务的次数
  OkToRetryOnAllOperations: false # 是否所有类型请求都重试 默认false(只有GET请求重试)

4.5 zuul 使用OKHttp

  • 依赖
<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
</dependency>
  • yml配置
ribbon:
  http:
    client:
      enabled: false          # 关闭httpclient
  okhttp:
    enabled: true             # 开启okhttp

4.6 ribbon.OkToRetryOnAllOperations

  • 源码查看:FeignLoadBalancer
public RequestSpecificRetryHandler getRequestSpecificRetryHandler(FeignLoadBalancer.RibbonRequest request, IClientConfig requestConfig) {
   
   
        if (this.ribbon.isOkToRetryOnAllOperations()) {
   
   
            return new RequestSpecificRetryHandler(true, true, this.getRetryHandler(), requestConfig);
        } else {
   
   
            return !request.toRequest().httpMethod().name().equals("GET") ? new RequestSpecificRetryHandler(true, false, this.getRetryHandler(), requestConfig) : new RequestSpecificRetryHandler(true, true, this.getRetryHandler(), requestConfig);
        }
    }
    public RequestSpecificRetryHandler(boolean okToRetryOnConnectErrors, boolean okToRetryOnAllErrors, RetryHandler baseRetryHandler, @Nullable IClientConfig requestConfig) {
   
   
        this.retrySameServer = -1;
        this.retryNextServer = -1;
        this.connectionRelated = Lists.newArrayList(new Class[]{
   
   SocketException.class});
        Preconditions.checkNotNull(baseRetryHandler);
        this.okToRetryOnConnectErrors = okToRetryOnConnectErrors;
        this.okToRetryOnAllErrors = okToRetryOnAllErrors;
        this.fallback = baseRetryHandler;
        if (requestConfig != null) {
   
   
            if (requestConfig.containsProperty(CommonClientConfigKey.MaxAutoRetries)) {
   
   
                this.retrySameServer = (Integer)requestConfig.get(CommonClientConfigKey.MaxAutoRetries);
            }

            if (requestConfig.containsProperty(CommonClientConfigKey.MaxAutoRetriesNextServer)) {
   
   
                this.retryNextServer = (Integer)requestConfig.get(CommonClientConfigKey.MaxAutoRetriesNextServer);
            }
        }

    }

4.7 ribbon重试存在的问题:

issues: SocketTimeoutException(connect time out) is not judged as a ConnectionException: https://github.com/Netflix/ribbon/issues/359

csdn博客:https://blog.csdn.net/weixin_44032384/article/details/104414846

五、swagger的使用

5.1 分别在网关服务与其他服务中配置

(可以抽取swagger公共模块)

添加依赖

<!--swagger (已父项目中声明依赖与版本号:2.9.2) -->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
</dependency>

网关服务中需要的配置:

@Configuration
@EnableSwagger2
public class SwaggerConfig {
   
   

    @Autowired
    private DiscoveryClientRouteLocator discoveryClientRouteLocator;

    @Primary
    @Bean
    public SwaggerResourcesProvider swaggerResourcesProvider() {
   
   
        return new SwaggerResourcesProvider() {
   
   
            @Override
            public List<SwaggerResource> get() {
   
   
                List<SwaggerResource> resources = new ArrayList<>();
                List<Route> routes = discoveryClientRouteLocator.getRoutes();
                for (Route route : routes) {
   
   
                    // 从网关中取获取各个服务的 api-docs
                    resources.add(swaggerResource(route.getId(), route.getFullPath().replace("**", "v2/api-docs")));
                }
                return resources;
            }
        };
    }

    private SwaggerResource swaggerResource(String name, String location) {
   
   
        SwaggerResource swaggerResource = new SwaggerResource();
        swaggerResource.setName(name);
        swaggerResource.setLocation(location);
        swaggerResource.setSwaggerVersion("2.0");
        return swaggerResource;
    }

}

其他微服务中需要的配置:

@Configuration
@EnableSwagger2
@ConfigurationProperties(prefix = "com.swagger")   // 自定义前缀
@Data
public class Swagger2Config {
   
   
    //在各个项目配置文件中添加相应的属性:
    private String basePackage = "com.basePackage";    
    private String title = "swagger-title";
    private String description;

    @Bean
    public Docket createRestApi() {
   
   
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select().apis(RequestHandlerSelectors.basePackage(basePackage))
                .paths(PathSelectors.any()).build().securitySchemes(securitySchemes())
                .securityContexts(securityContexts());
    }

    private ApiInfo apiInfo() {
   
   
        return new ApiInfoBuilder()
                // 文档标题
                .title(title)
                // 文档描述
                .description(StringUtils.hasText(description) ? description : title)
               // .termsOfServiceUrl("https://www.***.com")
                // 设置文档版本号
                .version("v2.3")
                .build();
    }

    private List<ApiKey> securitySchemes() {
   
   
        List<ApiKey> apiKeyList = new ArrayList();
        apiKeyList.add(new ApiKey("Authorization", "Authorization", "header"));
        return apiKeyList;
    }

    private List<SecurityContext> securityContexts() {
   
   
        List<SecurityContext> securityContexts = new ArrayList<>();
        securityContexts.add(
                SecurityContext.builder()
                        .securityReferences(defaultAuth())
                        .forPaths(PathSelectors.regex("^(?!auth).*$"))
                        .build());
        return securityContexts;
    }

    List<SecurityReference> defaultAuth() {
   
   
        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        List<SecurityReference> securityReferences = new ArrayList<>();
        securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
        return securityReferences;
    }

}

访问地址

ip:port/swagger-ui.html

可以通过网关服务的swagger页面去调用其他服务(会先经过网关)

如果是直接访问某个服务的swagger页面,则直接调用该服务,不经过网关

5.2 注解的使用

六、Maven在 Linux中使用

6.1 maven3.6.1下载地址

wget https://archive.apache.org/dist/maven/maven-3/3.6.1/binaries/

6.2 修改settings.xml配置

#自定义仓库地址
<localRepository>/usr/local/server/maven/repository3.6.1</localRepository>
#阿里云maven仓库
  <mirrors>
    <mirror>  
        <id>nexus-aliyun</id>  
        <mirrorOf>central</mirrorOf>    
        <name>Nexus aliyun</name>  
        <url>http://maven.aliyun.com/nexus/content/groups/public</url>  
    </mirror> 
  </mirrors> 
#修改maven的默认jdk版本为1.8
<profiles>
    <profile>
        <id>jdk-1.8</id>
        <activation>
            <activeByDefault>true</activeByDefault>
            <jdk>1.8</jdk>
        </activation>
        <properties>
            <maven.compiler.source>1.8</maven.compiler.source>
            <maven.compiler.target>1.8</maven.compiler.target>
            <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
        </properties>
    </profile>
</profiles>

6.3 配置mvn环境变量

echo "export MAVEN_HOME=/usr/local/maven3.6.1/apache-maven-3.6.1"  >>  /etc/profile
echo "export PATH=$MAVEN_HOME/bin:$PATH"  >>  /etc/profile
source /etc/profile
测试:
mvn -v

6.4 mvn常用命令

mvn  clean   
mvn  compile    # 编译
mvn  package    # 打包
mvn  install    # 打包并构建到本地仓库
mvn install -Dmaven.test.skip=true   # 打包并跳过测试
#单独构建模块 commonweb   同时会构建commonweb模块依赖的其他模块(上游模块)
mvn install -pl commonweb -am  
#单独构建模块commonweb ,同时构建依赖模块commonweb 的其他模块(下游模块)
mvn install -pl commonweb  -amd

#单独构建模块nnhx-eureka 并跳过测试
mvn install -pl  nnhx-eureka -am  -Dmaven.test.skip=true

#单独构建模块register-center 下面的 nnhx-eureka 并跳过测试
mvn install -pl  register-center/nnhx-eureka -am -Dmaven.test.skip=true

ps:构建指定模块时,建议先构建其上游模块(如果少量模块构建推荐使用命令操作,带上此参数【 -am】 ) ,且尽量避免同时构建同一个模块

相关文章
|
3天前
|
负载均衡 算法
SpringCloud&Ribbon负载均衡原理与实践
SpringCloud&Ribbon负载均衡原理与实践
10 3
|
4天前
|
监控 Java 微服务
第八章 Spring Cloud 之 Hystrix
第八章 Spring Cloud 之 Hystrix
|
20天前
|
Nacos
SpringCloud Feign使用
SpringCloud Feign使用
23 1
|
27天前
Springcloud-ribbon和hystrix配置
Springcloud-ribbon和hystrix配置
8 0
|
1月前
|
SpringCloudAlibaba Java 测试技术
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(六)Hystrix(豪猪哥)的使用
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(六)Hystrix(豪猪哥)的使用
39 1
|
1月前
|
负载均衡 算法 Java
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(四)Ribbon的使用
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(四)Ribbon的使用
25 0
|
1月前
|
负载均衡
【二十】搭建SpringCloud项目四(Ribbon)
【二十】搭建SpringCloud项目四(Ribbon)
20 0
|
1月前
【十九】搭建SpringCloud项目三(Feign)
【十九】搭建SpringCloud项目三(Feign)
22 0
|
1月前
|
存储 负载均衡 Java
【Spring底层原理高级进阶】微服务 Spring Cloud 的注册发现机制:Eureka 的架构设计、服务注册与发现的实现原理,深入掌握 Ribbon 和 Feign 的用法 ️
【Spring底层原理高级进阶】微服务 Spring Cloud 的注册发现机制:Eureka 的架构设计、服务注册与发现的实现原理,深入掌握 Ribbon 和 Feign 的用法 ️
|
1月前
|
负载均衡 算法 Java
SpringCloud负载均衡源码解析 | 带你从表层一步步剖析Ribbon组件如何实现负载均衡功能
SpringCloud负载均衡源码解析 | 带你从表层一步步剖析Ribbon组件如何实现负载均衡功能