nacos、ribbon和feign(openfeign)的简明教程


相关文章:
【spring cloud 】Ribbon和OpenFeign(代替RestTemplate)
Dubbo 与 Feign 的区别
nacos、ribbon和feign的简明教程

概述

Feign官网

Feign是Spring Cloud组件中的一个轻量级RESTful的HTTP服务客户端,基础语法:

//Feign是个外套,需要指定底层的通信协议,这里是OkHttp
public class Example {
  public static void main(String[] args) {
    GitHub github = Feign.builder()
                     .client(new OkHttpClient())  
                     .target(GitHub.class, "https://api.github.com");
  }
}

起初feign是Netflix 公司下的产品,由于 Netflix 公司不再维护feign,feign由社区维护,feign更名为 openfeign,并且项目迁移到新的仓库(前面官网地址就是openfeign)。后续版本仅使用“io.github.openfeign”,推荐使用该依赖。

Feign内置了Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务。

spring-cloud-openfeign 是基于 openfeign 进行包装,集成了 SpringMVC 的注解等方便SpringBoot项目开发的一个组件。也就是这个时候,你才能使用注解语法 @FeignClient(name = “xxx-member”,path = “/member”)语法

一般使用<artifactId>spring-cloud-starter-openfeign</artifactId>集成

1. nacos简明教程

1.1 为什么需要nacos?

在微服务架构中,微服务之间经常要相互通信和调用,而且一个服务往往存在多个实例来降低负荷或保证高可用。我们假定A服务要调用B服务,最简单的方式把B服务的地址和端口保存在A服务的配置文件中。然后通过http请求去完成B服务的调用。但是B服务可能有好多个实例,而且可能会随着业务的需求随时的扩展或者停用掉一些实例,这个时候B服务的地址和端口可能会经常发生改变。如果记录在配置文件就多有不便。而且在众多的B服务中,可能有一些服务会出现各种问题坏掉,我们可能还需要写一个心跳检测,看看是不是所有的服务都正常运行,及时地剔除掉那些不能用的服务。如果完备稳定的实现这些功能,是一个不小的工作量。还好凡是有困难的地方总有前人造轮子。而Nacos就是来解决这样问题的轮子。

在这里插入图片描述
如图所示,通过简单的配置和注解,所有的微服务都把自己信息登记到Nacos server中去。在需要调用的时候,通过登记到Nacos server的名字就可以完成微服务间的调用。比如有以前通过访问 http://12.3.3.5:8090/service 来访问微服务的,变成了http://provider/service 的方式来访问,把服务与端口地址解耦。

1.2 如何使用Nacos

1.2.1 Nacos server的启动

Nacos使用非常的简单。从Nacos官网下载release包,linux\mac下面执行sh startup.sh -m standalone,windows下面执行startup.cmd -m standalone 然后就可以完成Nacosserver的启动。

1.2.2 在微服务中使用Nacos做服务注册和发现

这里讲的是 Nacos Spring Cloud语法,此外还有原生Nacos、spring 结合Nacos、spring boot 结合nacos

通过maven架包使用Nacos发现服务:

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    <version>2.2.3.RELEASE</version>
</dependency>

在配置文件中简单配置:

spring:
    application:
        name: provider  #这个很重要,是注册到Nacos中调用的服务的名称
    cloud:
        nacos:
        discovery:
            server-addr: 127.0.0.1:8848 #配置Nacos的服务地址

在启动类上增加注解@EnableDiscoveryClient:

@SpringBootApplication
@EnableDiscoveryClient 
public class ProviderApplication {

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

}

@EnableDiscoveryClient 其实可以省略,nacos比较特殊,可以自动发现,和其他的组件稍有不同

通过简单的几步就可以完成了把微服务注册到了Nacos Server。怎么样很简单吧。当然Nacos除了做服务注册和发现外,还可以做配置中心,使用方法大同小异。更多丰富的操作参考官方文档 Nacos官方网站

1.2.3 服务的调用

如果要通过http://provider/service的方式去调用微服务,还需要构造http请求,请求回来的结果还要做json解析等等一系列繁杂的工作。而Ribbon就用来解决这个问题的。

在springcloud.alibaba的nacos发现服务的Maven包中,已经包含了ribbon。我们通过简单的几行代码,就可以完成微服务的调用。
在这里插入图片描述

假定在provider服务中有这么一段代码,我们要调用:

//例子来自Nacos官网
    @RequestMapping(value = "/echo/{string}",method = RequestMethod.GET)
    public String echo(@PathVariable String string)
    {
        return "Hello Nacos Discover" + string;
    }

我们只需要实例化一个RestTemplate:

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

注意必须加上 @LoadBalanced,作用是ribbon和nacos实现协作,实现解析服务名

然后就可以在想要调用的地方来通过下面的代码来非常简单地调用:

String result = restTemplate.getForObject("http://provider/echo/"+str,String.class);

2. 负载均衡的问题

前面讲到,在微服务环境中常常同一个服务会有N多实例,我们不希望所有的调用都跑到一个实例上去,这个时候就需要用到负载均衡。我们只需要在启动来加上 @LoadBalanced 注解。在配置文件的spring.application.name相同的应用会被认为是同一个微服务,然后转发可以通过ribbon内置的策略路由到不同的provider中去。

如果我们期望有的provider的优先级比别的优先级高一些,可以再provider的配置文件中调节不同的权重。

spring:
  cloud:
    nacos:
      discovery:
        weight: 1 #配置权重

2.1 使用Feign

通过上面的方法,已经把微服务之间的相互调用变得非常的简单了。但是还不够,Feign可以让调用更加简单。

引用maven包

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

然后我们针对要调用的provider定义一个接口,接口的方法为要调用的方法名,参数和调用参数同名。@FeignClient 注解中name为微服务的名称。复杂一些的方法调用可能需要在接口中配合@RequestMapping指定具体的路由规则,然后就可以通过该接口直接调用微服务方法,是不是更加清晰简单呢?

@FeignClient(name = "provider")
@Service
public interface TestService {
    String echo(String serviceName);
}
public class TestController {
    private final RestTemplate restTemplate;
    @Autowired
    private TestService testService;

    @GetMapping("/echo2/{str}")
    public String echo2(@PathVariable String str)
    {
        return testService.echo(str);
    }
}

参考

nacos、ribbon和feign的简明教程