新起点:从 gRPC 到 Socket 编程

简介: 从 gRPC 到 Socket 编程

前言


就在刚刚,毫不夸张得说:我兴奋到了极点!只想手舞足蹈好好宣泄一下开心的心情。

这要从 49 天前的,我信誓旦旦的跟领导说由我来负责开发一个新版本的数据库资源管理系统说起。


正文


一、技术架构篇


老版本的数据库资源管理系统主要是用 Java 开发的,现在我要用 Go 语言重新实现一个数据库资源管理系统的服务端,React 重新实现一个数据库资源管理系统的客户端。技术不多说了。我面临的大的挑战(或者说是对自己的要求)如下,


  1. 前端摆脱脚手架 create-react-app,要自主搭建基础前端环境,做到完全可控;
  2. 服务端用 Go 语言实现,使实现 Go 语言版的数据库驱动;


二、接收挑战的原因


1.为什么要开发新版本的数据库管理工具?


因为数据库引擎做了破坏性的改动,性能得到了提升,架构也是最新的架构,比起老架构拥有无法比拟的优势,但外围生态不在兼容,数据库管理工具就是其中之一。


2.老版本的数据库管理工具完全不能用了吗?


可以用,但是它是用 GWT 这种古老的 web 框架编写的,如果我去改老工程,可以,而且能适配上新版本的数据库。但本质上就是维护旧项目,然而旧的不去,新的不来。其一,既然创始人的数据库引擎都大刀阔斧的改了,现在由我负责的新版本客户端为什么不能大刀阔斧的改?我相信创始人的神话,我要跟随。其二,我的职业规划相当明确,技术栈发展也是一样。老版本的技术架构和我当前的技术架构出入太大,既然由我负责做,那么在做的同时,我的技术栈一定是要有跟着项目进步的。其三,我原有的前端技术栈,现实告诉我必须抛开脚手架工具,而且之前做的项目里的架构需要优化(之前的架构,在实际开发时遇到坑,我需要沉淀一个更优秀的架构)。


三、挑战如何攻克


1、如何摆脱脚手架 create-react-app ?


在管理系统之前,我就在学 webpack,原因很简单:作为一名合格的前端开发者,必须能高效的定位问题,解决问题,如果一直被像 create-react-app 这种框架保护着,我离工作中遇到的前端问题的关键点就永远隔了一堵墙,破局的关键就是往底层学习。是前端】webpack 安装 是当时记录的一篇文章。


1.webp.jpg

《Webpack 实战》


对于学习,我最钟爱的就是书籍,《Webpack 实战》是我学习 Webpack 真正意义上的起点。技术人最大靠山应该是官方技术文档,但看书学习有个好处就是通俗易懂,我更倾向于以书籍为起点入门,进阶的时候,问题解决不了的时候再去往官方文档靠。官方文档一般是英文的,读起来有障碍,而且是牛津字典的性质,什么都有但内容太多。至于视频教程,我也用看过很多次,讲解的效果确实好,但缺点很明显,一个字:“慢”。


这个月 6 号的时候,随着【前端】webpack 搭建 React 应用环境(二)这篇文章的结束,我已经算是抛开 create-react-app 脚手架了,并且搭建的环境里集成了自己常用的工具,比如 webpack5、typescript、scss、react-router-dom v6、pxtorem、GrapchQL 等等,如今想改哪改哪,完全自由,出现错误,出现问题,定位也更清晰了。算起来解决问题我前前后后用了 4 个多月吧(中途做了别的事就是了,不是专攻这块)。


2、Go 语言版的数据库驱动问题如何解决?


做这块之前,我是经历了一个接纳数据库技术进入自己技术栈的心路历程,《数据库系统概念》是下决心之后,立马开始的学习内容。


26608654-4e8aa790e7154035.webp.jpg

《数据系统概念》


11 月份,我几乎是早上爬起来抱着《数据库系统概念》,晚上睡觉前放下《数据库系统概念》,攻克这本书的原因很简单,我希望自己的技术基础更扎实一点,在理论视野上能站在一定的高度(很多时候我们解决问题的第一步,是弄清楚我们遇到的是什么问题。然而在技术上,遇到问题时,在没什么视野的情况下,我们连 Baidu,连 Google 该搜什么关键词都不知道),降低实践的门槛,以及成功的概率(一般在项目上,都是有截止时间的,如果花费太多时间在基础上,最终能不能完成项目都是问题)。


实践对于一个人的成长具有非常重大的意义,但同时实践的机会难得,为了更高效的实践,基础积累沉淀必不可少。有的人进阶需要实践 5 次,而有的人进阶只需要实践 3 次,这就是成长的速度,实践的效率。


