https://github.com/Netflix/ribbon/wiki/Getting-Started
前面的80通过轮询负载访问8001/8002,即 负载均衡 + RestTemplate调用
总结 : Ribbon其实就是一个软负载均衡的客户端组件, 他可以和其他所需请求的客户端结合使用,和eureka结合只是其中一个实例
还有 postForObject / postForEntity (Post 请求方法)
根据前面说的官方文档中的警告,不要被@ComponentScan扫描到,否则达不到特殊化定制的目的
而springboot项目中的@ComponentScan就在主启动类上的@SpringBootApplication中(源码中可以看到),所以为了避免被扫到,就不要和主启动类在同一个包下
@Configuration
public class MySelfRule {
@Bean
public IRule myRule() {
// 将默认的轮换算法替换为随机算法
return new RandomRule();
}
}
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE", configuration = MySelfRule.class)
创建接口: LoadBalancer
public interface LoadBalancer {
// 从服务集群中选择出本次来提供服务的一个service
ServiceInstance instances(List<ServiceInstance> serviceInstances);
}
创建 LoadBalancer 接口的实现类 MyLB
@Component
public class MyLB implements LoadBalancer {
private AtomicInteger atomicInteger = new AtomicInteger(0);
// 提供服务的次数
public final int getAndIncrement() {
int current;
int next;
do {
current = this.atomicInteger.get();
next = (current+1) % Integer.MAX_VALUE;
}while(!this.atomicInteger.compareAndSet(current, next));
System.out.println("-------第" + next + "次访问");
return next;
}
@Override
public ServiceInstance instances(List<ServiceInstance> serviceInstances) {
// 轮询,需要提供服务的实例下标
int index = getAndIncrement() % serviceInstances.size();
// 返回该服务实例
return serviceInstances.get(index);
}
}
在 8001 和 8002的 PaymentController 上增加逻辑代码 (添加相同的代码)
@GetMapping("/payment/lb")
public String getPaymentLB() {
return serverPort;
}
在 80 的 OrderController 添加业务逻辑
// 注意别导错包
@Resource
private DiscoveryClient discoveryClient;
// 注入的是接口,不是实现类
@Resource
private LoadBalancer loadBalancer;
@GetMapping("/consumer/payment/lb")
public String getPaymentLB() {
// 获取服务名为:cloud-payment-service 的所有实例
List<ServiceInstance> instances = discoveryClient.getInstances("cloud-payment-service");
if (instances == null || instances.size() <= 0) {
return null;
}
// 调用方法,得到本次提供服务的实例
ServiceInstance instance = loadBalancer.instances(instances);
URI uri = instance.getUri();
return restTemplate.getForObject(uri + "/payment/lb", String.class);
}
https://github.com/spring-cloud/spring-cloud-openfeign
微服务调用接口 + @FeignClient
<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>cloud2020artifactId>
<groupId>com.atguigu.springcloudgroupId>
<version>1.0-SNAPSHOTversion>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>cloud-consumer-feign-order80artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-openfeignartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
dependency>
<dependency>
<groupId>com.atguigu.springcloudgroupId>
<artifactId>cloud-api-commonsartifactId>
<version>${project.version}version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<scope>runtimescope>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>com.atguigu.springcloudgroupId>
<artifactId>cloud-api-commonsartifactId>
<version>1.0-SNAPSHOTversion>
<scope>compilescope>
dependency>
dependencies>
project>
server:
port: 80
eureka:
client:
register-with-eureka: false
fetch-registry: true
service-url:
defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
@SpringBootApplication
@EnableFeignClients // 开启FeignClient功能,后面使用@FeignClient注解才有效
public class OrderFeignMain80 {
public static void main(String[] args) {
SpringApplication.run(OrderFeignMain80.class, args);
}
}
@Component
//可以远程调用该服务名的controller
@FeignClient("CLOUD-PAYMENT-SERVICE")
public interface PaymentFeignService {
@GetMapping("/payment/get/{id}")
public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);
}
@RestController
@Slf4j
public class OrderFeignController {
@Resource
private PaymentFeignService paymentFeignService;
@GetMapping("/consumer/payment/get/{id}")
public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id) {
return paymentFeignService.getPaymentById(id);
}
}
@GetMapping("/payment/Feign/Timeout")
public String paymentFeignTimeout() throws InterruptedException {
// 延迟3s
TimeUnit.SECONDS.sleep(3000);
return serverPort;
}
@GetMapping("/payment/Feign/Timeout")
public String paymentFeignTimeout();
@GetMapping("/consumer/payment/Feign/Timeout")
public String paymentFeignTimeout() {
return paymentFeignService.paymentFeignTimeout();
}
OpenFeign默认等待1秒钟,超过后报错
#设置feign客户端超时时间(OpenFeign默认支持ribbon)(单位:毫秒)
ribbon:
#指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间
ReadTimeout: 5000
#指的是建立连接后从服务器读取到可用资源所用的时间
ConnectTimeout: 5000
@Configuration
public class FeignConfig {
// feignClient配置日志级别
@Bean
public Logger.Level feignLoggerLevel() {
// 请求和响应的头信息,请求和响应的正文及元数据
return Logger.Level.FULL;
}
}
logging:
level:
# feign日志以什么级别监控哪个接口
com.atguigu.springcloud.service.PaymentFeignService: debug