Spring Cloud开发人员如何解决服务冲突和实例乱窜?(IP实现方案)
一、背景
在我上一篇文章《Spring Cloud开发人员如何解决服务冲突和实例乱窜?》中提到使用服务的元数据
来实现隔离和路由,有朋友问到能不能直接通过IP
来实现?本文就和大家一起来讨论一下这个问题
二、可行性分析
要实现通过IP
来隔离和路由的话有一个非常关键的点需要解决,就是怎样实现IP可辨识,意思就是如何区分那个IP
是服务器上的,那个IP
是开发人员本机的
如上图所示其实我们还是能找到规律可以辨识的,所以这个是可以行的!
- 开发人员本机IP - 其实就是
客户端IP
,也就是原始请求方的IP:172.16.20.2 - 服务器IP - 可以理解为服务器上的服务所在机器的IP(有点绕):172.16.20.1
三、路由规则逻辑
主要实现以下目标:
- 普通用户访问服务器上的页面时,请求的所有路由只调用
服务器上的实例
- 开发A访问时,请求的所有路由优先调用
开发A本机启动的实例
,如果没有则调用服务器上的实例
- 开发B访问时同上,请求的所有路由优先调用
开发B本机启动的实例
,如果没有则调用服务器上的实例
在找到IP
的辨识规律后,推导出下面3个路由规则来实现上面的目标
- 优先匹配
原始请求方的IP
的服务实例 - 再者匹配
上游服务所在机器IP
的服务实例 - 上面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添加到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);
五、获取服务器所在机器的IP
直接使用JDK自带的InetAddress
就可以了
String localIp = InetAddress.getLocalHost().getHostAddress()
六、总结
通过IP
的方案来实现开发环境服务实例隔离和策略路由后,可以实现到开发完全无感知
,既不需要配置元数据
,也不需要自己去传version
之类的参数了。
但是这个方案其实也是有局限性的
- 开发服务器必须是只用一台来部署所有的服务,因为如果上游服务和下游服务不在同一个
IP
上就失去了辨识能力了 - 因为网络环境比较复杂,不一定能获取到客户端的真实
原IP
- 开发人员启动客户端/前端的机器与启动后台服务必须是同一台电脑上才行;例如如果是
前端开发人员A
启动的客户端,去调试后台开发人员B
启动的服务就不行了,因为原IP
与注册上去的服务实例IP
匹配不上
最后可能大家会问原IP
怎样全链路传递下去?链路传递可以参考一下我的另外一篇文章《日志排查问题困难?分布式日志链路跟踪来帮你》
推荐阅读
- zuul集成Sentinel最新的网关流控组件
- 阿里注册中心Nacos生产部署方案
- Spring Boot自定义配置项在IDE里面实现自动提示
- Spring Cloud Zuul的动态路由怎样做?集成Nacos实现很简单
扫码关注有惊喜!
Spring Cloud开发人员如何解决服务冲突和实例乱窜?(IP实现方案)的更多相关文章
- Spring Cloud开发人员如何解决服务冲突和实例乱窜?
一.背景 在我们开发微服务架构系统时,虽然说每个微服务都是孤立的可以单独开发,但实际上并非如此,要调试和测试你的服务不仅需要您的微服务启动和运行,还需要它的上下文服务.依赖的基础服务等都要运行:但如果 ...
- Spring Cloud开发实践 - 02 - Eureka服务和接口定义
服务注册 EurekaServer Eureka服务模块只有三个文件, 分别是pom.xml, application.yml 和 EurekaServerApplication.java, 内容如下 ...
- 【译文】用Spring Cloud和Docker搭建微服务平台
by Kenny Bastani Sunday, July 12, 2015 转自:http://www.kennybastani.com/2015/07/spring-cloud-docker-mi ...
- Spring Cloud和Docker搭建微服务平台
用Spring Cloud和Docker搭建微服务平台 This blog series will introduce you to some of the foundational concepts ...
- Spring Cloud官方文档中文版-Spring Cloud Config(上)-服务端(配置中心)
官方文档地址为:http://cloud.spring.io/spring-cloud-static/Dalston.SR2/#spring-cloud-feign 文中例子我做了一些测试在:http ...
- Spring Cloud(一):服务治理技术概览【Finchley 版】
Spring Cloud(一):服务治理技术概览[Finchley 版] 发表于 2018-04-14 | 更新于 2018-05-07 | Spring Cloud Netflix 是 Spr ...
- 从 Spring Cloud 开始,聊聊微服务架构实践之路
[编者的话]随着公司业务量的飞速发展,平台面临的挑战已经远远大于业务,需求量不断增加,技术人员数量增加,面临的复杂度也大大增加.在这个背景下,平台的技术架构也完成了从传统的单体应用到微服务化的演进. ...
- 【Spring Cloud学习之一】微服务架构
一.网站架构模式发展 单体应用-->SOA-->微服务 1.分布式项目与项目集群分布式项目:根据业务需求进行拆分成N个子系统,多个子系统相互协作才能完成业务流程子系统之间通讯使用RPC远程 ...
- 9.Spring Cloud Config统一管理微服务配置
Spring Cloud Config统一管理微服务配置 9.1. 为什么要统一管理微服务配置 9.2. Spring Cloud Config简介 Spring Cloud Config为分布式系统 ...
随机推荐
- handlerAdapter与方法返回值的处理
前提:处理器方法被调用并返回了结果 public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer ma ...
- 使用.csv文件
引用自:https://blog.csdn.net/vision_tung/article/details/79845758 通用爬虫:https://blog.csdn.net/Vision_Tun ...
- android 界面提示框架WisdomProgressHUD,为金典而生
一:简述 今天给android开发者们,推荐一个金典的界面提示框架WisdomProgressHUD,使用简洁方便. WisdomProgressHUD 是一个半透明的 HUD 指示器. Wisdom ...
- 【iOS】duplicate symbols for architecture x86_64
今天遇到了这个问题,错误如下: duplicate symbol _OBJC_IVAR_$_BCViewController.bank in: /Users/***/Library/Developer ...
- 1.Go语言copy函数、sort排序、双向链表、list操作和双向循环链表
1.1.copy函数 通过copy函数可以把一个切片内容复制到另一个切片中 (1)把长切片拷贝到短切片中 package main import "fmt" func main() ...
- Hadoop学习(7)-hive的安装和命令行使用和java操作
Hive的用处,就是把hdfs里的文件建立映射转化成数据库的表 但hive里的sql语句都是转化成了mapruduce来对hdfs里的数据进行处理 ,并不是真正的在数据库里进行了操作. 而那些表的定义 ...
- asp.net core 一个中小型项目实战的起手式——项目搭建与仓储模式下的持久层创建(1)
常规的中小型项目搭建方式一般是三层架构加上mvc与webapi作为一个主要框架,再加上一些第三方库,例如orm框架(EF.SqlSugar.Dapper等),API文档工具(Swagger)这些的应用 ...
- Vue系列:wangEditor富文本编辑器简单例子
考虑到该富文本编辑器可能会在后续项目中继续使用,因此单独将其做成一个组件,把wangeditor作为组件的形式使用. 以下是参考代码 子组件部分: 父组件引用子组件: 以上就是 wangEditor ...
- Windows下的bat原来可以为我们做很多
用了windows系统这么多年了,对bat也不是很了解.最近研究了一下bat的用法.这里就大概列举一下自己的用法 参考网址 基本命令 echo echo我们可以理解成程序中的输出,和我们Java的Sy ...
- 简易数据分析 10 | Web Scraper 翻页——抓取「滚动加载」类型网页
这是简易数据分析系列的第 10 篇文章. 友情提示:这一篇文章的内容较多,信息量比较大,希望大家学习的时候多看几遍. 我们在刷朋友圈刷微博的时候,总会强调一个『刷』字,因为看动态的时候,当把内容拉到屏 ...