一、背景

在我上一篇文章《Spring Cloud开发人员如何解决服务冲突和实例乱窜?》中提到使用服务的元数据来实现隔离和路由,有朋友问到能不能直接通过IP来实现?本文就和大家一起来讨论一下这个问题

 

二、可行性分析

要实现通过IP来隔离和路由的话有一个非常关键的点需要解决,就是怎样实现IP可辨识,意思就是如何区分那个IP服务器上的,那个IP开发人员本机

如上图所示其实我们还是能找到规律可以辨识的,所以这个是可以行的!

  • 开发人员本机IP - 其实就是客户端IP,也就是原始请求方的IP172.16.20.2
  • 服务器IP - 可以理解为服务器上的服务所在机器的IP(有点绕):172.16.20.1

 

三、路由规则逻辑

主要实现以下目标:

  1. 普通用户访问服务器上的页面时,请求的所有路由只调用服务器上的实例
  2. 开发A访问时,请求的所有路由优先调用开发A本机启动的实例,如果没有则调用服务器上的实例
  3. 开发B访问时同上,请求的所有路由优先调用开发B本机启动的实例,如果没有则调用服务器上的实例

在找到IP的辨识规律后,推导出下面3个路由规则来实现上面的目标

  1. 优先匹配原始请求方的IP的服务实例
  2. 再者匹配上游服务所在机器IP的服务实例
  3. 上面2个逻辑都匹配不到的话使用轮询的方式找一个实例

 

具体的自定义负载均衡的对象怎么写我这里就不详细描述了,可以参考我上一篇文章《Spring Cloud开发人员如何解决服务冲突和实例乱窜?

 

四、获取原始请求方的IP

获取原IP的代码片段如下,只需要在网关上增加一个过滤器获取IP,然后添加到header里面一直传递下去就可以了

