分布式服务测试各节点调用第三方服务连通性

背景:分布式部署 一个主节点往各个节点下发任务(调用第三方服务),目的是为了测试各节点与第三方的连通性

思路:

主节点实现
创建Spring Boot项目:作为主节点的后端服务。
集成Eureka客户端:在主节点的pom.xml中添加Eureka客户端依赖,并在配置文件中配置Eureka服务器地址。
服务发现逻辑:编写服务来获取Eureka中的子节点列表,可以通过Eureka的REST API或者直接使用Spring Cloud提供的DiscoveryClient。
任务下发:接收外部请求,解析参数(外部系统接口名、IP、端口)。遍历从Eureka获取的子节点列表,对每个子节点发起HTTP请求,传递上述参数。
结果收集:收集各子节点的响应,组织成最终的结果列表。
子节点实现
创建Spring Boot项目:作为子节点的后端服务,并注册到Eureka服务器。
处理主节点请求:定义一个API来接收主节点的HTTP请求,提取外部系统接口名、IP、端口参数。
Socket调用外部接口:根据接收到的参数,使用Java的Socket编程建立到外部系统的连接,发送请求并等待响应。记得设置超时时间为2秒。
响应主节点:根据Socket调用的结果,构建响应信息(成功/失败及原因、外部接口名、IP、端口),并通过HTTP响应返回给主节点。
注意事项
错误处理:确保在每个关键步骤都有恰当的错误处理逻辑,比如网络请求失败、超时、Socket异常等。
日志记录:在主节点和子节点上都应记录详细的日志,便于问题追踪。
安全性:考虑对HTTP请求和Socket通信进行适当的安全加固,如使用HTTPS、身份验证等

废话不多说,直接上代码:新建一个简单的 springboot 项目,引入Eureka 等所需简单启动依赖

server 端(主节点)

参数说明:
externalApiName 策略名
ip 第三方 ip
port 第三方端口号
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/1e7d8345839d4331965026ee1f9638a1.png

controller(表单方式接收数据)

@RestController
public class TaskDistributorController {

    @Autowired
    private TaskManagerService taskManagerService;

    @PostMapping("/distributeTask")
    public ResponseEntity<List<ResultDto>> distributeTask(TaskRequest taskRequest) {
        try {
            // 调用服务层逻辑处理任务分配
            List<ResultDto> results = taskManagerService.distributeTasks(taskRequest);
            return ResponseEntity.ok(results);
        } catch (Exception e) {
            return ResponseEntity.status(500).body(null);
        }
    }


}

service

@Service
@Slf4j
public class TaskManagerService {

    @Autowired
    private DiscoveryClient discoveryClient;

    public List<ResultDto> distributeTasks(TaskRequest taskRequest) {
        // 获取子节点列表
        List<ServiceInstance> instances = discoveryClient.getInstances("deployment-test-tool-node");

        String externalApiName = taskRequest.getExternalApiName();
        List<ResultDto> results = new ArrayList<>();
        for (ServiceInstance instance : instances) {
            String workerUrl = "http://" + instance.getHost() + ":" + instance.getPort() + "/executeTask";
            // 构建请求参数
            MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
            params.put("externalApiName", Collections.singletonList(externalApiName));
            params.put("ip", Collections.singletonList(taskRequest.getIp()));
            params.put("port", Collections.singletonList(String.valueOf(taskRequest.getPort())));
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

            HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(params, headers);

            RestTemplate restTemplate = new RestTemplate();
            ResponseEntity<ResultDto> response = restTemplate.postForEntity(workerUrl, requestEntity, ResultDto.class);

            log.info("Response from worker: " + response.getBody());
            response.getBody().setIp(instance.getHost());
            response.getBody().setPort(String.valueOf(instance.getPort()));
            response.getBody().setExternalApiName(externalApiName);
            response.getBody().setExternalIpPort(taskRequest.getIp()+":"+taskRequest.getPort());
            results.add(response.getBody());
        }
        return results;
    }

}

node子节点(以 socket 方式发送请求)

controller

@RestController
public class WorkerController {

    @Autowired
    private ExternalSystemClient externalSystemClient;

    @PostMapping("/executeTask")
    public ResultDto executeTask(TaskRequest request) {
        return externalSystemClient.callExternalApi(request.getExternalApiName(), request.getIp(), request.getPort());
    }
}

service

@Service
public class ExternalSystemClient {

