软件系统开发定制SpringCloud快速学习(2)——Ribbon

SpringCloud快速学习(2)——

软件系统开发定制个人的动力节点视频学习笔记 视频地址:https://www.bilibili.com/video/BV1f94y1U7AB

基本介绍

​ Spring Cloud Ribbon 软件系统开发定制是一个基于 HTTP 和 TCP 的软件系统开发定制客户端负载均衡工具,它基于 Netflix

Ribbon 实现。通过 Spring Cloud 的封装,软件系统开发定制可以让我们轻松地将面向服务的 REST 模版请求

软件系统开发定制自动转换成客户端负载均衡的服务调用。 hash 权重

简单的说 Ribbon 就是 netfix 公司的一个开源项目,主要功能是提供客户端负载均衡算法和

服务调用。Ribbon 客户端组件提供了一套完善的配置项,比如连接超时,重试等。

在 Spring Cloud 构建的微服务系统中, Ribbon 作为服务消费者的负载均衡器,有两种使

用方式,一种是和 RestTemplate 相结合,另一种是和 OpenFeign 相结合。OpenFeign 已经

默认集成了 Ribbon。

快速上手

架构

02-provider-a

  • 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>02-ribbon</artifactId>        <groupId>edu.bcy</groupId>        <version>1.0-SNAPSHOT</version>    </parent>    <modelVersion>4.0.0</modelVersion>    <artifactId>02-provider-a</artifactId>    <properties>        <java.version>1.8</java.version>        <spring-cloud.version>Hoxton.SR12</spring-cloud.version>    </properties>    <dependencies>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency>        <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-test</artifactId>            <scope>test</scope>        </dependency>    </dependencies>    <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>    <build>        <plugins>            <plugin>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-maven-plugin</artifactId>            </plugin>        </plugins>    </build></project>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • yml
