ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

SpringCloud——服务调用入门

2020-12-13 17:57:07  阅读:135  来源: 互联网

标签:调用 return 入门 SpringCloud id 服务 public Ribbon 客户端


对于各个服务都配置到注册中心,我们需要一个技术使得这些服务能够互相调用使用。在原始服务调用是采用httpclient,之后演变成restTemplate(由spring提供的访问rest服务的模板工具集)。

Ribbon

1.Ribbon:基于Netflix Ribbon实现的一套客户端负载均衡的工具。主要功能是提供客户端的软件负载均衡算法和服务调用。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。
2.Ribbon工作流程:首先选择EurekaServer,优先选择同一个区域内负载较少的server。再在根据用户指定的策略,从server中取到的服务注册列表中选择一个地址。
3.Ribbon是采用LB(Load Balance)负载均衡:将用户的多个请求平均分摊到多个服务上面。和我们所认知的NGINX负载均衡不同,Nginx是服务器的负债均衡,客户端将所有请求交给Nginx,再由Nginx实现转发请求,即负载均衡是由服务器完成。
4.DiscoveryClient:对于注册eureka里面的微服务,可以通过服务发现来获得该服务的信息。需要在主启动类上加@EnableDiscoveryClient

 @GetMapping("/payment/discovery")
    public Object discovery(){
        // 获取注册中心的服务
        List<String> services = discoveryClient.getServices();
        for(String element: services){
            log.info("***element***"+element);
        }
        // 获取指定服务名的服务信息
        List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
        for(ServiceInstance instance:instances){
            log.info(instance.getServiceId()+"\t"+instance.getHost()+"\t"+instance.getPort()+"\t"+
                    instance.getUri());
        }
        return this.discoveryClient;
    }

5.RestTemplate有两种调用服务方法:postForObjectpostForEntity

  //static final String PAYMENT_URL = "http://localhost:8081";

 static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";

@GetMapping("/consumer/payment/get/{id}")
    public CommonResult<Payment> getPayment(@PathVariable("id") Long id){
        /** postForObject(返回对象为响应体中数据转化为对象:Json)
         * 1.url: 请求地址
         * 2.responseType: 返回的数据
         */
        return  restTemplate.getForObject(PAYMENT_URL+"/payment/get/"+id,CommonResult.class);
    }

@GetMapping("/consumer/payment/getForEntity/{id}")
    public CommonResult<Payment> getPaymentEntity(@PathVariable("id") Long id){
        /** getForEntity(返回responseEntity对象含有相应中一些信息响应头、响应状态码) 返回需要加上getBody方法
         * 1.url: 请求地址
         * 2.responseType: 返回的数据
         */
        ResponseEntity<CommonResult> entity = restTemplate.getForEntity(PAYMENT_URL+"/payment/get/"+id,CommonResult.class);
        if(entity.getStatusCode().is2xxSuccessful()){
            log.info("ResponseEntity{}",entity);
            return entity.getBody();
        }else{
            return new CommonResult<>(400,"操作失败");
        }
    }

补充:对于Eureka集群 消费端不应该再去写死地址而是写服务名称(注册中心名字;大写),并且加上@LoadBalanced注解(默认是轮询机制)
在这里插入图片描述
6.Ribbon自带7种负载规则:
①com.netflix.loadbalancer.RoundRobinRule(轮询)
②com.netflix.loadbalancer.RandomRule(随机)
③com.netflix.loadbalancer.RetryRule(先按照RoundRobinRule的策略获取服务,如果获取服务失败则在指定时间内进行重试,获取可用的服务)
④WeightedResponseTimeRule(对RoundRobinRule的扩展,响应速度越快的实例选择权重越多大,越容易被选择)
⑤BestAvailableRule(会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务)
⑥AvailabilityFilteringRule(先过滤掉故障实例,再选择并发较小的实例)
⑦ZoneAvoidanceRule(默认规则,复合判断server所在区域的性能和server的可用性选择服务器)
7.Ribbon的替换规则:这个自定义配置类不能放在@ComponentScan所扫描的当前包下以及子包下,否则我们自定义的这个配置类就会被所有的Ribbon客户端所共享,达不到特殊化定制的目的了。不能去掉@LoadBalanced
自定义规则主启动类
8.负载均衡算法:rest第几次请求书%(取余)服务集群总数 = 实际调用服务器位置下标,每次重启rest从1开始。
注意:手写算法调用需要去掉@LoadBalanced注解