/**
* 获取Ip地址
*/
private String getIpAddr(HttpServletRequest request){
String ip = request.getHeader("X-Forwarded-For");
if (isEmptyIP(ip)) {
ip = request.getHeader("Proxy-Client-IP");
if (isEmptyIP(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
if (isEmptyIP(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
if (isEmptyIP(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
if (isEmptyIP(ip)) {
ip = request.getRemoteAddr();
if ("127.0.0.1".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip)) {
// 根据网卡取本机配置的IP
try {
ip = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
log.error("InetAddress.getLocalHost()-error", e);
}
}
}
}
}
}
} else if (ip.length() > 15) {
String[] ips = ip.split(",");
for (int index = 0; index < ips.length; index++) {
String strIp = ips[index];
if (!isEmptyIP(ip)) {
ip = strIp;
break;
}
}
}
return ip;
} private boolean isEmptyIP(String ip) {
if (StrUtil.isEmpty(ip) || UNKNOWN_STR.equalsIgnoreCase(ip)) {
return true;
}
return false;
}

把原IP添加到headerHTTP_X_FORWARDED_FOR里面传递给下游服务

RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
String sourceIp = getIpAddr(request);
ctx.getZuulRequestHeaders().put("HTTP_X_FORWARDED_FOR", sourceIp);

 

五、获取服务器所在机器的IP

直接使用JDK自带的InetAddress就可以了

String localIp = InetAddress.getLocalHost().getHostAddress()

 

六、总结

通过IP的方案来实现开发环境服务实例隔离和策略路由后,可以实现到开发完全无感知,既不需要配置元数据,也不需要自己去传version之类的参数了。

但是这个方案其实也是有局限性

  1. 开发服务器必须是只用一台来部署所有的服务,因为如果上游服务和下游服务不在同一个IP上就失去了辨识能力了
  2. 因为网络环境比较复杂,不一定能获取到客户端的真实原IP
  3. 开发人员启动客户端/前端的机器与启动后台服务必须是同一台电脑上才行;例如如果是前端开发人员A启动的客户端,去调试后台开发人员B启动的服务就不行了,因为原IP与注册上去的服务实例IP匹配不上

 

最后可能大家会问原IP怎样全链路传递下去?链路传递可以参考一下我的另外一篇文章《日志排查问题困难?分布式日志链路跟踪来帮你

 

推荐阅读

 

扫码关注有惊喜!

Spring Cloud开发人员如何解决服务冲突和实例乱窜?(IP实现方案)的更多相关文章

  1. Spring Cloud开发人员如何解决服务冲突和实例乱窜?

    一.背景 在我们开发微服务架构系统时,虽然说每个微服务都是孤立的可以单独开发,但实际上并非如此,要调试和测试你的服务不仅需要您的微服务启动和运行,还需要它的上下文服务.依赖的基础服务等都要运行:但如果 ...

  2. Spring Cloud开发实践 - 02 - Eureka服务和接口定义

    服务注册 EurekaServer Eureka服务模块只有三个文件, 分别是pom.xml, application.yml 和 EurekaServerApplication.java, 内容如下 ...

  3. 【译文】用Spring Cloud和Docker搭建微服务平台

    by Kenny Bastani Sunday, July 12, 2015 转自:http://www.kennybastani.com/2015/07/spring-cloud-docker-mi ...

  4. Spring Cloud和Docker搭建微服务平台

    用Spring Cloud和Docker搭建微服务平台 This blog series will introduce you to some of the foundational concepts ...

  5. Spring Cloud官方文档中文版-Spring Cloud Config(上)-服务端(配置中心)

    官方文档地址为:http://cloud.spring.io/spring-cloud-static/Dalston.SR2/#spring-cloud-feign 文中例子我做了一些测试在:http ...

  6. Spring Cloud(一):服务治理技术概览【Finchley 版】

    Spring Cloud(一):服务治理技术概览[Finchley 版]  发表于 2018-04-14 |  更新于 2018-05-07 |  Spring Cloud Netflix 是 Spr ...

  7. 从 Spring Cloud 开始,聊聊微服务架构实践之路

    [编者的话]随着公司业务量的飞速发展,平台面临的挑战已经远远大于业务,需求量不断增加,技术人员数量增加,面临的复杂度也大大增加.在这个背景下,平台的技术架构也完成了从传统的单体应用到微服务化的演进. ...

  8. 【Spring Cloud学习之一】微服务架构

    一.网站架构模式发展 单体应用-->SOA-->微服务 1.分布式项目与项目集群分布式项目:根据业务需求进行拆分成N个子系统,多个子系统相互协作才能完成业务流程子系统之间通讯使用RPC远程 ...

  9. 9.Spring Cloud Config统一管理微服务配置

    Spring Cloud Config统一管理微服务配置 9.1. 为什么要统一管理微服务配置 9.2. Spring Cloud Config简介 Spring Cloud Config为分布式系统 ...

随机推荐

  1. 基于drone构建CI-CD系统

    kubernetes集群三步安装 CI 概述 用一个可描述的配置定义整个工作流 程序员是很懒的动物,所以想各种办法解决重复劳动的问题,如果你的工作流中还在重复一些事,那么可能就得想想如何优化了 持续集 ...

  2. 【iOS】CGContextSaveGState: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable

    CGContextSaveGState: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SH ...

  3. 基于vue2.0搭建项目流程

    搭建vue2.0项目--myproject 一. 环境搭建: 1 打开命令行(cmd) 2 安装node node官网 3 安装 vue-cli步骤如下: npm install -g vue-cli ...

  4. 疯子的算法总结(二) STL Ⅰ 算法 ( algorithm )

    写在前面: 为了能够使后续的代码具有高效简洁的特点,在这里讲一下STL,就不用自己写堆,写队列,但是做为ACMer不用学的很全面,我认为够用就好,我只写我用的比较多的. 什么是STL(STl内容): ...

  5. Ubuntu 磁盘挂载错误

    一.错误 报错原因: 在删除或者复制移动时,磁盘或者u盘等外接硬件设备,忽然掉落(断掉,接口松动),在次挂载磁盘时就会出现错误 错误日志: $MFTMirr does not match $MFT ( ...

  6. 自定义仿 IPhone 开关控件

    极力推荐文章:欢迎收藏 Android 干货分享 阅读五分钟,每日十点,和您一起终身学习,这里是程序员Android 本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以 ...

  7. HelloDjango 系列教程:博客从“裸奔”到“有皮肤”

    文中涉及的示例代码,已同步更新到 HelloGitHub-Team 仓库 在此之前我们已经编写了博客的首页视图,并且配置了 URL 和模板,让 django 能够正确地处理 HTTP 请求并返回合适的 ...

  8. ArrayList 的使用方法【摘要】

    ArrayList 的使用方法 1.什么是ArrayList ArrayList就是传说中的动态数组,用MSDN中的说法,就是Array的复杂版本,它提供了如下一些好处: (1)动态的增加和减少元素 ...

  9. k8s+istio:流量控制之灰度发布

    通过Kubernetes+Istio的流量控制实现灰度发布,主要演示通过流量权重实现蓝绿,通过http自定义头实现金丝雀 准备环境 k8s和istio不想自己装的话可以在云上买个按量付费集群,用完即删 ...

  10. IBM实习工作(一)

    2019.1.21 今天的任务是完成会计是否在岗配置表格增加操作记录,任务描述:1.  [会计是否在岗配置] 查询结果界面: 修改人编码/修改人/修改时间 字段:2.      字段取值为[会计是否在 ...