server:    port: 8080spring:    application:        name: providereureka:    client:        service-url:            defaultZone: http://localhost:8761/eureka    instance:        hostname: localhost        prefer-ip-address: true        instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 启动类
@SpringBootApplication@EnableEurekaClientpublic class ProviderAApplication {    public static void main(String[] args) {        SpringApplication.run(ProviderAApplication.class, args);    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 开放接口
@RestControllerpublic class ProviderController {    @GetMapping("hello")    public String hello(){        return "我是提供者aaaa的接口";    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

02-provider-b

基本和 02-provider-a 一致

  • 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>02-ribbon</artifactId>        <groupId>edu.bcy</groupId>        <version>1.0-SNAPSHOT</version>    </parent>    <modelVersion>4.0.0</modelVersion>    <artifactId>02-provider-b</artifactId>    <properties>        <java.version>1.8</java.version>        <spring-cloud.version>Hoxton.SR12</spring-cloud.version>    </properties>    <dependencies>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency>        <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-test</artifactId>            <scope>test</scope>        </dependency>    </dependencies>    <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>    <build>        <plugins>            <plugin>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-maven-plugin</artifactId>            </plugin>        </plugins>    </build></project>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • yml
server:    port: 8081spring:    application:        name: providereureka:    client:        service-url:            defaultZone: http://localhost:8761/eureka    instance:        hostname: localhost        prefer-ip-address: true        instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 启动类
@SpringBootApplication@EnableEurekaClientpublic class ProviderBApplication {    public static void main(String[] args) {        SpringApplication.run(ProviderBApplication.class, args);    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 开放接口
@RestControllerpublic class ProviderController {    @GetMapping("hello")    public String hello(){        return "我是提供者bbbb的接口";    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

02-consumer

  • 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>02-ribbon</artifactId>        <groupId>edu.bcy</groupId>        <version>1.0-SNAPSHOT</version>    </parent>    <modelVersion>4.0.0</modelVersion>    <artifactId>02-consumer</artifactId>    <properties>        <java.version>1.8</java.version>        <spring-cloud.version>Hoxton.SR12</spring-cloud.version>    </properties>    <dependencies>        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-netflix-ribbon</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-eureka-client</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-test</artifactId>            <scope>test</scope>        </dependency>    </dependencies>    <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>    <build>        <plugins>            <plugin>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-maven-plugin</artifactId>            </plugin>        </plugins>    </build></project>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • yml
server:    port: 8082spring:    application:        name: consumereureka:    client:        service-url:            defaultZone: http://localhost:8761/eureka    instance:        hostname: localhost        prefer-ip-address: true        instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}# 访问不用的服务可以使用不用的算法规则#provider:  # 先写服务提供者的应用名称#    ribbon:#        NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule    #几种算法的全限定类名ribbon:    eager-load:        enabled: false # ribbon它只有自己的话 能不能做服务发现 借助eureka  # ribbon需要去eureka中获取服务列表 如果false就懒加载    eureka:        enabled: true    http:  # 我们使用ribbon 用的restTemplate发请求 java.net.HttpUrlConnection 发的请求  很方便 但是它不支持连接池        client:  # 发请求的工具有很多 httpClient  它支持连接池 效率更好  如果你想改请求的工具 记得加这个依赖即可            enabled: false    okhttp: # 这个也是请求工具 移动端用的比较多 轻量级的请求        enabled: false
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 启动类
@SpringBootApplication@EnableEurekaClientpublic class ConsumerApplication {    public static void main(String[] args) {        SpringApplication.run(ConsumerApplication.class, args);    }    /**     * 这个RestTemplate 已经变了     * LoadBalanced 他就会被ribbon来操作     * @return     */    @Bean    @LoadBalanced    public RestTemplate restTemplate(){        return new RestTemplate();    }    /**     * 往容器中放一个rule对象     * 你访问任何一个提供者 都是这个算法     * @return     */    @Bean    public IRule myRule(){        return new RandomRule();    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 负载均衡配置(这里实际上由启动类@LoadBalanced实现负载均衡,下面这个类就是看看)
import com.netflix.loadbalancer.ILoadBalancer;import com.netflix.loadbalancer.IRule;import com.netflix.loadbalancer.Server;import org.springframework.stereotype.Component;@Componentpublic class MyRule implements IRule {    @Override    public Server choose(Object key) {        return null;    }    @Override    public void setLoadBalancer(ILoadBalancer lb) {    }    @Override    public ILoadBalancer getLoadBalancer() {        return null;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 消费者接口
@RestControllerpublic class ConsumerController {    @Autowired    private RestTemplate restTemplate;    @Autowired    private LoadBalancerClient loadBalancerClient;    /**     * 思考 ribbon是怎么将 http://provider/hello 路径请求成功的     * http://127.0.0.1:8080/hello     * 1.拦截这个请求     * 2.截取主机名称     * 3.借助eureka来做服务发现 list<>     * 4.通过负载均衡算法 拿到一个服务ip port     * 5.reConstructURL     * 6.发起请求     *     * @param serviceName     * @return     */    @GetMapping("testRibbon")    public String testRibbon(String serviceName){        // 正常来讲 需要 拿到ip和port 以及 路径 才可以用        // http://provider/hello        String result = restTemplate.getForObject("http://" + serviceName + "/hello", String.class);        // 只要你给restTemplate 加了ribbon的注解 项目中这个对象发起的请求 都会走ribbon的代理        // 如果你想使用原生的restTemplate 就需要重新创建一个对象//        RestTemplate myRest = new RestTemplate();//        String forObject = myRest.getForObject("http://localhost:8888/aaa", String.class);        return result;    }    // 轮训的算法 怎么去实现    // 两台机器   A B    // A    // B    // A    // B    // 代码实现轮训的算法  List<机器>    // 请求次数    //  int index =   1 % size    list.get(index);    // % 取模 取余好处是一个周期函数 让得到的结果 总是小于 除数的    //  1 / 2    1 % 2    // 1%2=1    // 2%2=0    // 3%2=1    // 4%2=0    // 全局顶一个int i = 0    // i++  线程不安全的    // i % size    // 怎么能做一个线程安全的轮训算法   加锁 效率极低  CAS 自旋锁 没有线程的等待和唤醒的开销    // CAS 优点 性能好 java层面无锁的状态  但是在jvm层面 有锁的cmpxchg    // CAS 缺点 会导致短暂时间内 CPU 飙升  还有ABA 问题    /**     * 核心是负载均衡     * @param serviceName     * @return     */    @GetMapping("testRibbonRule")    public String testRibbonRule(String serviceName){        ServiceInstance choose = loadBalancerClient.choose(serviceName);        return choose.toString();    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71

结果

消费者调用生产者

总结

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发