public interface LoadBalancer {
    ServiceInstance serviceInstance(List<ServiceInstance> serviceInstances);
}


@Component
public class MyLB implements LoadBalancer {

    private AtomicInteger atomicInteger = new AtomicInteger(0);

    /**
     * 获取当前请求次数
     * @return
     */
    public final  int getAndIncrement(){
        int current;
        int next;
        do{
            current = this.atomicInteger.get();
            next = current >+ Integer.MAX_VALUE ? 0:current + 1;
        }while (!this.atomicInteger.compareAndSet(current,next));
        System.out.println("*********next访问次数为:"+next);
        return  next;
    }



    /**
     * 负载均衡算法:
     *      第几次请求书%(取余)服务集群总数 =  实际调用服务器位置下标,每次重启rest从1开始。
     * @param serviceInstances
     * @return
     */
    @Override
    public ServiceInstance serviceInstance(List<ServiceInstance> serviceInstances) {
        int index = getAndIncrement() % serviceInstances.size();
        return serviceInstances.get(index);
    }
}

controller层代码:

@GetMapping(value = "/consumer/payment/lb")
    public String getPaymentLB() {
        List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");

        if(instances == null || instances.size() <= 0) {
            return null;
        }
        ServiceInstance serviceInstance = loadBalancer.serviceInstance(instances);
        URI uri = serviceInstance.getUri();
        return restTemplate.getForObject(uri+"/payment/lb",String.class);
    }

注意当这边一个服务挂掉都也能访问该服务但是会报错。
源码:
在这里插入图片描述
服务出错和结果:
在这里插入图片描述

在这里插入图片描述

OpenFeign

在这里插入图片描述
1.Feign:一个声明式WebService客户端。使用Feign能让编写Web Service客户端更加简单。只需创建一个服务接口然后在上面添加注解。Feign也支持可拔插式的编码器和解码器。Spring Cloud对Feign进行了封装,使其支持了Spring MVC标准注解和HttpMessageConverters。Feign可以与Eureka和Ribbon组合使用以支持负载均衡。
2.Ribbon+RestTemplate是模板化调用服务(一个接口被多处调用),而feign只需要定义服务绑定接口以声明式方法。
3.Feign是一个声明式的Web服务客户端,让编写Web服务客户端变得非常容易,只需 创建一个接口并在接口上添加注解即可
application.yml

server:
  port: 80

eureka:
  client:
    register-with-eureka: false
    fetchRegistry: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka

#设置feign客户端超时时间(OpenFeign默认支持ribbon)
ribbon:
  #指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间
  ReadTimeout: 5000
  #指的是建立连接后从服务器读取到可用资源所用的时间
  ConnectTimeout: 5000
logging:
  level:
    # feign日志以什么级别监控哪个接口
    com.charon.springcloud.service.PaymentFeignService: debug

主启动类:

@SpringBootApplication
@EnableFeignClients
public class OpenFeignMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OpenFeignMain80.class,args);
    }
}

Feign调用(接口)

@Component
@FeignClient(value = "CLOUD-PAYMENT-SERVICE")
public interface PaymentFeignService {

    @GetMapping(value = "/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);

    @GetMapping(value = "/payment/feign/timeout")
    public String paymentFeignTimeout();
}

4.openFeign一般默认是1秒钟,得不到就返回报错。所以有时候需要超时控制。
5.OpenFeign提供了日志打印的功能,了解Feign中Http请求的细节。说白了就是对于日志的监控和输出。
NULL:默认,不显示日志。
BASIC:仅记录请求方法,url,响应状态码。
HEADERS:出来了BASIC外还有请求和响应信息。
FULL:除了HEADERS外还有请求和响应的正文元数据。

@Configuration
public class FeignConfig {

    @Bean
    Logger.Level feignLoggerLevel(){
        return Logger.Level.FULL;
    }
}

标签:调用,return,入门,SpringCloud,id,服务,public,Ribbon,客户端
来源: https://blog.csdn.net/qq_41730219/article/details/111127134

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有