美文网首页
spring cloud 10 feign

spring cloud 10 feign

作者: 西西_20f6 | 来源:发表于2019-04-11 20:49 被阅读0次

    一、服务调用
    服务调用和消息一般是两个维度,
    1,服务调用是同步的
    2,消息是异步的回调,事件的一个周期

    二、准备
    • 远程过程调用(RPC)

    • 接口定义语言(IDL)
    interface definition language

    • 通讯协议(Protocol)
    HTTP,web-socket,Socket

    • Netflix Feign
    契约式编程
    springcloud将Feign和spring mvc整合

    • Spring Cloud 技术回顾 (服务短路 、负载均衡、服务发现、分布式配置等)

    image.png

    三、
    1,NOSQL:redis,elasticsearch,mongodb
    2,integration:rabbitmq,kafka,
    3,config:config client/config server/zookeeper config/consul config
    4,discovery:eureka server,eureka discovery,zookeeper discovery,consul discovery
    5,routing:zuul,gateway,ribbon,feign
    6,circuit breaker:hystrix,turbine

    四、核心概念
    1,远程过程调用(RPC)
    remote procedure call,通过网络进行传输。
    一个计算机通信协议。该协议允许运行于一台计算机的程序调用另一台计算机的子程序(进程),而程序员无需额外地为这个交互作用编程。如果涉及的软件采用面向对象编程,那么远程过程调用亦可称作远程调用或远程方法调用。
    • 例如
    • Java RMI(二进制协议)进程之间的协议,必须用POJO(序列化&反序列化)
    • WebServices(文本协议)一般都有骨架或者说是结构,比如XML schema

    2,消息传递
    RPC 是一种请求-响应协议,一次 RPC在客户端初始化,再由客户端将请求消息传递到远程的服务器,执行指定的带有参数(这里的参数和方法的参数有所区别。这里的参数也有可能是请求头之类的信息)的过程。经过远程服务器执行过程后,将结果作为响应内容(响应头和响应体)返回到客户端。

    3,存根(Stub)
    在一次分布式计算 RPC 中,客户端和服务器转化参数(不仅仅是方法的参数)的一段代码。 由于存根的参数转化,RPC执行过程如同本地执行函数调用。存根必须在客户端和服务器两端均装载,并且保持兼容(比如高版本的服务端兼容低版本的客户端调用)。

    HTTP调用的存根在于内部的实现。web服务器和客户端都支持HTTP协议的话,那么协议的内容和格式就是存根。
    如果是java rmi(remote method invoke)的话,两边都必须要有接口,传输的模型对象必须序列化,类的版本要保持一致,pojo的字段也要兼容。
    java 序列化主要关注POJO字段的状态,对pojo的方法不是很关注。

    五、spring cloud feign
    • 依赖
    • org.springframework.cloud:spring-cloud-starter-feign
    • 激活
    • @EnableFeignClients (标记在服务调用方的SpringApplication上)
    • 申明
    • @FeignClient 标记在接口Api上,name="服务提供方的service id"

    申明@FeignClient API,name属性尽量使用占位符,避免硬编码。

    package com.xixi.spring.cloud8.server.api;
    
    import com.xixi.spring.cloud8.server.domain.User;
    import org.springframework.cloud.netflix.feign.FeignClient;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import java.util.List;
    
    /**
     * 用户服务
     * 声明Feign客户端,feigncliet里面的方法将会映射到rest api
     * ${user-service-name}指向user-service-provider
     */
    @FeignClient(name = "${user-service-name}")//利用占位符,避免未来整合硬编码
    public interface UserService {
    
        /**
         * 保存用户
         * @param user
         * @return
         */
        @PostMapping("/user/save")
        boolean saveUser(@RequestBody User user);
    
    
        /**
         * 查询所有的用户列表
         * @return
         */
        @GetMapping("/user/list")
        List<User> findAll();
    }
    
    

    在user-service-client客户端激活@EnableFeignClients,放在服务调用方上,申明要激活的接口。在这里是UserService.class

    @EnableFeignClients(clients = {UserService.class})
    public class UserServiceClientApplication{}
    

    六、默认组件
    • Decoder/Encoder : ResponseEntityDecoder / SpringEncoder
    • Logger : Slf4jLogger
    • Contract : SpringMvcContract
    原生的feign并不支持我们spring mvc的annotation(@RequestMapping),但是和spring结合以后就支持了,靠SpringMvcContract
    如果想自己扩展,可以实现Contract,Contract的作用就是Define what annotations and values are valid on interfaces.
    • Feign.Builder : HystrixFeign.Builder
    • Client : LoadBalancerFeignClient( Ribbon 激活的话)

    feign的底层还是ribbon LoadBalancerClient那一套,

    七、• 整合负载均衡: Netflix Ribbon

    1,user-service-client的配置文件application.properties

    ###ribbon 客户端应用
    spring.application.name = user-ribbon-client
    
    eureka.client.enabled = false
    ##服务提供方名称
    provider.service.name = user-service-provider
    ##服务提供方主机
    provider.service.host = localhost
    ###服务提供方端口
    provider.service.port = 8081
    server.port = 8080
    
    
    ##关闭eureka注册,通过显示地配置服务端的地址
    ##定义服务提供方地址,为RibbonLoadBalancerClient提供服务列表,如果有多个可以用逗号隔开。
    user-service-provider.ribbon.listOfServers = \
      http://${provider.service.host}:${provider.service.port}
    
    ##配置自定义实现的MyPing,这样就不用@Bean去配置IPing,
    # user-service-provider是要被负载均衡的服务
    user-service-provider.ribbon.NFLoadBalancerPingClassName=\
      com.xixi.spring.cloud8.server.user.ribbon.client.ping.MyPing
    
    ###配置@FeignClient(name = "${user.service.name}")中的占位符
    #user.service.name需要制定user service接口的提供方,也就是user-service-provider
    user.service.name = ${provider.service.name}
    

    2,服务调用方激活@EnableFeignClients,使用user-service调用服务
    在UserRibbonController中注入userServiceFeignClient

      /**
       * 同一个接口不建议在客户端和服务端之间共享,实际情况最好使用组合UserService的方式
       * FeignClient标记的接口可以直接注入,Feign会动态代理帮我们去构造它的实现类
       */
      @Autowired
      private UserService userServiceFeignClient;
    
      @GetMapping("/user/list")
      public List<User> getUserList2() {
    
        return userServiceFeignClient.findAll();
      }
    
    

    3,服务端实现user-service API,暴露Rest接口
    首先,

    @Service("inMemoryUserService")
    public class InMemoryUserService implements UserService
    

    其次,
    user-service-provider是最终的服务提供方,不需要标记为feignClient
    UserServiceProviderController implements UserService
    UserServiceProviderController实现feignclient接口。

    最后,

      //由于UserServiceProviderController继承了UserService,所以这块可以不写@PostMapping("/user/save")。Feign Inheritance Support
      //注意:@PostMapping会被继承,但是@RequestBody,@RequestParam是不会被继承的,method parameter mapping is not inherited
      //这是因为java语言的特性决定的,方法外面的东西可以从父类继承,但是方法里面的实现,子类会覆盖父类。
      //URL映射可以从父类继承。PostMapping("/user/save")
      @Override
      public boolean saveUser(@RequestBody User user) {
        return userService.saveUser(user);
      }
    
    

    八、• 整合服务短路: Netflix Hystrix
    1,调整UserService api

    package com.xixi.spring.cloud10.server.api;
    
    import com.xixi.spring.cloud10.server.domain.User;
    
    import com.xixi.spring.cloud10.server.fallback.UserServiceFallback;
    import java.util.List;
    import org.springframework.cloud.netflix.feign.FeignClient;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestBody;
    
    /**被标记为@FeignClient的接口,将会伪装UserService的客户端去调用它要调用的服务
     * 用户服务
     * 声明Feign客户端,feign client里面的方法将会映射到rest api
     * ${user-service-name}指向user-service-provider
     *
     * 整合Hystrix Fallback
     */
    @FeignClient(name = "${user.service.name}",//利用占位符,避免未来整合硬编码
        primary = true,//primary = true表示当UserService有多个实现类的时候,FeignClient动态代理的那个实现类优先级最高
        fallback = UserServiceFallback.class )
    public interface UserService {
    
        /**
         * 保存用户
         * @param user
         * @return
         */
        @PostMapping("/user/save")
        boolean saveUser(@RequestBody User user);
    
    
        /**
         * 查询所有的用户列表
         * @return
         */
        @GetMapping("/user/list")
        List<User> findAll();
    }
    
    
    

    写一个UserServiceFallback

    package com.xixi.spring.cloud10.server.fallback;
    
    import com.xixi.spring.cloud10.server.api.UserService;
    import com.xixi.spring.cloud10.server.domain.User;
    import java.util.Collections;
    import java.util.List;
    
    public class UserServiceFallback implements UserService {
    
      @Override
      public boolean saveUser(User user) {
        return false;
      }
    
      @Override
      public List<User> findAll() {
        return Collections.emptyList();
      }
    }
    
    

    2,在user-service-provider上整合@HystrixCommand

      @HystrixCommand(commandProperties = {
          //设置超时时间为100ms
          @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "100")
      },
          //通过@HystrixCommand#fallbackMethod()实现异常处理,设置fallback方法,会在当前类或是他的父类里面去找fallbackForGetUsers()
          fallbackMethod = "fallbackForGetUsers")
      public List<User> findAll() {
        return userService.findAll();
      }
    

    九、• 整合服务发现: Netflix Eureka
    (废弃ribbon白名单配置的方式,使用eureka获取服务列表)
    1,写一个eureka-server
    (1)引入eureka-server jar
    (2)写引导类
    (3)配置文件application.properties
    2,user-service-client增加服务发现配置
    (1)加依赖

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

    (2)引导类激活服务发现@EnableDiscoveryClient
    (3)application.properties,注意要注释掉之前白名单的配置

    eureka.client.enabled = true
    ###连接eureka server
    eureka.server.hostname = localhost
    eureka.server.port = 8083
    eureka.client.serviceUrl.defaultZone = \
      http://${eureka.server.hostname}:${eureka.server.port}/eureka
    

    3,user-service-provider增加服务发现配置
    (1)加依赖
    (2)引导类加注解@EnableDiscoveryClient
    (3)application.properties

    十、• 整合配置服务器: Config Server
    (1)加依赖

        s<dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-config-server</artifactId>
        </dependency>
    

    (2)引导类加注解@EnableDiscoveryClient,@SpringBootApplication,@EnableConfigServer
    (3)application.properties

    1,配置user-service.properties

    ###user-service-client配置内容,作为user-service-client配置内容的一部分,
    # user-service-client本身也会有自己的application.properties
    ##如果有冲突,user-service的配置内容优先
    ##服务提供方名称
    provider.service.name = user-service-provider
    ##服务提供方主机
    #provider.service.host = localhost
    ####服务提供方端口
    #provider.service.port = 8081
    
    ###配置@FeignClient(name = "${user.service.name}")中的占位符
    #user.service.name需要制定user service接口的提供方,也就是user-service-provider
    user.service.name = ${provider.service.name}
    

    2,

    3,

    十一、• 整合配置客户端: Config Client

    相关文章

      网友评论

          本文标题:spring cloud 10 feign

          本文链接:https://www.haomeiwen.com/subject/rlkoiqtx.html