Los principiantes de microservicios de SpringCloud también pueden tomar (Hoxton.SR8) (2) Ribbon | Consumidores de servicios

Simplemente comience, copie directamente y podrá crear microservicios (Hoxton.SR8) Se lanza 2020.8.28, los artículos creados por SpringCloud se están resolviendo, no se pierda los productos secos

Resumen:

Spring Cloud Netflix Ribbon es uno de los componentes centrales del subproyecto Spring Cloud Netflix. Proporciona principalmente funciones de equilibrio de carga para llamadas entre servicios y reenvío de puerta de enlace de API. En la arquitectura de microservicio, muchos servicios se implementarán con múltiples, y otros servicios llamarán el servicio Cómo garantizar el equilibrio de carga es un problema que debe tenerse en cuenta. El equilibrio de carga puede aumentar la disponibilidad y escalabilidad del sistema.Cuando usamos RestTemplate para llamar a otros servicios, Ribbon puede implementar fácilmente el equilibrio de carga. Este artículo presentará su uso en detalle.

1. Cree un módulo de servicio al usuario

Nota: Consulte la configuración del cliente del artículo anterior (1) para configuración y construcción.

   

1.1 Crear UserApiController para proporcionar servicios de interfaz

package com.zqh.www.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * 用户服务类
 */
@RestController
@RequestMapping("/api/user")
public class UserApiController {

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

    @GetMapping("/getUserList")
    public Map<String, Object> getUserList() {
        System.out.println("我是:" + port + "有人调用我啦");
        ArrayList<User> dataList = new ArrayList<>();
        User user = new User();
        user.setUserId(1);
        user.setUserName("我是测试1");
        dataList.add(user);
        User user2 = new User();
        user2.setUserId(2);
        user2.setUserName("我是测试2");
        dataList.add(user2);
        HashMap<String, Object> resultMap = new HashMap<>();
        resultMap.put("code", "200");
        resultMap.put("msg", "获取成功");
        resultMap.put("data", dataList);
        return resultMap;
    }

    // 为了方便演示,所以我就直接在这里创建了一个类,大家不要照搬哦
    class User {
        private Integer userId;
        private String userName;

        public Integer getUserId() {
            return userId;
        }

        public void setUserId(Integer userId) {
            this.userId = userId;
        }

        public String getUserName() {
            return userName;
        }

        public void setUserName(String userName) {
            this.userName = userName;
        }
    }
}

2. Cree un módulo de servicio de cinta para llamar al servicio de usuario

Nota: Consulte la configuración del cliente del artículo anterior (1) para configuración y construcción.

  

  

2.1 Cree RibbonApiController y llame a UserApiController 

package com.zqh.www.controller;

import com.zqh.www.utils.RestTemplateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;

@RestController
@RequestMapping("/api/ribbon")
public class RibbonApiController {

    @Autowired
    private RestTemplateUtils restTemplateUtils;

    private String userServiceUrl = "http://user-service";
//    private String userServiceUrl = "http://localhost:8084";

    @GetMapping("/getUserList")
    public Map<String, Object> getUserList() {
        return restTemplateUtils.exchange(userServiceUrl + "/api/user/getUserList", HttpMethod.GET, null, null, null, Map.class);
    }
}

2.2 RestTemplateUtils

package com.zqh.www.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.util.Map;

@Component
public class RestTemplateUtils {

    private final static Logger logger = LoggerFactory.getLogger(RestTemplateUtils.class);

    @Autowired
    private RestTemplate restTemplate;

