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
-
Los microservicios SpringCloud Xiaobai también pueden tomar (Hoxton.SR8) (4) Hystrix | Disyuntor
-
Los microservicios blancos de SpringCloud pueden tomar (Hoxton.SR8) (seis) Zuul | Services Gateway
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:
- Primero abra un servicio de usuario sin cerrarlo, luego copie un servicio de usuario y cambie el nombre
- 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
- 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:
- 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
- Use la cinta para llamar al servicio y pruebe la llamada de interfaz bajo la carga del servicio
- Tratar con datos faltantes cuando se usa RestTemplate para devolver un resultado de tipo List