SpringCloud 三种服务调用方式,你知道几种?

搭建服务测试环境

测试中,服务发现层采用Netflix的Eureka搭建。

主要步骤如下:

1.引入Eureka所需依赖


  
     org.springframework.cloud
     spring-cloud-starter-eureka-server
  



   org.springframework.cloud
   spring-cloud-starter-eureka

2.修改配置文件

服务端:

eureka:
  instance:
   hostname:  eureka9001.com  #eureka服务端的实例名称
   instance-id:  eureka9001
client:
   register-with-eureka:  false  #false表示不向注册中心注册自己
   fetch-registry:  false  # #false 表示自己就是注册中心,职责就是维护服务实例,并不需要去检索服务
   service-url:
   defaulteZone:  http://127.0.0.1:9001

客户端1:

server:
   port:  8002
spring:
   application:
     name:  licensingservice
eureka:
   instance:
     instance-id:  licensing-service-8002
     prefer-ip-address:  true
   client:
     register-with-eureka:  true
     fetch-registry:  true
     service-url:
       defaultZone:  http://127.0.0.1:9001/eureka/,

客户端2:

server:
  port:  8002
spring:
  application:
    name:  licensingservice
eureka:
  instance:
    instance-id:  licensing-service-8002
    prefer-ip-address:  true
  client:
    register-with-eureka:  true
    fetch-registry:  true
    service-url:
      defaultZone:  http://127.0.0.1:9001/eureka/,    

一组微服务的不同实例采服务名相同,不同的实例Id区分,分别对应,spring.application.name 和eureka.instance.instance-id。

3.启动服务

服务端:

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

客户端:

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

4.测试

进入到Eureka服务端地址,我这是127.0.0.1:9001,可以查看注册到注册中心的服务。

如图:

SpringCloud 三种服务调用方式,你知道几种?_第1张图片

注意事项:Eureka通过三次心跳检测均通过,服务才会成功注册到注册中心,默认每次间隔10s,及初次启动服务需等待30s才能在Eureka中看到注册服务。

消费者搭建

1.Discover Client方式

微服务中服务既是消费者也可以是调用者,因此消费者配置和上面服务配置大体一致,依赖及配置参考上面服务端搭建方式。启动主类添加EnableEurekaClient注释:

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

核心配置类:

@Component
public  class ConsumerDiscoveryClient {

   @Autowired
   private DiscoveryClient discoveryClient;

   public ServiceInstance getServiceInstance() {
    List serviceInstances = discoveryClient.getInstances( "licensingservice");
     if (serviceInstances.size() ==  0) {
       return  null;
    }
     return serviceInstances.get( 0);
  }

   public String getUrl(String url) {
    ServiceInstance serviceInstance= this.getServiceInstance();
     if (serviceInstance== null)
       throw  new RuntimeException( "404 ,NOT FOUND");
    String urlR=String.format(url,serviceInstance.getUri().toString());
     return urlR;
  }
}

通过DiscoveryClient从Eureka中获取licensingservice服务的实例数组,并返回第一个实例。

测试Controller

@RestController
@RequestMapping( "test")
public  class TestController {
   //注意必须new,否则会被ribbon拦截器拦截,改变URL行为
   private RestTemplate restTemplate= new RestTemplate();
   @Autowired
   private ConsumerDiscoveryClient consumerDiscoveryClient;
   @RequestMapping( "/getAllEmp")
   public List getAllLicense(){
    String url=consumerDiscoveryClient.getUrl( "%s/test/getAllEmp");
     return restTemplate.getForObject(url,List .class);
  }
}

测试:

  1. 调试信息

SpringCloud 三种服务调用方式,你知道几种?_第2张图片从该图可以直观看到licensingservice,拥有两个服务实例,并可以查看实例信息。

  1. 页面返回信息

SpringCloud 三种服务调用方式,你知道几种?_第3张图片成功查询到数据库存储信息。

2.Ribbon功能的Spring RestTemplate方式

依赖同上。

核心配置类:

//指明负载均衡算法
@Bean
public IRule iRule() {
   return  new RoundRobinRule();
}

@Bean
@LoadBalanced  //告诉Spring创建一个支持Ribbon负载均衡的RestTemplate
public RestTemplate restTemplate() {
   return  new RestTemplate();
}

设置负载均衡方式为轮询方式。

测试类:

@RestController
@RequestMapping( "rest")
public  class ConsumerRestController {

     @Autowired
     private RestTemplate restTemplate;
     private  final  static String SERVICE_URL_PREFIX =  "http://LICENSINGSERVICE";

     @RequestMapping( "/getById")
     public Emp getById(Long id) {
        MultiValueMap paramMap =  new LinkedMultiValueMap();
        paramMap.add( "id", id);
         return restTemplate.postForObject(SERVICE_URL_PREFIX +  "/test/getById", paramMap, Emp .class);
    }
}

测试结果:

  • 第一次:
SpringCloud 三种服务调用方式,你知道几种?_第4张图片
  • 第二次:
SpringCloud 三种服务调用方式,你知道几种?_第5张图片
  • 第三次:

SpringCloud 三种服务调用方式,你知道几种?_第6张图片因为采用轮询负载均衡方式分别调用不同服务实例,未区别,将name做出了一定更改。

以上两种方式对比,Ribbon方式是对第一种方式的封装且内置不同的负载算法,支持自定义。使用更加简单,但此两次均需编写RestTemplate的请求方法,较为繁琐且容易出错,第三种方式Feign客户端则极大的降低了开发难度和提升速度。

3.feign客户端方式

引入依赖:


     org.springframework.cloud
     spring-cloud-starter-feign

主要代码:

@FeignClient(value =  "LICENSINGSERVICE",fallbackFactory = ServiceImp .class)
public interface ServiceInterface {

   @RequestMapping( "/test/getById")
   Emp getById(@RequestParam("id") Long id);

   @RequestMapping( "/test/getLicenseById")
   License getLicenseById(@RequestParam("id") Long id);

   @RequestMapping( "/test/getAllEmp")
   List getAllLicense();
}
@Component
public  class ServiceImp implements FallbackFactory {

     @Override
     public ServiceInterface create(Throwable throwable) {
         return  new ServiceInterface() {
             @Override
             public Emp getById(Long id) {
                Emp emp =  new Emp();
                emp.setName( "i am feign fallback create");
                 return emp;
            }

             @Override
             public License getLicenseById(Long id) {
                 return  null;
            }

             @Override
             public List getAllLicense() {
                 return  null;
            }
        };
    }
}

采用接口模式开发,通过注解指明服务名以及后备方法,在服务表现不佳时,方便返回默认的结果,而不是一个不友好的错误。

主启动类:

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

测试类:

@RestController
@RequestMapping( "rest")
public  class ConsumerRestController {
   @Autowired
   private ServiceInterface serviceInterface;

   @Autowired
   private RestTemplate restTemplate;
   @RequestMapping( "/getById")
   public Emp getById(Long id) {
     return serviceInterface.getById(id);
  }
}

测试结果:

  • 正常测试:
SpringCloud 三种服务调用方式,你知道几种?_第7张图片
  • 关闭两个服务实例,模拟服务实例死亡:

SpringCloud 三种服务调用方式,你知道几种?_第8张图片Feign除了能简化服务调用,也可以实现当调用的服务失败时,友好的反馈信息。

此三种调用方式,由低至上,从不同层次实现了SpringCloud中的微服务互相调用。

你可能感兴趣的:(java-ee,java,架构,后端,c4java)