当前位置: 首页 > news >正文

docker里Java服务执行ping命令模拟流式输出

文章目录

    • 业务场景
    • 处理解决
      • 实现ping功能并实时返回输出
      • 实现长ping和中断请求
      • docker容器找不到ping命令处理

业务场景

  • 我们某市的客户,一直使用CS版本的信控平台,直接安装客户Windows server服务器上,主要对信号机设备进行在线管理、方案配时、管控等
  • 其中有一项功能,在网络波动情况,对信号机管控失败,判断信号机是否在线。大致方法是直接调用Windows的dos窗口,发送 ping ip的命令,显示网络情况
  • 我们新的信控平台使用Spring Cloud微服务架构,使用Spring Boot构建Java服务,使用google的jib插件打成docker镜像包
  • 我们使用docker虚拟化部署,使用docker-compose统一管理所有服务,部署在Linux服务器里
  • 客户很喜欢之前的功能,需要我们在新平台里实现这个功能,调用dos窗口,ping网络
  • 而我们新平台是B/S架构,浏览器是很难调用Windows组件去弹出窗口实现ping功能,而且我们也没有限制一定使用的是Windows电脑访问,有网有浏览器就行
  • ping功能无论Windows还是Linux,都是有的,至于界面展现,只能自己实现了
    在这里插入图片描述

处理解决

