乐趣区

关于网关:微服务项目服务管理混乱来看这一篇生产者消费者服务实践使用API网关实现服务聚合

API 网关的服务聚合

  • 通过同一个入口路由到不同的服务上

    服务聚合实现

  • 因为服务器在集群部署的时候, 同一个服务内容存在多个不同的服务 IP 地址, 所以不能间接通过 IP 地址拜访服务
  • API 服务拜访的时候要先获取服务的 IP 地址, 而后再拜访服务
  • 进行服务聚合的我的项目要称为服务提供者 (实现服务接口), 服务提供者的 SpringApplication 要加 Main.main(args) 提供近程调用接口给 API 网关
  • 此时能够获取到服务的 IP 地址
  • 如何获取服务 IP 地址?

    上下文信息:
    上下文中寄存的是以后调用过程中所需的环境信息, 所有配置信息都将转换为 URL 的参数.
    RpcContext 是一个 ThreadLocal 的长期状态记录器, 当接管到 RPC 申请, 或发动 RPC 申请时,RpcContext 的状态都会变动.
    比方:A 调 B,B 再调 C, 则 B 机器上, 在 B 调 C 之前,RpcContext 记录的是 A 调 B 的信息, 在 B 调 C 之后,RpcContext 记录的是 B 调 C 的信息
    
    服务生产方:
    ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    // 近程调用
    xxxService.xxx();
    // 本端是否为生产端,这里会返回 true
    boolean isConsumerSide = RpcContext.getContext().isConsumerSide();
    // 获取最初一次调用的提供方 IP 地址
    String serverIP = RpcContext.getContext().getRemoteHost();
    // 获取以后服务配置信息,所有配置信息都将转换为 URL 的参数
    String application = RpcContext.getContext().getUrl().getParameter("application");
    // 留神:每发动 RPC 调用,上下文状态会变动
    yyyService.yyy();
    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    服务提供方:
    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    public class XxxServiceImpl implements XxxService {public void xxx() {
          // 本端是否为提供端,这里会返回 true
          boolean isProviderSide = RpcContext.getContext().isProviderSide();
          // 获取调用方 IP 地址
          String clientIP = RpcContext.getContext().getRemoteHost();
          // 获取以后服务配置信息,所有配置信息都将转换为 URL 的参数
          String application = RpcContext.getContext().getUrl().getParameter("application");
          // 留神:每发动 RPC 调用,上下文状态会变动
          yyyService.yyy();
          // 此时本端变成生产端,这里会返回 false
          boolean isProviderSide = RpcContext.getContext().isProviderSide();
      } 
    }
    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  • 在配置文件的 service 中配置上须要聚合的服务以及版本
  • 创立路由 controller

    @Controller
    public class RouterController{@Value(value=${services.ports.user})
      private String userPort;
    
      @Value(value=${services.ports.content})
      private String contentPort;
      
      @Reference
      private UserConsumerService userConsumerService;
    
      @Reference
      private ContentConsumerService contentConsumerService;
    
      @RequestMapping(value="user",method=RequestMethod.GET)
      public String user(String path){userConsumerService.info();
          return getRequest(userPort,path);
      }
    
      @RequestMapping(value="content",method=RequestMethod.GET)
      public String content(String path){contentConsumerService.info();
          return getRequest(contentPort,path);
      }
      
      public String getRouter(String serverPort,String path){
          // 判断是否为消费者
          boolean isConsumerSide=RpcContext.getContext().isConsumerSide();
          if(isConsumerSide){
              // 获取最初一次调用的提供方的 IP 地址
              String serverIP=RpcContext.getContext().getRemoteHost()
              return String.format("redirect:http://%s:%s%s",serverIP,serverPort,path);
          }
          return null;
      }
    }
退出移动版