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

grpc代理服务的实现(一)

最近公司需要无感知基于服务代号来实现通信, 并监控和管理通信连接,目前公司使用的是如下的逻辑(当然逻辑简化了,但是思想不变)

目录

    • 简单的原理图
    • 代理服务的实现
      • 创建 tls tcp 服务, 用于grpc client 和 grpc service 通信
      • 保存 与 代理服务建立的 grpc service 的连接
      • 保存 grpc client dial 的连接
        • client 连接上了的时候告诉 tcp server, 要连接哪个 grpc service
        • 从 保存的conn 中查询是否有 相关的连接
        • 如果有,则 通过 io.Copy 来让grpc client 与 grpc service 通信
      • 代码地址

简单的原理图

schematic diagram

代理服务的实现

创建 tls tcp 服务, 用于grpc client 和 grpc service 通信

func Run() error {// 创建 CA证书 用于 tls 连接ca, err := private_keys.NewCA("127.0.0.1")if err != nil {log.Fatal(err)}serverCA, err := tls.X509KeyPair(ca.CertPem(), ca.KeyPem())if err != nil {log.Fatal(err)}tlsServerConfig := &tls.Config{Certificates: []tls.Certificate{serverCA},}// 创建 带 tls 的tcp服务listener, err := tls.Listen("tcp", fmt.Sprintf(":%d", Port), tlsServerConfig)if err != nil {log.Printf("Error tcp listening on port %d: %v\n", Port, err)return err}fmt.Println("TCP Listening on port ", Port, "; successfully")for {conn, err := listener.Accept()if err != nil {log.Printf("Error accepting connection: %v\n", err)return err}fmt.Println("tcp new connection")// 处理请求go forwardCommunication(conn)}return nil
}func forwardCommunication(conn net.Conn) error {// 首次连接上的时候,通信告诉 tcp server 是客户端连接还是服务端连接bufBytes, err := ReadData(conn)if err != nil {return err}device := &Device{}err = json.Unmarshal(bufBytes, device)if err != nil {log.Printf("Error unmarshalling json: %v\n", err)return err}
}

保存 与 代理服务建立的 grpc service 的连接

func server(deviceID string, conn net.Conn) error {sendData, err := json.Marshal(OK{Code: 1})if err != nil {log.Printf("Error marshalling json: %v\n", err)return err}sendData = append(sendData, '@')_, err = conn.Write(sendData)if err != nil {log.Printf("Error writing to connection: %v\n", err)return err}// 保存 grpc 服务的 dial connectsetConnMap(deviceID, conn)return nil
}

保存 grpc client dial 的连接

client 连接上了的时候告诉 tcp server, 要连接哪个 grpc service
从 保存的conn 中查询是否有 相关的连接
如果有,则 通过 io.Copy 来让grpc client 与 grpc service 通信
func client(deviceID string, conn net.Conn) error {toConn := GetConn(deviceID)successCode := 0if toConn == nil {successCode = -1}sendData, _ := json.Marshal(OK{Code: successCode})_, err := conn.Write(append(sendData, MessageEnd))if err != nil {log.Printf("Error writing to connection: %v\n", err)}if successCode < 0 {conn.Close()return err}go func() {_, err := io.Copy(toConn, conn)if err != nil {log.Printf("client toConn error reading from connection: %v\n", err)}log.Printf("toConn conn closed.\n")return}()go func() {_, err := io.Copy(conn, toConn)if err != nil {log.Printf("client conn error reading from connection: %v\n", err)}log.Printf("conn toConn closed.\n")}()fmt.Println("Client connected to device", deviceID)return nil
}

代码地址

https://github.com/wanmei002/websocket-reverse-proxy

相关文章:

  • 硬引用、软引用、弱引用、虚引用和原子引用
  • 架构风格-系统架构师(十五
  • Pipeline知识小记
  • 复分析——第6章—— Γ 函数和 ζ 函数(E.M. Stein R. Shakarchi)
  • PCL 点云RANSAC+SVD提取平面
  • 一文了解HarmonyOSNEXT发布重点内容
  • ubuntu22.04安装onlyoffice社区版
  • React-配置json-server
  • 认识和使用 Vite 环境变量配置,优化定制化开发体验
  • 鸿蒙NEXT开发中的知识:构建自己的ArkTS应用工程(Stage模型)
  • Redis面试题自测
  • leetcode34:在排序数组中查找元素的第一个和最后一个位置
  • JMeter的基本使用与性能测试,完整入门篇保姆式教程
  • Stable Diffusion 3 大模型文生图“开源英雄”笔记本部署和使用教程,轻松实现AI绘图自由
  • Aidlux 1.4 部署homeassistant core 2024.6实录
  • 10个确保微服务与容器安全的最佳实践
  • 230. Kth Smallest Element in a BST
  • 4. 路由到控制器 - Laravel从零开始教程
  • Bootstrap JS插件Alert源码分析
  • Docker 笔记(1):介绍、镜像、容器及其基本操作
  • ES6 ...操作符
  • gops —— Go 程序诊断分析工具
  • laravel 用artisan创建自己的模板
  • leetcode讲解--894. All Possible Full Binary Trees
  • tab.js分享及浏览器兼容性问题汇总
  • Windows Containers 大冒险: 容器网络
  • 初识 beanstalkd
  • 短视频宝贝=慢?阿里巴巴工程师这样秒开短视频
  • 跨域
  • 老板让我十分钟上手nx-admin
  • 如何胜任知名企业的商业数据分析师?
  • 如何抓住下一波零售风口?看RPA玩转零售自动化
  • 数据科学 第 3 章 11 字符串处理
  • 我感觉这是史上最牛的防sql注入方法类
  • 我有几个粽子,和一个故事
  • 移动端解决方案学习记录
  • 阿里云移动端播放器高级功能介绍
  • 微龛半导体获数千万Pre-A轮融资,投资方为国中创投 ...
  • ​Spring Boot 分片上传文件
  • ​软考-高级-信息系统项目管理师教程 第四版【第14章-项目沟通管理-思维导图】​
  • !! 2.对十份论文和报告中的关于OpenCV和Android NDK开发的总结
  • # Redis 入门到精通(八)-- 服务器配置-redis.conf配置与高级数据类型
  • ###C语言程序设计-----C语言学习(6)#
  • #NOIP 2014# day.1 T3 飞扬的小鸟 bird
  • #常见电池型号介绍 常见电池尺寸是多少【详解】
  • $$$$GB2312-80区位编码表$$$$
  • $.ajax()方法详解
  • $forceUpdate()函数
  • (55)MOS管专题--->(10)MOS管的封装
  • (arch)linux 转换文件编码格式
  • (C语言)输入一个序列,判断是否为奇偶交叉数
  • (delphi11最新学习资料) Object Pascal 学习笔记---第5章第5节(delphi中的指针)
  • (NO.00004)iOS实现打砖块游戏(十二):伸缩自如,我是如意金箍棒(上)!
  • (保姆级教程)Mysql中索引、触发器、存储过程、存储函数的概念、作用,以及如何使用索引、存储过程,代码操作演示
  • (动手学习深度学习)第13章 计算机视觉---图像增广与微调