88 docker 环境下面 前端A连到后端B + 前端B连到后端A

前言

呵呵 最近出现了这样的一个问题, 我们有多个前端服务, 分别连接了对应的后端服务, 前端A -> 后端A, 前端B -> 后端B 

但是 最近的时候 却会出现一种情况就是, 有些时候 前端A 连接到了 后端B, 前端B 连接到了 后端A  

我们 前端服务使用 nginx 提供前端 html, js, css 的服务, 对于前端业务中的请求, 也是使用的 nginx 来代理到真实的后端服务上面, 后端服务 我们就假定为普通的 tomcat 服务器, 前后端服务都是部署在 docker 上面

然后 就给人造成一种 数据跑掉了的错觉, 呵呵 也是引起了我们同事 使用系统的很大的疑惑, 然后 搞出了一些 "我的数据 再和我做迷藏", "我的数据从成都跑到北京去了" 之类的笑话 

然后 你一去检查服务的配置, 等等, 你发现 前端配置, 后端配置 都没得问题, 我最开始以为是 nginx 运行时加载的配置 被修改了?, 加载在内存的配置 和 实际的配置文件不一致?, 但是 实际 看了一下, 发现配置是 没有问题的 

对于这个问题 还是很好奇的, 当然 后面也做了一些 探索, 也有一些 初步的推断, 然后 今天的时候[1114] 尝试在本地复现一下这个问题, 也发现了一些 和自己开始的判断 不一样的一些地方 

let's go 

问题特征

这个问题的出现 和 消失有这样的一些特征 

1. 所有的前端, 后端配置都是正常的, 但是 实际接口返回的数据 就是不一样 

2. 出现了这个问题之后, 重启一下 前端服务 之后, 前端服务就正常了 

3. 一般是后端代码更新了之后, jenkins 自动发版之后 会出现这个问题 

前端容器中 也缺少 ping 之类的网络工具, 造成排查的时候 还是存在一些 障碍 

问题inspect

最开始 想要处理这个问题, 我得看一下 nginx 最终吧服务转发到了 那一台后端服务器 

因此, 在 nginx 配置的地方, 增加了一个 add_header backendIP $upstream_addr; 来获取实际处理 后端请求的服务的信息 

然后 后来一次 是因为 后台发版了, 之后 这个问题就复现了, 这也使我观察到了 上面的 特征3 

然后 看一下 backendIP, 然后 再 inspect 对应的额后端服务, 发现后端服务的 ip 和这个 backendIP 对不上 ?? 

所以 问题的大致原因 也就出现了, 发版之后 后端服务的 ip 变化了, 然后 前端服务里面访问的 ip 还是之前的 ip 

当然 最开始, 我以为是 前端服务里面的 dns 缓存之类的, 直到今天 测试了一下, 发现 似乎是其他的原因 

接下来 我们便来以一个 demo 实际的走一下 这个流程 

构造问题

首先 我们需要 一个前端服务, 和 两个后端服务, 前端服务A 只连接 其中的一个 后端服务A 

然后 之后我们同时重启 两个后端服务, 然后 再来访问这个 前端服务A, 可能会存在 前端服务A 访问到了 后端服务B 的情况 

1. 看下后端服务 

一个简单的 SpringBoot 项目, 其中开放了一些简单的接口, 比如这里的 /hello/context, 可以输出 当前应用名称 和 一些上下文的信息 

2. 部署后端服务 

首先来部署两个后端服务, docker-compose 大致如下 

两个服务使用 同一个镜像, 只是传递的环境变量的 APP_NAME 有一些区别, 因此 访问 /hello/context 的时候 appName 的输出会有一些区别 

另外使用同一个镜像的原因在于, 更加简单的构造 两个镜像同时重启 

version: "2"networks:fuzzy:external: trueservices:app0:container_name: app0image: app0:0.0.1ports:- "7901:7901"environment:APP_NAME: app0networks:- fuzzyapp1:container_name: app1image: app0:0.0.1ports:- "7902:7901"environment:APP_NAME: app1networks:- fuzzy

服务起起来之后 测试一下, 这里把服务映射到了宿主机的端口, 根据这个来测试一下 

访问情况如下, 可以看到是 符合我们的预期的, 不是很意外 

http://localhost:7901/hello/context

http://localhost:7902/hello/context

3. 部署前端服务 

