Spring Cloud — 服务消费

前言

      题目本想写服务消费者,可是又怕太强调消费者三个字,因为在Eureka中服务消费者同样也可以作为服务生产者来提供服务,所以这里只写了服务消费。Eureka的服务消费有两种方式,一种是rest+ribbon的方式,另一种是Feign的方式。

Rest+Ribbon

      像上一篇博客所讲,创建一个Spring Boot项目,添加Ribbon的引用;如果是Spring Boot1.0,则添加Ribbon引用为:

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>

如果使用的Spring Boot2.0,Ribbon引用的id不同,添加Ribbon引用为:

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

在application.properties文件中添加配置:

server.port=8765
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
spring.application.name=consumer-ribbon

在启动类上添加注解@EnableEurekaClient,实现向Eureka Server的注册,并用Bean的方式注入RestTemplate,如下所示:

@SpringBootApplication
@EnableDiscoveryClient
@RestController
public class ConsumerRibbonApplication {

	public static void main(String[] args) {
		SpringApplication.run(ConsumerRibbonApplication.class, args);
	}

	@Bean
	@LoadBalanced
	RestTemplate restTemplate(){
		return new RestTemplate();
	}

	@Autowired
	private HelloService helloService;

	@GetMapping(value = "/ribbon/sayHello")
	public String hello(String name){
		return helloService.hiService(name);
	}
}

      这里没有创建Controller层,直接将启动类注解为Controller,具体的业务逻辑放在Service的实现中。Service所做的,就是根据要调用的服务地址调用生产者的服务:

@Service
public class HelloServiceImpl implements HelloService{

    @Autowired
    RestTemplate restTemplate;

    @Override
    public String hiService(String name) {
        return restTemplate.getForObject("http://EUREKA-PRODUCER-HELLO/hello?name="+name,String.class);
    }
}

      如上述代码所示,Eureka在调用生产者服务时,只需要使用服务名称即可,Ribbon会根据注册该服务名的机器进行负载均衡。我所注册的EUREKA-PRODUCER-HELLO名称的机器有两台,用port来区分,在调用时打印机器的端口号。启动consumer-ribbon时,访问多次即可看到输出的端口号的变化,即代表是多个服务生产者提供服务的。

Ribbon是客户端负载,已经默认实现了以下所示的配置Bean:

Bean Type Bean Name Class Name

IClientConfig

ribbonClientConfig

DefaultClientConfigImpl

IRule

ribbonRule

ZoneAvoidanceRule

IPing

ribbonPing

DummyPing

ServerList<Server>

ribbonServerList

ConfigurationBasedServerList

ServerListFilter<Server>

ribbonServerListFilter

ZonePreferenceServerListFilter

ILoadBalancer

ribbonLoadBalancer

ZoneAwareLoadBalancer

ServerListUpdater

ribbonServerListUpdater

PollingServerListUpdater

Feign

      利用这种方式调用,同样按上一篇博客介绍创建Spring Boot项目,然后添加Feign的依赖,同样Spring Boot1.0和Spring Boot2.0的引用方式不同,下面是2.0的引用:

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

      同样的在启动类上添加注解@EnableEurekaClient以注册到Eureka Server上,并添加@EnableFeignClients的注解,代表使用Feign的方式调用服务生产者,如下所示:

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
@RestController
public class ConsumerFeignApplication {

	public static void main(String[] args) {
		SpringApplication.run(ConsumerFeignApplication.class, args);
	}

	@Autowired
	private HelloServiceFeignClient helloServiceFeignClient;


	@GetMapping(value = "/feign/sayHello")
	public String sayHello(@RequestParam("name") String name){
		return helloServiceFeignClient.sayHello(name);
	}
}

上面代码中的HelloServiceFeignClient是一个接口,用来调用其他服务,以类似于Restful的风格来调用:

@FeignClient(value = "EUREKA-PRODUCER-HELLO")
@Component
public interface HelloServiceFeignClient {

    /**
     * 打招呼
     * @param name
     * @return
     */
    @GetMapping(value = "/hello")
    String sayHello(@RequestParam("name") String name);
}

      @FeignClient注解中的value代表要访问的服务名称,下面方法中的url代表访问服务的url,@GetMapping的注解也可使用@RequestMapping(method = RequestMethod.GET)注解代替,post调用方式也一样。对于参数来说,@RequestParam中的value要和服务方的参数名称对应,如果传入多个参数,可以使用@RequestBody注解实体来实现。

      FeignClient默认继承了Ribbon,所以这种调用方式的负载均衡也是Ribbon实现的。另外,如果一个服务中要调用多个服务时,课创建多个interface类,只要将@FeignClient的value改成相应的服务名即可,这样注入不同的interface即可调用不同服务中的方法。

后语

      个人认为FeignClient的方式还是比较好用,习惯了Restful的调用方式,感觉FeignClient的方式很顺眼也很方便,而且合作开发时代码风格也比较统一。如果服务提供方提供了jar包就更好了,连interface都不用写了,直接使用对方的jar包来调用Eureka服务,而且还可以使用对方的返回实体,自己动手的地方简直太少了。只不过这样的话,自己的服务还是要注册到EurekaServer上才行,因为毕竟还是通过FeignClient的方式调用。

猜你喜欢

转载自blog.csdn.net/u013038861/article/details/80040381