实现ping功能并实时返回输出

  • 代码实现,有两个核心功能点
  • 一是根据不同的操作系统,执行对应的系统命令,进行结果接收与解析
    • 对于第一个问题,Java有现成的类库,使用Runtime.getRuntime().exec(ping命令)即可
    • 对于Windows服务器,需要使用GB2312解析命令执行结果
    • 对于Linux 服务器,需要使用UTF_8解析命令执行结果
    • 对于ServletOutputStream.println输出中文字符串报错Not an ISO 8859-1 character问题,可以使用PrintWriter.println输出代替
    • 也可以在ServletOutputStream.println输出时输出字符数组(string.getBytes()
  • 二是流式输出到请求端,模拟再现一秒一次的逐步展示的效果
    • 对于第二个问题,核心是命令执行的结果输出流,要实时的返回给请求端,请求端能接收到
    • 主要是获取流,然后按行读取,按行flush()即可返回给请求端
    • 对于请求端实时渲染,需要在代码的response里指定ContentTypetext/event-stream,这样flush刷新的返回流,才能实时被前端浏览器接收到(ChatGPT流式输出也是使用的这种content-type
    • 一开始是考虑使用multipart,完全不行,流flush后,浏览器无法获取,只能在流输出完成后,浏览器才能获取到
  • 具体代码如下:
    /*** 获取信号机的网络状态* @param ip* @param count* @param response*/@GetMapping("/ping/start")public void ping(String ip, Integer count, HttpServletResponse response) {logger.info("ping 信号机【{}】 开始 ......", ip);response.setStatus(HttpServletResponse.SC_OK);response.setContentType("text/event-stream");response.setCharacterEncoding("UTF-8");String line = null;Process pro = null;BufferedReader buf = null;try {if (null == count) {count = 4;}String osName = System.getProperty("os.name");if (osName.toLowerCase().contains("windows")){pro = Runtime.getRuntime().exec("ping -n " + count + " " + ip);buf = new BufferedReader(new InputStreamReader(pro.getInputStream(), "GB2312"));} else if (osName.toLowerCase().contains("linux")){pro = Runtime.getRuntime().exec("ping -c " + count + " " + ip);buf = new BufferedReader(new InputStreamReader(pro.getInputStream(), StandardCharsets.UTF_8));}PrintWriter out = response.getWriter();while (null != buf && (line = buf.readLine()) != null){out.println(line);out.flush();}logger.info("执行ping请求结束!");out.close();} catch (Exception e){logger.error("执行ping命令出现异常");e.printStackTrace();}finally {if (null != pro){pro.destroy();}}}

实现长ping和中断请求

  • 主要是在请求时传输一个唯一命令id,缓存到内存里
  • 当命令执行完成,或者接收到打断请求时,调用destroy()打断循环,结束请求
  • 当然,可以尝试使用kill -2去模拟CTRL + C的打断,可以使用Runtime.getRuntime().exec(中断命令)打断试下,我的代码已经满足自己的需求了,就没再尝试,有兴趣的小伙伴可以试一下
  • 具体代码如下:

package com.newatc.api.rest;import com.newatc.api.signalcontrol.dto.PingRequestVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;/*** 调用系统命令并返回** @author yanyulin* @date 2024-1-16 15:11:55*/
@RestController
@RequestMapping(value = "/api/syscmd")
public class SysCmdController {private static final Logger logger = LoggerFactory.getLogger(SysCmdController.class);/*** 命令id-执行过程map*/public static final Map<String, Boolean> COMMAND_REQUEST_MAP = new HashMap<>();/*** 开始信号机的网络状态诊断*/@PostMapping("/ping/start")public void ping(@RequestBody PingRequestVO pingRequest, HttpServletResponse response) {String ip = pingRequest.getIp();String cmdId = pingRequest.getCmdId();Integer count = pingRequest.getCount();logger.info("ping 信号机【{}】 开始 ......", ip);response.setStatus(HttpServletResponse.SC_OK);response.setContentType("text/event-stream");response.setCharacterEncoding("UTF-8");String line = null;Process pro = null;BufferedReader buf = null;try {if (null == count) {count = 4;}if (count > 50) {count = 50;}String osName = System.getProperty("os.name");if (osName.toLowerCase().contains("windows")){pro = Runtime.getRuntime().exec("ping -n " + count + " " + ip);buf = new BufferedReader(new InputStreamReader(pro.getInputStream(), "GB2312"));} else if (osName.toLowerCase().contains("linux")){pro = Runtime.getRuntime().exec("ping -c " + count + " " + ip);buf = new BufferedReader(new InputStreamReader(pro.getInputStream(), StandardCharsets.UTF_8));}COMMAND_REQUEST_MAP.put(cmdId, true);PrintWriter out = response.getWriter();while (null != buf && (line = buf.readLine()) != null){out.println(line);out.flush();if (!COMMAND_REQUEST_MAP.get(cmdId)) {pro.destroy();}}logger.info("执行ping请求结束!");out.close();} catch (Exception e){logger.error("执行ping命令出现异常");e.printStackTrace();}finally {if (null != pro){pro.destroy();}COMMAND_REQUEST_MAP.remove(cmdId);}}/*** 打断命令执行状态*/@PostMapping("/ping/stop")public void ping(@RequestBody PingRequestVO requestVO) {COMMAND_REQUEST_MAP.put(requestVO.getCmdId(), false);}
}

docker容器找不到ping命令处理

  • 我们打包导出的docker镜像,无法使用ping命令,报错,找不到这个命令bash: ping:command not found
  • 我们使用的是极简镜像eclipse-temurin:11-jre-focal,这个版本里的ubuntu没有安装不需要的命令
  • 具体可以参考我的这篇博文:《自制Java镜像发布到dockerhub公网使用》
  • 也可以直接使用我发布到公网的包含ping命令的jre11镜像文件1363241277/jre11:11-jre-focal
  • 主要思路,就是打包使用的原始Java镜像里,要已经安装ping等需要的命令

相关文章:

docker里Java服务执行ping命令模拟流式输出

文章目录 业务场景处理解决实现ping功能并实时返回输出实现长ping和中断请求docker容器找不到ping命令处理 业务场景 我们某市的客户&#xff0c;一直使用CS版本的信控平台&#xff0c;直接安装客户Windows server服务器上&#xff0c;主要对信号机设备进行在线管理、方案配时…...

代码随想录算法训练营第十三天| 239. 滑动窗口最大值 、347.前 K 个高频元素

239. 滑动窗口最大值 思路&#xff1a; 用遍历区间的元素时&#xff0c;维护一个单调队列&#xff0c;从大到小排列。 要找到最大值&#xff0c;实际单调队列保存区间内最大值及最大值右侧的第二大值&#xff08;用于当前最大值处于区间左端&#xff0c;在区间右移时更新临时最…...

旋转花键的使用寿命与机械原理分析

旋转花键是一种传动部件&#xff0c;广泛应用于各种机械设备中。对于厂商来说&#xff0c;如何保证使用寿命是重中之重&#xff0c;而旋转花键的使用寿命与其机械原理密切相关&#xff0c;了解其机械原理有助于更好地维护和使用旋转花键&#xff0c;从而提高其使用寿命。 旋转花…...

互联网摸鱼日报(2024-01-22)

互联网摸鱼日报(2024-01-22) 开源中国资讯 Stability AI 推出更小、更高效的 1.6B 语言模型 X 正面向 Android 推出音频和视频通话 Extism —— WebAssembly 插件实现框架 Gitee 推荐 | 龙蜥社区最佳安全加固实践指南 security-benchmark 每日一博 | 得物云原生容器技术探…...

CentOS 7 安装配置MySQL

目录 一、安装MySQL​编辑​编辑 1、检查MySQL是否安装及版本信息​编辑 2、卸载 2.1 rpm格式安装的mysql卸载方式 2.2 二进制包格式安装的mysql卸载 3、安装 二、配置MySQL 1、修改MySQL临时密码 2、允许远程访问 2.1 修改MySQL允许任何人连接 2.2 防火墙的问题 2…...

Gold-YOLO(NeurIPS 2023)论文与代码解析

paper&#xff1a;Gold-YOLO: Efficient Object Detector via Gather-and-Distribute Mechanism official implementation&#xff1a;https://github.com/huawei-noah/Efficient-Computing/tree/master/Detection/Gold-YOLO 存在的问题 在过去几年里&#xff0c;YOLO系列已经…...

多个coco数据标注文件合并

一、coco数据集是什么&#xff1f; COCO&#xff08;Common Objects in Context&#xff09;是一个用于目标检测和图像分割任务的标注格式。如果你有多个COCO格式的JSON文件&#xff0c;你可能需要将它们合并成一个文件&#xff0c;以便更方便地处理和管理数据。在这篇博客中&…...

Kubernetes(K8S)拉取本地镜像部署Pod 实现类似函数/微服务功能(可设置参数并实时调用)

以两数相加求和为例&#xff0c;在kubernetes集群拉取本地的镜像&#xff0c;实现如下效果&#xff1a; 1.实现两数相加求和 2.可以通过curl实时调用&#xff0c;参数以GET方式提供&#xff0c;并得到结果。&#xff08;类似调用函数&#xff09; 一、实现思路 需要准备如下的…...

k8s使用ingress实现应用的灰度发布升级

v1是1.14.0版本nginx ,实操时候升级到v2是1.20.0版本nginx&#xff0c;来测试灰度发布实现过程 一、方案&#xff1a;使用ingress实现应用的灰度发布 1、服务端&#xff1a;正常版本v1&#xff0c;灰度升级版本v2 2、客户端&#xff1a;带有请求头versionv2标识的请求访问版…...

最新热门商用GPT4.0带MJ绘画去授权版本自定义三方接口(开心版)

一台VPS 搭建宝塔 解析域名 上传程序至根目录 访问首页在线安装配置数据库 PHP版本选择:7.3 安装完成后访问网站首页即可&#xff01; 配置APIKEY&#xff0c;登录网站后台自定义配置&#xff0c;不然网站无法使用&#xff01; 网站后台地址/admin 默认账号:admin 密码…...

Halcon基于形状的模板匹配inspect_shape_model

Halcon基于形状的模板匹配 基于形状的匹配&#xff0c;就是使用目标对象的轮廓形状来描述模板。Halcon中有操作助手&#xff0c;可以直观 地进行形状模板匹配的参数选择以及效果测试。如果使用算子编写&#xff0c;步骤如下。 &#xff08;1&#xff09;从参考图像上选择检测的…...

html中根元素以及根元素字体的含义

在 HTML 中&#xff0c;根元素是指 <html> 标签&#xff0c;可以使用 CSS 来设置根元素的字体大小。根元素的字体大小会影响整个页面的文本内容&#xff0c;默认情况下&#xff0c;根元素的字体大小是浏览器默认的大小。 要设置根元素的字体大小&#xff0c;你可以使用 …...

51单片机1-6

目录 单片机介绍 点亮一个LED 流水灯参考代码 点亮流水LEDplus版本 独立按键 独立按键控制LED亮灭 静态数码管 静态数码管显示 动态数码管显示 模块化编程 调试工具 矩阵键盘 矩阵键盘显示数据 矩阵键盘密码锁 学习B站江协科技课程笔记。 安装keil&#xff0c;下…...

vue2(Vuex)、vue3(Pinia)、react(Redux)状态管理

vue2状态管理Vuex Vuex 是一个专为 Vue.js应用程序开发的状态管理模式。它使用集中式存储管理应用的所有组件的状态&#xff0c;以及规则保证状态只能按照规定的方式进行修改。 State&#xff08;状态&#xff09;:Vuex 使用单一状态树&#xff0c;即一个对象包含全部的应用层…...

用户画像项目背景

1,用户画像项目介绍 大数据平台简介 数据仓库+用户画像+推荐系统 (1)数据仓库:加快数据的分析和查询 数据仓库分层:ODS层(映射HDFS的数据)—DW(数据仓库层)–APP(层)—BI(层) DW:DWD明细数据层(数据的清洗和转换),DWM(轻度聚合层),DWS(高度聚合),APP(层),DIM(层) …...

Go使用记忆化搜索的套路【以20240121力扣每日一题为例】

题目 分析 这道题很明显记忆化搜索&#xff0c;用py很容易写出来 Python class Solution:def splitArray(self, nums: List[int], k: int) -> int:n len(nums)# 寻找分割子数组中和的最小的最大值s [0]for num in nums:s.append(s[-1] num)#print(s)cachedef dfs(cur,…...

【LeetCode】每日一题 2024_1_21 分割数组的最大值(二分)

文章目录 LeetCode&#xff1f;启动&#xff01;&#xff01;&#xff01;题目&#xff1a;分割数组的最大值题目描述代码与解题思路 LeetCode&#xff1f;启动&#xff01;&#xff01;&#xff01; 今天是 hard&#xff0c;难受&#xff0c;还好有题解大哥的清晰讲解 题目&a…...

bevy the book 20140118翻译(全)

源自&#xff1a;Bevy Book: Introduction 主要用 有道 翻译。 Introduction 介绍 Getting Started 开始 Setup 设置 Apps 应用程序 ECS Plugins 插件 Resources 资源 Next Steps 下一个步骤 Contributing 贡献 Code 代码 Docs 文档 Building Bevys Ecosystem 构建 b…...

MySQL数据库面试知识点

1、数据库基础&#xff1a; MySQL是一个开源的关系型数据库管理系统&#xff0c;用于存储、管理和检索数据。它支持多种存储引擎&#xff0c;包括InnoDB、MyISAM等。MySQL是由瑞典公司MySQL AB开发&#xff0c;后来被Sun Microsystems收购&#xff0c;最终被甲骨文公司(Oracle…...

超优秀的三维模型轻量化、格式转换、可视化部署平台!

1、基于 HTML5 和 WebGL 技术&#xff0c;可在主流浏览器上进行快速浏览和调试&#xff0c;支持PC端和移动端 2、自主研发 AMRT 展示框架和9大核心技术&#xff0c;支持3D模型全网多端流畅展示与交互 3、提供格式转换、减面展UV、烘焙等多项单模型和倾斜摄影模型轻量化服务 4、…...

AtCoder 第409​场初级竞赛 A~E题解

A Conflict 【题目链接】 原题链接&#xff1a;A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串&#xff0c;只有在同时为 o 时输出 Yes 并结束程序&#xff0c;否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言&#xff1a;为什么 Eureka 依然是存量系统的核心&#xff1f; 尽管 Nacos 等新注册中心崛起&#xff0c;但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制&#xff0c;是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案

一、TRS收益互换的本质与业务逻辑 &#xff08;一&#xff09;概念解析 TRS&#xff08;Total Return Swap&#xff09;收益互换是一种金融衍生工具&#xff0c;指交易双方约定在未来一定期限内&#xff0c;基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

基于Docker Compose部署Java微服务项目

一. 创建根项目 根项目&#xff08;父项目&#xff09;主要用于依赖管理 一些需要注意的点&#xff1a; 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件&#xff0c;否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

Rust 异步编程

Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

SpringTask-03.入门案例

一.入门案例 启动类&#xff1a; package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...

全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比

目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec&#xff1f; IPsec VPN 5.1 IPsec传输模式&#xff08;Transport Mode&#xff09; 5.2 IPsec隧道模式&#xff08;Tunne…...

laravel8+vue3.0+element-plus搭建方法

创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...

ABAP设计模式之---“简单设计原则(Simple Design)”

“Simple Design”&#xff08;简单设计&#xff09;是软件开发中的一个重要理念&#xff0c;倡导以最简单的方式实现软件功能&#xff0c;以确保代码清晰易懂、易维护&#xff0c;并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计&#xff0c;遵循“让事情保…...