前端服务我们这里 为了简单, 是直接使用的 nginx 镜像, 没有业务, 连接 app0 的服务 

前端服务的 docker-compose 如下 

version: "2"networks:fuzzy:external: trueservices:nginx:container_name: nginximage: nginx:latestports:- "80:80"volumes:- ./data:/etc/nginxnetworks:- fuzzy

nginx 配置大致如下 

可以看到 /hello 开头的这部分请求, 我们把它 转发到了 app0 的服务上面, 使用 add_header backendIP $upstream_addr; 输出了一下 具体的处理业务的后端服务器的信息  

server {listen       80;listen  [::]:80;server_name  localhost;location / {root   /usr/share/nginx/html;index  index.html index.htm;}location ~ /hello {proxy_pass   http://app0:7901;add_header backendIP $upstream_addr;proxy_set_header SSL-Client-Cert $ssl_client_cert;proxy_set_header name jerry;}#error_page  404              /404.html;# redirect server error pages to the static page /50x.htmlerror_page   500 502 503 504  /50x.html;location = /50x.html {root   /usr/share/nginx/html;}}

4. 正常情况 和 出现问题的情况 

正常的情况 

出现问题 

问题细节

正常情况

首先我们看一下 app0, app1, nginx 的 ip 情况 

从下面可以整理出 网路情况如下 

app0192.168.80.3
app1192.168.80.2
nginx192.168.80.4

然后我们来看一下 正常的情况下 处理的后端服务的情况 

可以看到的是 访问的是 ip 是 192.168.80.3 对应于上面的 app0 

我们重启 app0, app1 直到复现问题

我们可以看到 此时处理服务的容器 的ip还是 192.168.80.3 

但是 返回的数据, 却已经是 app1 应该返回的数据了 

我们再来看一下 app0, app1, nginx 的 ip 情况 

从下面可以整理出 网路情况如下 

app0192.168.80.2
app1192.168.80.3
nginx192.168.80.4

可以看到的是 app0 和 app1 的 ip 变了, 两个容器的 ip 交换了一下, 但是 前端容器 还是将服务委托给了 192.168.80.3 的这个容器, 而不是 app0 这个服务 

是前端容器的 dns 的缓存么? 

为了 验证这个问题, 呵呵 可以使用 ping 或者 nslookup 之类的网络工具, 但是 在 nginx 容器里面这两个都没得 

我今天 还想了一阵子, 怎么验证这个问题, 呵呵 curl 有一个 -v, verbose 展示出请求的更详细的信息 

curl -v http://app0:7901/hello/context 

从下面的日志信息可以看出, 从 前端服务的容器中访问 app0 访问的是 最新的app0[192.168.80.2], 因此可以排除 容器的 dns缓存的猜测 

master:nginx jerry$ docker exec -it nginx /bin/sh
# curl -v http://app0:7901/hello/context
* Expire in 0 ms for 6 (transfer 0x55712a1dff50)
* Expire in 1 ms for 1 (transfer 0x55712a1dff50)
* Expire in 0 ms for 1 (transfer 0x55712a1dff50)
* Expire in 1 ms for 1 (transfer 0x55712a1dff50)
* Expire in 0 ms for 1 (transfer 0x55712a1dff50)
* Expire in 0 ms for 1 (transfer 0x55712a1dff50)
* Expire in 2 ms for 1 (transfer 0x55712a1dff50)
* Expire in 0 ms for 1 (transfer 0x55712a1dff50)
* Expire in 0 ms for 1 (transfer 0x55712a1dff50)
* Expire in 2 ms for 1 (transfer 0x55712a1dff50)
* Expire in 0 ms for 1 (transfer 0x55712a1dff50)
* Expire in 0 ms for 1 (transfer 0x55712a1dff50)
* Expire in 2 ms for 1 (transfer 0x55712a1dff50)
* Expire in 0 ms for 1 (transfer 0x55712a1dff50)
* Expire in 0 ms for 1 (transfer 0x55712a1dff50)
* Expire in 2 ms for 1 (transfer 0x55712a1dff50)
* Expire in 0 ms for 1 (transfer 0x55712a1dff50)
* Expire in 0 ms for 1 (transfer 0x55712a1dff50)
* Expire in 0 ms for 1 (transfer 0x55712a1dff50)
*   Trying 192.168.80.2...
* TCP_NODELAY set
* Expire in 200 ms for 4 (transfer 0x55712a1dff50)
* Connected to app0 (192.168.80.2) port 7901 (#0)
> GET /hello/context HTTP/1.1
> Host: app0:7901
> User-Agent: curl/7.64.0
> Accept: */*
> 
< HTTP/1.1 200 
< Content-Type: text/plain;charset=UTF-8
< Content-Length: 135
< Date: Sat, 14 Nov 2020 09:24:12 GMT
< 
* Connection #0 to host app0 left intact
context info as follow!, APP_NAME : app0<br/> headers : {"host":"app0:7901","user-agent":"curl/7.64.0","accept":"*/*"}<br/> params : {}

nginx 的 dns 缓存

nginx -s reload 一下 

# nginx -s reload 
2020/11/14 09:27:13 [notice] 33#33: signal process started

看一下 /hello/context 的情况, 返回的数据也是 app0 处理之后返回的数据, backendIP 也更新成了 192.168.80.2[app0对应的ip] 

所以之前的处理方式 : 重启前端服务, 实际上真正解决问题的是 nginx 的重新加载 

完 

参考

nginx查看请求被转发到哪台服务器

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/669897.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

嵌入式软件bug分析基本要求

摘要&#xff1a;软件从来不是一次就能完美的&#xff0c;需要以包容的眼光看待它的残缺。那问题究竟为何产生&#xff0c;如何去除呢&#xff1f; 1、软件问题从哪来 软件缺陷问题千千万万&#xff0c;主要是需求、实现、和运行环境三方面。 1.1 需求描述偏差 客户角度的描…

【教程】ESP32-CAM使用I2C驱动0.91寸OLED

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhang.cn] 先安装库 1. 打开 Arduino IDE&#xff0c;然后转到 Sketch > Include Library > Manage Libraries。 2. 在搜索框中输入“SSD1306”&#xff0c;然后从 Adafruit 安装 SSD1306 库。 3. 选择“install al…

文心一言 VS 讯飞星火 VS chatgpt (195)-- 算法导论14.3 3题

三、用go语言&#xff0c;请给出一个有效的算法&#xff0c;对一个给定的区间i&#xff0c;返回一个与i重叠且具有最小低端点的区间;或者当这样的区间不存在时返回T.nil。 文心一言&#xff0c;去掉math&#xff0c;代码正常运行&#xff1a; 在Go语言中&#xff0c;你可以使…

JenkinsGitLab完成自动化构建部署

关于GitLab安装:GitLab安装-CSDN博客 Docker中安装GitLab:Docker下安装GitLab-CSDN博客 安装JenKins Jenkins官网:Jenkins 中文版:Jenkins 安装时候中文页面的war包下不来 在英文页面 记得装JDK8以上 JenKins使用java写的 运行JenKins需要JDK环境 我这里已经装好了 将下…

python制作恶意软件删除工具

今天&#xff0c;来教大家用python制作一个恶意软件删除工具 查杀流程图 对&#xff0c;就这些&#xff0c;已经具备了杀毒软件的功能 判断文件是否为病毒 要查杀病毒&#xff0c;先要判断文件是不是病毒&#xff08;不然删错了咋办&#xff09;&#xff0c;这里我们用获取文…

云计算市场分析

目录 一、云计算市场概述 1.1 概述 二、国外云计算厂商 2.1 亚马逊AWS 2.2 微软AzureAzure 2.3 Apple iCloud 三、国内云计算厂商 3.1 阿里云 3.2 腾讯云 3.3 华为云 3.4 百度智能云 一、云计算市场概述 1.1 概述 云计算从出现以来&#xff0c;其发展就非常迅速。以…

win10重装Ubuntu22.04安装报错复盘

目录 一&#xff1a;补充启动盘制作 二&#xff1a;错误信息[0xC0030570] The file or directory is corrupted and unreadable. 三&#xff1a;ubuntu重装步骤&#xff1a; 四&#xff1a;磁盘冗余阵列 五&#xff1a;尝试将SCS11(2,0.0), 第1分区(sda)设备的一个vfat文…

大华智慧园区综合管理平台 /ipms/barpay/pay RCE漏洞复现

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

springboot kafka 实现延时队列

好文推荐&#xff1a; 2.5万字详解23种设计模式 基于Netty搭建websocket集群实现服务器消息推送 2.5万字讲解DDD领域驱动设计 文章目录 一、延时队列定义二、应用场景三、技术实现方案&#xff1a;1. Redis2. Kafka3. RabbitMQ4. RocketMQ 四、Kafka延时队列背景五、Kafka延时队…

锐捷VSU和M-LAG介绍

参考网站 堆叠、级联和集群的概念 什么是堆叠&#xff1f; 框式集群典型配置 RG-S6230[RG-S6501-48VS8CQ]系列交换机 RGOS 12.5(4)B1005版本 配置指南 总结 根据以上的几篇文章总结如下&#xff1a; 级联&#xff1a;简单&#xff0c;交换机相连就叫级联&#xff0c;跟搭…

HCIA--路由优先级实验

要求&#xff1a; 1. pc1访问pc3,4,5走上面&#xff0c;R1-R2实现备份21.1.1.0/24实现备份&#xff1b; 2. pc3,4,5,6访问pc1,2走下面&#xff0c; R3,4之间实现等价路由&#xff0c;尽量减少路由条目&#xff0c;实现全网可达&#xff0c;pc7代表运营商 所有pc均可访问 1…

5.0 ZooKeeper 数据模型 znode 结构详解

数据模型 在 zookeeper 中&#xff0c;可以说 zookeeper 中的所有存储的数据是由 znode 组成的&#xff0c;节点也称为 znode&#xff0c;并以 key/value 形式存储数据。 整体结构类似于 linux 文件系统的模式以树形结构存储。其中根路径以 / 开头。 进入 zookeeper 安装的 …

阅读笔记——《RapidFuzz: Accelerating fuzzing via Generative Adversarial Networks》

【参考文献】Ye A, Wang L, Zhao L, et al. Rapidfuzz: Accelerating fuzzing via generative adversarial networks[J]. Neurocomputing, 2021, 460: 195-204.【注】本文仅为作者个人学习笔记&#xff0c;如有冒犯&#xff0c;请联系作者删除。 目录 摘要 一、介绍 二、相关…

寒假作业-day4

1>请编程实现哈希表的创建存储数组{12,24,234,234,23,234,23}&#xff0c;输入key查找的值&#xff0c;实现查找功能。 代码&#xff1a; #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> typedef int datatype; type…

C++ PE文件信息解析

尝试解析PE文件结构, 于是编写了此PE信息助手类, 暂时完成如下信息解析 1.导入表信息 2.导入表信息 3.资源表信息 CPEHelper.h #pragma once// // brief: PE文件解析助手类 // copyright: Copyright 2024 FlameCyclone // license: // birth: Created by Visual Studio 20…

软件价值8-站点连通性检查

站点连通性检查&#xff0c;即看网站是否能访问得通&#xff0c;实用价值不大&#xff0c;不过用来作软件应用入门还不错。 代码&#xff1a; import urllib.request import tkinter as tkdef test_connectivity():window tk.Tk()window.geometry(600x400)window.resizable(F…

输出超级玛丽2_题解

【题解提供者】吴立强 解法 思路 本题代码非常简单&#xff0c;直接一行一行对齐后输出即可&#xff0c;只是比较麻烦。 代码展示 #include <iostream> using namespace std;int main() {printf(" ********\n");printf(" …

普通编程,机器学习与深度学习

普通编程&#xff1a;基于人手动设置规则&#xff0c;由输入产生输出经典机器学习&#xff1a;人手工指定需要的特征&#xff0c;通过一些数学原理对特征与输出的匹配模式进行学习&#xff0c;也就是更新相应的参数&#xff0c;从而使数学表达式能够更好的根据给定的特征得到准…

Java 学习和实践笔记(1)

2024年&#xff0c;决定好好学习计算机语言Java. B站上选了这个课程&#xff1a;【整整300集】浙大大佬160小时讲完的Java教程&#xff08;学习路线Java笔记&#xff09;零基础&#xff0c;就从今天开始学吧。 在这些语言中&#xff0c;C语言是最基础的语言&#xff0c;绝大多…

Blender_pmx导出fbx

Blender_pmx导出fbx 学无止境&#xff1f; 相关链接&#xff1a; Blender教程&#xff1a; Blender中文手册介绍 — Blender Manualhttps://docs.blender.org/manual/zh-hans/2.79/about/introduction.htmlhttps://www.blendercn.org/https://www.blendercn.org/Blender下载…