12 月份,了解完数据库基础之后,我开始研究 gRPC,其实这里我的出发点还是选得有点偏差了。因为我之所以选择要研究 gRPC 是因为,我在数据库配置文件里看到了 rpcPort 这个名词,搜索资料之后,知道要往通信上靠。


3.webp.jpg

配置文件


本身用的也是 Go 语言,自然选择了 gRPC 这个技术,《Go 语言编程之旅》是我配套的学习内容。


4.webp.jpg

《Go 语言编程之旅》


随着学习的推进,我了解到 gRPC 是 RPC 的一种实现,属于框架的性质。在最近的日更里,日更内容全是这本书,涉及到关键点 gRPC 的时候,我更加专注,因为 gRPC 是我买这本书的意义所在。随即,接受新的概念、把整个开发环境搭起来,程序跑通。没问题之后,因为兴趣,我还迁移了前端的 gRPC-Web,打通了前后端,非常的开心。


然而正当我在 gRPC 这块告一段落,开始对接数据库时(也就是今天),我倒腾了一天,下午 5 点,我还是没有进展,下面这张图,你是能体会出来一点我面对的是什么的,


5.webp.jpg

WireShark 抓包逐字节分析


现在的程序员写的代码,一般很难看出什么黑客的感觉了,但是当这次接触这么多 01010111 的时候,我想起这似乎是很多很多年前脑海里的程序员会做的事。


配合数据库服务端源码,我的 Go 客户端代码,两边同时开启 Debug,中间使用 WireShark 抓取 TCP 数据包分析。我发现我传输的数据,老是多了些内容,网络请求到达数据库服务端的时候老是识别不出来我的网络请求是做啥的。


Unsupported request type code: 17257061
java.io.IOException: Unsupported request type code: 17257061
    at com.cloudwave.server.federation.zone.ZoneServerReceiver.completeRequest(ZoneServerReceiver.java:1240)
    at com.cloudwave.server.federation.zone.ZoneServerReceiver.completeRequest(ZoneServerReceiver.java:48)
    at com.cloudwave.server.net.ServerReceiver.run(ServerReceiver.java:176)
    at com.cloudwave.server.net.ServerReactor.dispatch(ServerReactor.java:97)
    at com.cloudwave.server.net.ServerReactor.run(ServerReactor.java:73)
    at com.cloudwave.server.master.MasterServer$1.run(MasterServer.java:1085)
    at java.lang.Thread.run(Thread.java:748)


抓包分析到,我发送的数据里多了一串内容,郁闷至极:“多的这是啥玩意?”


6.webp.jpg


后来我 Baidu、Google,如何在发起 RPC 网络请求时不带 ServiceName,我从 gRPC 开始转移到 RPC,开始觉察到是 gRPC 框架搞得鬼。结果进一步 DeBug 另一个 Go 驱动(数据库资源管理工具立项以来,我另一个同事按照 MySQL 驱动开发的基础版,我要做的数据库驱动是处理那些数据库通用驱动不能支持的功能)才发现,里面根本没看到啥 RPC。只有下面这些什么 SysCall,感觉像是更基础的系统级网络调用。


