在我上一篇文章《 Spring Cloud开发人员如何解决服务冲突和实例乱窜? 》中提到使用服务的 元数据
来实现隔离和路由,有朋友问到能不能直接通过 IP
来实现?本文就和大家一起来讨论一下这个问题
要实现通过 IP
来隔离和路由的话有一个非常关键的点需要解决,就是怎样实现 IP可辨识 ,意思就是如何区分那个 IP
是 服务器 上的,那个 IP
是 开发人员本机 的
如上图所示其实我们还是能找到规律可以辨识的, 所以这个是可以行的!
客户端IP
,也就是 原始请求方的IP : 172.16.20.2 主要实现以下目标:
服务器上的实例
开发A本机启动的实例
,如果没有则调用 服务器上的实例
开发B本机启动的实例
,如果没有则调用 服务器上的实例
在找到 IP
的辨识规律后,推导出下面3个 路由规则 来实现上面的目标
原始请求方的IP 上游服务所在机器IP
具体的自定义负载均衡的对象怎么写我这里就不详细描述了,可以参考我上一篇文章《 Spring Cloud开发人员如何解决服务冲突和实例乱窜? 》
获取 原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添加到header的 HTTP_X_FORWARDED_FOR
里面传递给下游服务
RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); String sourceIp = getIpAddr(request); ctx.getZuulRequestHeaders().put("HTTP_X_FORWARDED_FOR", sourceIp);
直接使用JDK自带的 InetAddress
就可以了
String localIp = InetAddress.getLocalHost().getHostAddress()
通过 IP
的方案来实现 开发环境 服务实例隔离和策略路由后,可以实现到 开发完全无感知
,既不需要配置 元数据
,也不需要自己去传 version
之类的参数了。
但是这个方案其实也是有 局限性 的
IP
上就失去了辨识能力了 原IP
前端开发人员A
启动的客户端,去调试 后台开发人员B
启动的服务就不行了,因为 原IP
与注册上去的 服务实例IP
匹配不上 最后可能大家会问 原IP
怎样全链路传递下去?链路传递可以参考一下我的另外一篇文章《 日志排查问题困难?分布式日志链路跟踪来帮你 》