前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring Cloud开发人员如何解决服务冲突和实例乱窜?(IP实现方案)

Spring Cloud开发人员如何解决服务冲突和实例乱窜?(IP实现方案)

作者头像
陶陶技术笔记
发布2020-06-02 16:23:22
5680
发布2020-06-02 16:23:22
举报
文章被收录于专栏:陶陶技术笔记陶陶技术笔记

一、背景

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

二、可行性分析

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

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

  • 开发人员本机IP - 其实就是客户端IP,也就是原始请求方的IP:172.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里面一直传递下去就可以了

代码语言:javascript
复制
/**
 * 获取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里面传递给下游服务

代码语言:javascript
复制
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
String sourceIp = getIpAddr(request);
ctx.getZuulRequestHeaders().put("HTTP_X_FORWARDED_FOR", sourceIp);

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

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

代码语言:javascript
复制
String localIp = InetAddress.getLocalHost().getHostAddress()

六、总结

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

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

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

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-09-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 陶陶技术笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、背景
  • 二、可行性分析
  • 三、路由规则逻辑
  • 四、获取原始请求方的IP
  • 五、获取服务器所在机器的IP
  • 六、总结
相关产品与服务
负载均衡
负载均衡(Cloud Load Balancer,CLB)提供安全快捷的流量分发服务,访问流量经由 CLB 可以自动分配到云中的多台后端服务器上,扩展系统的服务能力并消除单点故障。负载均衡支持亿级连接和千万级并发,可轻松应对大流量访问,满足业务需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档