// Implemented in ../runtime/syscall_windows.go.
func Syscall(trap, nargs, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
func Syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
func Syscall9(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno)
func Syscall12(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 uintptr) (r1, r2 uintptr, err Errno)
func Syscall15(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2 uintptr, err Errno)
func Syscall18(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18 uintptr) (r1, r2 uintptr, err Errno)
func loadlibrary(filename *uint16) (handle uintptr, err Errno)
func loadsystemlibrary(filename *uint16, absoluteFilepath *uint16) (handle uintptr, err Errno)
func getprocaddress(handle uintptr, procname *uint8) (proc uintptr, err Errno)
// A DLL implements access to a single DLL.
type DLL struct {
    Name   string
    Handle Handle
}


再紧跟着分析数据库服务端源码,最终发现,整个数据库服务端和客户端交互的技术就是纯粹的 Socket,没有任何封装。至此,一切云雾皆散去,我要使用的技术其实只是如何发送接收普通的 tcp 请求。最后代码只有一页,总共 78 行。看结果,


7.webp.jpg

服务端实时数据


8.webp.jpg

客户端实时数据


经过数据比对,完全一致,数据库服务端与 Go 客户端通信连接成功,终于跨出了这一步,万事开头难。我在解决这个问题之前,其实我选的方向稍微就有点偏差,最终没有 gRPC 华丽出手的机会,但也很正常,没人指导,能独自解决问题就已经很棒了!(这是对自己的认可)。而且也算是无心插柳柳成荫,我新获得了 gRPC 这项技术,而且通过反复的发现问题,解决问题的过程,我对底层的理解更清晰了。(以前遇到010101111 这种字节级别的代码,我都是直接跳过不看的,太难了)


9.webp.jpg

日志校验也显示成功


四、一些感想


明天约了一个领导,昨晚休息的比较晚,我白天也不习惯睡觉,准备今晚早点休息的,可实在兴奋难以言表,要做一次及时地复盘,毕竟顺利抵达今天这一步,其实我前前后后算是准备了四个多月。其间也是踏踏实实,重积累。

一幅完美的画,可能从动笔到画成只需要三天,但背后执笔的人可能练习了三十年。

我更加坚定自己对于成长的理解。

再次想起王国维在《人间词话》里描述的人生三境界之其二:“衣带渐宽终不悔,为伊消得人憔悴”。


目录
相关文章
|
缓存 监控 Java
Java Socket编程最佳实践:优化客户端-服务器通信性能
【6月更文挑战第21天】Java Socket编程优化涉及识别性能瓶颈,如网络延迟和CPU计算。使用非阻塞I/O(NIO)和多路复用技术提升并发处理能力,减少线程上下文切换。缓存利用可减少I/O操作,异步I/O(AIO)进一步提高效率。持续监控系统性能是关键。通过实践这些策略,开发者能构建高效稳定的通信系统。
466 1
|
Java
Java Socket编程与多线程:提升客户端-服务器通信的并发性能
【6月更文挑战第21天】Java网络编程中,Socket结合多线程提升并发性能,服务器对每个客户端连接启动新线程处理,如示例所示,实现每个客户端的独立操作。多线程利用多核处理器能力,避免串行等待,提升响应速度。防止死锁需减少共享资源,统一锁定顺序,使用超时和重试策略。使用synchronized、ReentrantLock等维持数据一致性。多线程带来性能提升的同时,也伴随复杂性和挑战。
403 0
|
安全 Java 网络安全
Java Socket编程教程:构建安全可靠的客户端-服务器通信
【6月更文挑战第21天】构建安全的Java Socket通信涉及SSL/TLS加密、异常处理和重连策略。示例中,`SecureServer`使用SSLServerSocketFactory创建加密连接,而`ReliableClient`展示异常捕获与自动重连。理解安全意识,如防数据截获和中间人攻击,是首要步骤。通过良好的编程实践,确保网络应用在复杂环境中稳定且安全。
323 0
|
网络协议 测试技术 网络安全
Python编程-Socket网络编程
Python编程-Socket网络编程
163 0
|
网络协议 开发者 Python
深度探索Python Socket编程:从理论到实践,进阶篇带你领略网络编程的魅力!
【7月更文挑战第25天】在网络编程中, Python Socket编程因灵活性强而广受青睐。本文采用问答形式深入探讨其进阶技巧。**问题一**: Socket编程基于TCP/IP,通过创建Socket对象实现通信,支持客户端和服务器间的数据交换。**问题二**: 提升并发处理能力的方法包括多线程(适用于I/O密集型任务)、多进程(绕过GIL限制)和异步IO(asyncio)。**问题三**: 提供了一个使用asyncio库实现的异步Socket服务器示例,展示如何接收及响应客户端消息。通过这些内容,希望能激发读者对网络编程的兴趣并引导进一步探索。
220 4
|
开发者 Python
Python Socket编程:不只是基础,更有进阶秘籍,让你的网络应用飞起来!
【7月更文挑战第25天】在网络应用蓬勃发展的数字时代,Python凭借其简洁的语法和强大的库支持成为开发高效应用的首选。本文通过实时聊天室案例,介绍了Python Socket编程的基础与进阶技巧,包括服务器与客户端的建立、数据交换等基础篇内容,以及使用多线程和异步IO提升性能的进阶篇。基础示例展示了服务器端监听连接请求、接收转发消息,客户端连接服务器并收发消息的过程。进阶部分讨论了如何利用Python的`threading`模块和`asyncio`库来处理多客户端连接,提高应用的并发处理能力和响应速度。掌握这些技能,能使开发者在网络编程领域更加游刃有余,构建出高性能的应用程序。
151 3
|
网络协议 Python
网络世界的建筑师:Python Socket编程基础与进阶,构建你的网络帝国!
【7月更文挑战第26天】在网络的数字宇宙中,Python Socket编程是开启网络世界大门的钥匙。本指南将引领你从基础到实战,成为网络世界的建筑师。
221 2
|
消息中间件 网络协议 网络安全
Python Socket编程:打造你的专属网络通道,基础篇与进阶篇一网打尽!
【7月更文挑战第26天】在网络编程领域,Python以简洁语法和强大库支持成为构建应用的首选。Socket编程为核心,实现计算机间的数据交换。
218 1
|
网络协议 安全 Java
Java中的网络编程:Socket编程详解
Java中的网络编程:Socket编程详解