SpringCloud之微服务调用OpenFeign

工程搭建

首先我们需要先创建以下模块

  • common-pojo:存放项目的pojo类。

  • common-dao:存放与数据库相关的持久层代码和配置文件,比如mybatis的mapper接口和文件。

  • eureka-server:用来启动注册中心,具体请看 注册中心。

  • customer-provider:用来提供服务,注册服务。

  • customer-consumer:用来调用服务,处理业务。

上面pojo和mapper具体操作代码就不写了,就是简单的增删改查,可以通过mybatis逆向工程生成代码。

在 common-dao 中依赖mybatis的起步依赖,pom文件如下所示:

    <dependencies>
        
        <dependency>
            <groupId>com.lbbgroupId>
            <artifactId>common-pojoartifactId>
            <version>1.0-SNAPSHOTversion>
            <scope>compilescope>
        dependency>
        
        <dependency>
            <groupId>org.mybatis.spring.bootgroupId>
            <artifactId>mybatis-spring-boot-starterartifactId>
            <version>2.1.1version>
        dependency>
        
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
        dependency>
        
        <dependency>
            <groupId>com.github.pagehelpergroupId>
            <artifactId>pagehelperartifactId>
            <version>5.1.11version>
        dependency>
    dependencies>

发布服务

customer-provider,作为服务端工程 服务端需要发布服务,并且将服务注册到Eureka,所以服务端需要添加Eureka的客户端依赖

    <dependencies>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
            <groupId>com.lbbgroupId>
            <artifactId>common-daoartifactId>
            <version>1.0-SNAPSHOTversion>
            <scope>compilescope>
        dependency>
        
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
        dependency>
    dependencies>

编写Controller

这部分内容没有任何特殊 的地方,按照之前的写法正常编写即可。我 们可以实现一个根据客户id查询客户信息的方法:

@RestController
public class MyController {
     
    @Autowired
    private CrmCustomerMapper customerMapper;

    @RequestMapping("custInfo/{id}")
    //CrmResult是封装类,封装类一些数据以及状态码,信息
    public CrmResult getCustomer(@PathVariable Integer id){
       
        return CrmResult.ok(customerMapper.selectByPrimaryKey(id.longValue()));
    }
}

配置文件application.yml

#spring.application.name 在配置文件中我们配置了应用程序的名称,这个名称很重 要,不能重复。将来调用服务时是使用此名称来调用服务的。 
spring:
  application:
    name: customer-service
#数据库信息
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql:///crm?characterEncoding=utf8&useSSL=false&nullCatalogMeansCurrent=true&serverTimezone=UTC
    driver-class-name: com.mysql.cj.jdbc.Driver
  #设置编码问题
  http:
    encoding:
      force: true
      charset: UTF-8
#eureka
eureka:
  client:
    # eureka.client.service-url.defaultZone 属性配置了注册中心的位置
    service-url:
      defaultZone: http://localhost:8000/eureka
  #下面两个 默认就是true,可以不写
  # register-with-eureka: true
  # fetch-registry: true
#端口号
server:
  port: 9000  

启动项

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
//注册到Eureka
@EnableEurekaClient
@MapperScan(basePackages = "com.lbb.crm.dao")
public class ProviderRunner {
     
    public static void main(String[] args) {
     
        SpringApplication.run(ProviderRunner.class,args);
    }
}

先启动eureka,再启动服务提供方就可以注册服务成功。

调用服务

依赖pom

customer-consumer,模块作为消费端工程 消费端也需要连接到Eureka来查询服务信息,所以也需要添加Eureka的客户端依赖,并且消费端 需要调用服务端的服务,所以还需要添加feign的依赖:

    <dependencies>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
            <groupId>com.lbbgroupId>
            <artifactId>common-daoartifactId>
            <version>1.0-SNAPSHOTversion>
            <scope>compilescope>
        dependency>
        
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
        dependency>
        
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-openfeignartifactId>
        dependency>
    dependencies>

配置文件

#spring.application.name 在配置文件中我们配置了应用程序的名称,这个名称很重 要,不能重复。将来调用服务时是使用此名称来调用服务的。
spring:
  application:
    name: customer-service
  #设置编码问题
  http:
    encoding:
      force: true
      charset: UTF-8
#eureka
eureka:
  client:
    # eureka.client.service-url.defaultZone 属性配置了注册中心的位置
    service-url:
      defaultZone: http://localhost:8000/eureka
#指定启动端口
server:
  port: 8787

引导类

@SpringBootApplication(exclude= {
     DataSourceAutoConfiguration.class})
