zoukankan      html  css  js  c++  java
  • Spring-Cloud-Ribbon学习笔记(一):入门

    简介

    Spring Cloud Ribbon是一个基于Http和TCP的客户端负载均衡工具,它是基于Netflix Ribbon实现的。它不像服务注册中心、配置中心、API网关那样独立部署,但是它几乎存在于每个微服务的基础设施中。理解Ribbon对于我们使用Spring Cloud来讲非常的重要,因为负载均衡是对系统的高可用、网络压力的缓解和处理能力扩容的重要手段之一。

    在Spring Cloud中,有两种服务调用方式,一种是Ribbon+RestTemplate,另一种是Feign。文本先讲解下基于Ribbon+RestTemplate的用法。

    当Ribbon与Eureka配合使用时,Ribbon可自动从Eureka Server获取服务提供者地址列表,并基于负载均衡算法,请求其中一个服务提供者实例。

    实现

    新建服务spring-cloud-ribbon

    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.yan</groupId>
        <artifactId>spring-cloud-ribbon</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.1.0.RELEASE</version>
            <relativePath/>
        </parent>
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>Finchley.RELEASE</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-ribbon</artifactId>
                <version>RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-config</artifactId>
                <version>RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-eureka</artifactId>
                <version>RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
                <version>RELEASE</version>
            </dependency>
        </dependencies>
    
    </project>
    

    配置

    yml

    server:
      port: 8004
    spring:
      application:
        name: spring-cloud-ribbon
      cloud:
        config:
          discovery:
            enabled: true
            service-id: spring-cloud-config-server
      profiles:
        active: dev
    eureka:
      client:
        serviceUrl:
          defaultZone: http://localhost:8761/eureka/
    

    启动类

    核心是配有注解@LoadBalanced的RestTemplate的Bean配置

    package com.yan;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.client.RestTemplate;
    
    @SpringBootApplication
    @Configuration
    @EnableDiscoveryClient
    public class RibbonApplication {
        public static void main(String[] args) {
            SpringApplication.run(RibbonApplication.class, args);
        }
    
        @Bean
        @LoadBalanced
        public RestTemplate restTemplate() {
            return new RestTemplate();
        }
    }
    
    

    Controller

    package com.yan.controller;
    
    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.http.HttpEntity;
    import org.springframework.web.bind.annotation.*;
    import org.springframework.web.client.RestTemplate;
    
    import java.util.StringJoiner;
    
    @RestController
    @RequestMapping("/ribbon")
    public class RibbonController {
        private final RestTemplate template;
    
        @Autowired
        public RibbonController(RestTemplate template) {
            this.template = template;
        }
    
        @GetMapping("/get")
        public Object get(String svcName, String url, String className) {
            Class<?> clazz = getResponseType(className);
            String uri = getUrl(svcName, url);
            return template.getForObject(uri, clazz);
        }
    
        @PostMapping("/post")
        public Object post(@RequestParam String svcName, @RequestParam String url, @RequestParam String className, @RequestBody HttpEntity<?> httpEntity) throws JsonProcessingException {
            Class<?> clazz = getResponseType(className);
            String url1 = getUrl(svcName, url);
            Object res = template.postForObject(url1, httpEntity, clazz);
            String resJson = new ObjectMapper().writeValueAsString(res);
            System.out.println(resJson);
            return res;
        }
    
        private Class<?> getResponseType(@RequestParam String className) {
            Class<?> clazz;
            try {
                clazz = Class.forName(className);
            } catch (ClassNotFoundException e) {
                clazz = String.class;
            }
            return clazz;
        }
    
        private String getUrl(String svcName, String url) {
            StringJoiner stringJoiner = new StringJoiner("/");
            String uri = stringJoiner.add(svcName).add(url).toString().replaceAll("/+", "/");
            return "http://" + uri;
        }
    
    }
    
    

    测试

    假如我有两个名叫svcA的服务,同时注册到同一个Eureka上,只是端口号不同,它们都有一个post接口定义如下:

        @Value("${server.port}")
        private int port;
    
        @PostMapping("/post/{name}")
        public String post(@PathVariable String name, @RequestBody String type) {
            return "svcA:" + port + "===>
    " + "name:" + name + "
    type:" + type;
        }
    

    打开Postman:
    发送请求:http://localhost:8004/ribbon/post?svcName=SVCA&url=/post/xixi&className=java.lang.String
    Header:{'Content-Type': 'application/json'}
    Body: {'raw': {
    {
    "headers": {"Content-Type": ["application/json"]},
    "body": "haha"
    }
    }}

    多次点击发送请求,在ribbon服务下看到日志:

    "svcA:8081===>
    name:xixi
    type:haha"
    "svcA:8087===>
    name:xixi
    type:haha"
    "svcA:8081===>
    name:xixi
    type:haha"
    "svcA:8087===>
    name:xixi
    type:haha"
    "svcA:8081===>
    name:xixi
    type:haha"
    "svcA:8087===>
    name:xixi
    type:haha"
    

    两个服务交替接收请求,这说明Ribbon配置生效了。

  • 相关阅读:
    瀑布流-03-通过封装的自定义布局快速实现商品展示
    瀑布流-02-手把手教你封装自定义布局
    瀑布流-01-自定义布局实现绚丽的瀑布流
    CoreAnimation-09-模拟时钟
    CoreAnimation-08-CATransition
    CoreAnimation-07-CAAnimationGroup
    CoreAnimation-06-CAKeyframeAnimation
    CoreAnimation-05-CABasicAnimation
    CoreAnimation-04-核心动画必备基础
    logstash+elasticsearch 错误摘记
  • 原文地址:https://www.cnblogs.com/yw0219/p/10428521.html
Copyright © 2011-2022 走看看