    /**
     * @param url           请求路径
     * @param method        请求方式? HttpMethod.POST/HttpMethod.GET
     * @param uriVariables  表单传参的参数
     * @param jsonObject    JSON格式传参的参数
     * @param requestHeader 请求头
     * @param responseType  返回结果Class
     * @return
     * @Description: JSON格式参数和表单参数一起传
     */
    public <T> T exchange(String url, HttpMethod method, Map<String, Object> uriVariables, Object jsonObject, HttpHeaders requestHeader, Class<T> responseType) {
//		一般的表单传参
        String uriVariablesParam = "";
        if (null != uriVariables && 0 != uriVariables.size()) {
            StringBuffer uriSb = new StringBuffer("?");
            uriVariables.forEach((k, v) -> {
                uriSb.append(k).append("=").append("{").append(k).append("}").append("&");
            });
            uriVariablesParam = uriSb.substring(0, uriSb.length() - 1).toString();
        }
        HttpHeaders requestHeaders = requestHeader;
        if (null == requestHeaders) {
            requestHeaders = new HttpHeaders();
        }

        HttpEntity<Object> requestEntity = new HttpEntity<>(null, requestHeaders);
        if (null != jsonObject) {
            requestEntity = new HttpEntity<>(jsonObject, requestHeaders);
        }
        url += uriVariablesParam;
        long startTime = System.currentTimeMillis();
        if (null == uriVariables || 0 == uriVariables.size()) {
            T body = restTemplate.exchange(url, method, requestEntity, responseType).getBody();
            logger.info("【接口请求】【{}】【处理时间:{}】【普通参数:{}】【JSON参数:{}】【返回结果:{}】", url, System.currentTimeMillis() - startTime, uriVariables, jsonObject, body);
            return body;
        }
        T body = restTemplate.exchange(url, method, requestEntity, responseType, uriVariables).getBody();
        logger.info("【接口请求】【{}】【处理时间:{}】【普通参数:{}】【JSON参数:{}】【返回结果:{}】", url, System.currentTimeMillis() - startTime, uriVariables, jsonObject, body);
        return body;
    }
}

2.3 RibbonConfig

package com.zqh.www.config;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.List;

@Configuration
public class RibbonConfig {

    /**
     * 使用@LoadBalanced注解赋予RestTemplate负载均衡的能力,以及根据微服务名称调用接口的能力
     *
     * @return
     */
    @LoadBalanced
    @Bean
    public RestTemplate restTemplate() {
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
        simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);

        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        objectMapper.registerModule(simpleModule);

        RestTemplate restTemplate = new RestTemplate();
        List<HttpMessageConverter<?>> converters = new ArrayList<>();
        MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
        jsonConverter.setObjectMapper(objectMapper);
        converters.add(jsonConverter);
        restTemplate.setMessageConverters(converters);
        return restTemplate;
    }
}

3. Llamada de prueba de servicio único

    

 

4. Servicio de carga

Nota:

  1. Primero abra un servicio de usuario sin cerrarlo, luego copie un servicio de usuario y cambie el nombre

      
  2. Modifique el archivo yml de user-service, preste atención a si el servicio anterior no está cerrado o en ejecución, y luego inicie la aplicación recién configurada

      
  3. En este momento, habrá 2 servicios de usuario en el registro eureka

4.1 Prueba de llamada

Primera llamada: se encontró que se llamó al servicio de usuario del puerto 8086, pero no al servicio de usuario del puerto 8084

  

Primera llamada: se encuentra que se ha llamado al servicio de usuario del puerto 8084, pero no se ha llamado al servicio de usuario del puerto 8086 y la carga está completa
 

Configuración común de 5 cintas

Nota:

  1. La configuración no tiene efecto y el documento no ha encontrado el motivo. . Si algún lector conoce el motivo, hágamelo saber, muchas gracias

5.1 Configuración global

ribbon:
  httpclient:
    enabled: true
  ConnectTimeout: 3000 #服务请求连接超时时间(毫秒)
  ReadTimeout: 3000 #服务请求处理超时时间(毫秒)
  OkToRetryOnAllOperations: true #对超时请求启用重试机制
  MaxAutoRetriesNextServer: 1 #切换重试实例的最大个数
  MaxAutoRetries: 1 # 切换实例后重试最大次数
  NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #修改负载均衡算法

5.2 Configuración de servicio individual

user-service:
  ribbon:
    httpclient:
      enabled: true
    ConnectTimeout: 3000 #服务请求连接超时时间(毫秒)
    ReadTimeout: 3000 #服务请求处理超时时间(毫秒)
    OkToRetryOnAllOperations: true #对超时请求启用重试机制
    MaxAutoRetriesNextServer: 1 #切换重试实例的最大个数
    MaxAutoRetries: 1 # 切换实例后重试最大次数
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #修改负载均衡算法

6. Resumen

  1. Use la cinta para llamar al servicio y pruebe la llamada de interfaz bajo la carga del servicio
  2. Tratar con datos faltantes cuando se usa RestTemplate para devolver un resultado de tipo List  

7.dirección del huésped

Referencia fuente

Supongo que te gusta

Origin blog.csdn.net/itjavaee/article/details/109049288
Recomendado
Clasificación