    public ResultDto callExternalApi(String apiName, String ip, int port) {
        Socket socket = null;
        BufferedReader in = null;
        PrintWriter out = null;
        try {
            socket = new Socket();
            SocketAddress address = new InetSocketAddress(ip, port);
            socket.connect(address, 2000); // 这里的2000是创建链接超时时间,单位为毫秒

            socket.setSoTimeout(2000); // 设置超时时间2秒

            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            out = new PrintWriter(socket.getOutputStream(), true);

            // 发送请求
            out.println(apiName);

            // 读取响应
            String response = in != null ? in.readLine() : "";
            if (response != null) {
                return new ResultDto("success", "连接成功");
            } else {
                return new ResultDto("failed", "未收到响应");
            }
        } catch (Exception e) {
            return new ResultDto("failed", e.getMessage());
        } finally {
            // 关闭资源
            if (in != null) try { in.close(); } catch (Exception ignored) {}
            if (out != null) try { out.close(); } catch (Exception ignored) {}
            if (socket != null) try { socket.close(); } catch (Exception ignored) {}
        }
    }
}

模拟第三方以socket方式接收

socketserver

@Component
@Slf4j
public class SocketServer {
    @Value("${server.port}")
    private int port;


    @PostConstruct
    public void startServer() {
        try (ServerSocket serverSocket = new ServerSocket(port)) {
            log.info("Socket服务已启动,等待连接...");
            while (true) {
                try (Socket clientSocket = serverSocket.accept();
                     PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true)) {
                    out.println("连接成功,测试联通性良好!");
                } catch (IOException e) {
                    log.error("处理客户端连接时发生错误", e);
                }
            }
        } catch (IOException e) {
            log.error("启动Socket服务器时发生错误", e);
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python28 十大机器学习算法之线性回归和逻辑回归

1.三类广义上的机器学习算法 监督学习。工作原理&#xff1a;该算法由一个目标/结果变量&#xff08;或因变量&#xff09;组成&#xff0c;该变量将从一组给定的预测变量&#xff08;自变量&#xff09;进行预测。使用这组变量&#xff0c;我们生成了一个将输入数据映射到所…

阿里云服务器入门使用教程——购买及操作系统选择并进行远程连接

文章目录 一、首先选择一个你自己要买的云服务器类型二、能选的就一个地域和一个操作系统&#xff0c;其他都是固定的三、创建完实例并使用finalshell连接的效果(要在完成后续步骤后才能连接)四、购买之后进入阿里云控制台&#xff0c;开通资源中心五、然后就可以看到已经帮你创…

Python数据可视化-地图可视化

1.首先绘制实现数据可视化的思维导图 具体要实现什么功能-怎么处理&#xff0c;先把思路写好 数据来源&#xff1a; 爬取的数据 运行结果&#xff1a; 部分代码&#xff1a; 完整代码请在下方↓↓↓&#x1f447;获取 转载请注明出处&#xff01;

Java设计模式系列--观察者模式写法4:注入接口

原文网址&#xff1a;Java设计模式系列--观察者模式写法4&#xff1a;注入接口-CSDN博客 简介 说明 本文用示例介绍观察者模式的写法&#xff1a;注入接口。此方法是观察者模式最好的写法 观察者模式的含义 以微信公众号为例&#xff0c;我们关注了某个微信公众号后能收到…

http/2 二进制分帧层 (Binary Framing Layer)讲解

文章目录 二进制帧HTTP/2 中的帧、消息和流1. 帧&#xff08;Frame&#xff09;2. 消息&#xff08;Message&#xff09;3. 流&#xff08;Stream&#xff09;总结示例&#xff1a; 二进制帧结构1.帧头部结构2.帧负载数据 请求和响应多路复用 链接参考&#xff1a;https://web.…

算法设计与分析--考试真题

分布式算法试题汇总选择题简答题算法题 2013级试题2019级试题2021年秋考卷 根据考试范围找相应题目做。 分布式算法试题汇总 选择题 下述说法错误的是___ A 异步系统中的消息延迟是不确定的 B 分布式算法的消息复杂性是指在所有合法的执行上发送消息总数的最大值 C 在一个异步…

深入探索Java开发世界:Redis~类型分析大揭秘

文章目录 深入探索Java开发世界&#xff1a;Redis~类型分析大揭秘一、数据结构类型二、分布式锁类型三、事物命令类型四、事物三大特性类型 深入探索Java开发世界&#xff1a;Redis~类型分析大揭秘 Redis数据库基础知识&#xff0c;类型知识点梳理~ 一、数据结构类型 Redis是一…

PHP语言学习02

好久不见&#xff0c;学如逆水行舟&#xff0c;不进则退&#xff0c;真是这样。。。突然感觉自己有点废。。。 <?php phpinfo(); ?> 新生第一个代码。 要想看到运行结果&#xff0c;打开浏览器&#xff08;127.0.0.1/start/demo01.php&#xff09; 其中&#xff0c…

揭开免费可视化工具流行背后的原因

免费可视化工具为什么越来越受欢迎&#xff1f;在大数据时代&#xff0c;数据可视化已经成为各行各业的重要工具。它不仅帮助企业和个人更直观地理解数据&#xff0c;还在决策过程中起到关键作用。尽管市场上有许多付费的数据可视化工具&#xff0c;但免费工具的受欢迎程度却在…

面试准备算法

枚举 答案肯定是字符串的某个前缀&#xff0c;然后简单直观的想法是枚举所有前缀来判断&#xff0c;设前缀长度lenz&#xff0c;前缀串的长度必然要是两个字符串长度的约数才能满足条件。 可以枚举长度&#xff0c;再去判断这个前缀串拼接若干次以后是否等于str1和str2。 cla…

高德地图基于Three开发三维流动管线。

先看效果 废话少说直接上干货,整体思路通过高德地图的GLCustomLayer图层加载Three三维管线。 第一步将管线经纬度转成三维空间经纬度 GLCustomLayer = new (window as any).AMap.GLCustomLayer({zIndex: 120,visible: true,init: (gl: any) => {initThree(gl);// burialDe…

idea Error running ‘Application‘

1、Error running ‘Application’ Error running ApplicationError running Application. Command line is too long.Shorten the command line via JAR manifest or via a classpath file and rerun.找到 .idea/libraies/workspace.xml 中的 PropertiesComponent 属性&#…

ICRA 2024 混变刚度的仿人软体手指实现多模式抓取

ICRA 2024 发表了"用于多模式抓取的具有混合可变刚度机制的仿生软指 "的研究工作。核心思想是利用记忆合金的形状记忆效应&#xff0c;构建结构简化、功能多样的柔性手指&#xff0c;从而实现更高效的多模式抓取。 与传统的刚性夹爪相比&#xff0c;柔性软体夹爪具有…

阿里巴巴找黄金宝箱(IV)

系列文章目录 本人最近再练习算法&#xff0c;所以会发布自己的解题思路&#xff0c;希望大家多指教 文章目录 系列文章目录前言一、题目描述二、输入描述三、输出描述四、java代码五、测试用例 前言 一、题目描述 贫如洗的椎夫阿里巴巴在去砍柴的路上&#xff0c;无意中发现…

CICD相关概念简单理解——筑梦之路

CI/CD 是现代软件开发流程中的关键实践&#xff0c;它代表着持续集成&#xff08;Continuous Integration&#xff09;和持续部署&#xff08;Continuous Deployment&#xff09;或持续交付&#xff08;Continuous Delivery&#xff09;的组合。这些实践旨在帮助软件开发团队更…

Java学习 (五) 面向对象--包概念、封装、构造器

一、 package &#xff08;包&#xff09; package 包 用于指定该文件中定义的类、接口等结构 像我们之前练习的代码&#xff0c;在顶部并没有定义package的关键字&#xff0c;这种就属于无名包 1、包 &#xff08;java 库&#xff09; 在java中的包&#xff0c;是一堆类和接…

2024我们该学习大模型吗?

一、引言 在快速变化的科技行业中&#xff0c;人工智能&#xff08;AI&#xff09;大模型已成为研究和应用的热点。随着AI技术的不断进步&#xff0c;特别是在自然语言处理、计算机视觉和机器学习平台等领域&#xff0c;许多专业人士开始将目光投向AI大模型的开发和应用。 二…

Linux挂载Windows共享文件

一、Windows共享目录 二、Linux挂载 yum install cifs-utils mkdir /aaa/ mount.cifs -o usernamexxx,passwordxxx //172.16.8.121/aaa /aaa/

【机器学习】在【PyCharm中的学习】:从【基础到进阶的全面指南】

目录 第一步&#xff1a;基础准备 1.1 Python基础 1.1.1 学习Python的基本语法 变量和数据类型&#xff1a; 1.1.2 控制流 条件语句&#xff1a; 循环语句&#xff1a; 1.1.3 函数和模块 函数&#xff1a; 模块&#xff1a; 1.2 安装PyCharm 1.2.1 下载并安装 第二…

Spring Boot 过滤器和拦截器详解

目录 Spring Boot 过滤器1.什么是过滤器2.工作机制3.实现过滤器 Spring Boot 拦截器1. 什么是拦截器2. 工作原理3.实现4.拓展&#xff08;MethodInterceptor 拦截器&#xff09;实现 过滤器和拦截器区别过滤器和拦截器应用场景过滤器拦截器 Spring Boot 过滤器 1.什么是过滤器 …