@EnableFeignClients     //启用feign进行远程调用
@EnableDiscoveryClient //启用服务注册与发现
public class ConsummerRunner {
     
    public static void main(String[] args) {
     
        SpringApplication.run(ConsummerRunner.class,args);
    }
}

在引导类中需要增加 @EnableDiscoveryClient 注解,需要启动服务注册与发现功能。发 现服务后还需要使用Feign来调用工程,所以需要增加 @EnableFeignClients 注解。

创建Feign代理对象

Feign是一个声明式Web Service客户端。使用Feign能让编写Web Service客户端更加简单, 它的使 用方法是定义一个接口,然后在上面添加注解,同时也支持JAX-RS标准的注解。Feign也支持可拔 插式的编码器和解码器。Spring Cloud对Feign进行了封装,使其支持了Spring MVC标准注解和HttpMessageConverters。Feign可以与Eureka和Ribbon组合使用以支持负载均衡。

@FeignClient(name = "CUSTOMER-SERVICE")
public interface MyService {
     
    //接口要与服务提供方一致
    @RequestMapping("custInfo/{id}")
    CrmResult getCrm(@PathVariable Integer id);
}

注意:

  • @FeignClient 代表我们要创建一个服务端的代理对象,其中 name 属性代表服务端spring.application.name 属性,并且不能包含下划线。

  • 接口中只需要对应服务端发布的服务定义方法即可。

  • 需要注意的是 @PathVariable 注解中必须指定参数名称。否则会报错

调用服务

@RestController
public class MyConSumer {
     
    //在controller中需要调用Feign代理对象的方法来调用服务,只需要将对象注入即可。
    @Autowired
    private MyService service;

    @RequestMapping("get/{id}")
    public CrmResult getCrm(@PathVariable Integer id){
     
        return service.getCrm(id);
    }
}

此时先启动服务注册中心,在启动服务方,最后启动消费方即可。

负载均衡

Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现。通 过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服 务调用。在Feign中已经集成了Ribbon,我们同时开启多个服务端,会自动实现负载均衡。

在 customer-provider 中修改 server.port 属性,以此配置文件再次启动一个实例,此时就有两个实例同时提供服务

#spring.application.name 在配置文件中我们配置了应用程序的名称,这个名称很重 要,不能重复。将来调用服务时是使用此名称来调用服务的。
spring:
  application:
    name: customer-service
#数据库信息
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql:///crm?characterEncoding=utf8&useSSL=false&nullCatalogMeansCurrent=true&serverTimezone=UTC
    driver-class-name: com.mysql.cj.jdbc.Driver
  #设置编码问题
  http:
    encoding:
      force: true
      charset: UTF-8
#eureka
eureka:
  client:
    # eureka.client.service-url.defaultZone 属性配置了注册中心的位置
    service-url:
      defaultZone: http://localhost:8000/eureka
  #下面两个 默认就是true,可以不写
  # register-with-eureka: true
  # fetch-registry: true
server:
  port: 9001

以从 Eureka中看到如下信息:

SpringCloud之微服务调用OpenFeign_第1张图片
客户调用时,两个服务就会实现负载均衡,默认是轮询的策略。下面是eureka负载均衡策略:

策略名 命名 策略描述
RandomRule 随机策略 随机选择一个server
RoundRobinRule 轮询策略 按顺序选中server (默认
RetryRule 重试策略 在一个配置时间段内,当选择server不成功,则一直尝试选择一个可用的server
BestAvailableRule 最低并发策略 逐个考察Server,如果Server断路器打开,则忽略,再选择其中并发链接最低的server
AvailabilityFilteringRule 可用过滤策略 过滤掉那些因为一直连接失败的,被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值)
ResponseTimeWeightedRule 响应时间加权策略 根据响应时间分配一个weight,响应时间越长,weight越小,被选中的可能性越低。响应时间越短,weight越大,被选中的可能性越高。这策略很贴切,综合了各种因素,比如:网络、磁盘、io等,都直接影响响应时间
ZoneAvoidanceRule 区域权重策略 综合判断server所在区域的综合性能,和server的可用性,轮询选中server,并且判断一个AWS Zone的运行性能是否可用,剔除不可用Zone中的所有server

客户端可以配置负载均衡的策略:

customer-service: 
	ribbon: 
		NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

customer-service 表示作用到哪个微服务, com.netflix.loadbalancer.RandomRule 即随机策略,当然,我们也可以指定为其他策略,包括我们自己定义的,只要把相应的包路径写到这即可,很方便。

链接:SpringCloud之熔断器及集中配置组件

你可能感兴趣的:(springcloud,SpringCloud)