在日常的开发过程中,本地代码远程调试一直是最理想的开发状态。本文通过介绍京东集团内开发的一个轻量简单的小工具”localhost”,从多角度的方案思考,到原理介绍,到最终的方案落地,在开发阶段发现问题,解决问题。

背景

起源

在很早之前,我参加了一个技术分享大会,当时现场是分享了一个本地在远程集群中的云原生开发方案,当时听完了之后就对其中本地开发的同时可以远程运行服务这部分非常感兴趣,本身作为前端开发来说,确实每次验证一些问题的时候,在本地开发阶段无法在真实的环境中调试,需要本地测试,打包,发版,验证,在处理一些兼容问题的时候,这个过程可能要重复很多次,会浪费很多时间。同时作为赛博云测的开发来说,在云测平台上经常会遇到一些前端开发同学需要调试不同设备的兼容问题,有的甚至顶不住需要线下借设备。云测平台存在的意义的就是能够线上化解决一切移动端的问题,开发的问题也是问题。

痛点

试想这样一个场景,测试同学上报了一个手机页面打开白屏的问题,云测平台上这个手机确实复现了这个问题,你搜索了一些可能的处理方式,然后修改发版验证,发现并没有用,这个时候该怎么办。

或者后端同学提前开发完,发了测试环境给前端同学实时调试接口,需要不停的修改字段或者逻辑或者debug调试问题,这个时候该怎么办。

又或者低代码的开发同学,写完物料组件之后想在实际设备中看看效果,但是不得不单独找设备来看,或者等测试同学报bug,时间都浪费在这个过程中,该怎么办。

我想开发同学或多或少都经历过这些场景,在联调或者调试一些问题的时候,总是没办法做到本地改完代码保存立马就能查看。作为一个工具平台,怎么去解决这个痛点并且能够更好的和平台结合,这个想法就一直在我心里存在着。

思考

从听那场分享会的时候,我就已经在想有什么方案可以实现这个目的,当时分享中说到了云原生开发的本地代码的处理部分,让我没想到的是,他们的方案非常直接,直接到将本地代码“搬”到了远程,实时在本地保存的时候将代码同步到远程的开发容器中,并且为了解决 http 协议传输的时间消耗,自定义了一套协议进行代码的同步,当然这个方案对于我所设想的场景实在是大材小用了,不过真的非常胆大心细,也给我了很多思路。

在后面的时间,借着代码同步的思路,我又设想了云 IDE 这个方案,本身代码同步的目的就是希望本地代码可以在远程运行,那直接通过云 IDE 开发,并直接运行服务,这样运行的服务也是在远程的,可以直接访问。这个思路是没问题的,但是按照目前大家的开发习惯,云 IDE 不是长久之计,况且为了这个想法,开发一套云 IDE,为了一口醋包了一顿饺子,可以,但没必要∠( ᐛ 」∠)_。

之后又和有些同事聊前端开发的问题,聊到了这个想法,给我提供了一个新的思路,通过 whistle 代理和 webpack 插件的方式,webpack 插件以监听模式打包,实时上传编译后的代码到远程服务器,whistle 代理用来解决调试过程中的一些问题。当然这个方案是公司其他的同学在很早之前就已经开发出来了,名字叫 Carefree,不过现在已经不维护了,比较可惜。这个方案只能解决前端开发同学的需求,并且云测平台上我们对代理服务器有些单独的处理,不是很适合。

中间又过了一段时间,我设想了一下这个需求的最终形态,之前的方案都非常重,如果我做为使用者,可能就是在难用和难受之间徘徊(没有说之前方案不好的意思,只是不适合这个需求...),我想它足够的简单和轻量,没有什么环境准备工作,拿来就能用。那最简单的方式就是不在代码上面下功夫,而是转向服务,只要维护好服务上的请求和响应,能够和本地进行交互,就可以达到我想法中所要求的。这个时候,我的想法聚集到了一个方向——内网穿透。

市面上的内网穿透的应用有很多,这又涉及到了另一个问题,安全,如果内网穿透滥用的话,很可能会造成隔离的内网服务被映射到外网从而被攻击,那损失就是把我卖了都赔不了...并且私下使用内网穿透本身也不好控制和追溯,有很大的安全隐患。

纠结了很长时间,既然不让偷偷用,那就光明正大的用,我可以自己实现一个应用,只要限制好功能和安全边界就可以了(已经和安全部门报备过了,放心)。而且自己实现,可以满足自己的所有想法,轻量简单,和云测平台结合等等,没有什么可以比实现自己的想法还令人激动的事情啦。于是便有了下面的内容。

localhost 是什么

介绍

localhost 是一个使用 Go 语言编写的轻量简单的内网穿透工具。这个工具支持 web 服务的映射,会将启动在本地 localhost 中的服务映射到远程服务器上,在访问远程对应的服务时,实际请求会利用本地和远程已经建立的隧道发送到本地服务中,达到访问本地服务的目的。为什么要使用 Go 来写呢,相对于其他的语言,Go 编译简单且编译完没有额外的运行环境要求,本地交叉编译可以得到各类系统的可执行文件,对于使用者来说非常友好。

使用

帮助文档在这里:localhost 帮助文档,可以在帮助文档里或者在赛博云测平台的云真机使用页面内进行工具下载。

就如上面说到的,localhost 是轻量简单的,使用方式非常简单,它是一个独立的可执行文件,启动的参数只有两个,启动方式如下:

# windows
localhost.exe -token xxxxxxxx -port xxxx # mac
localhost -token xxxxxxxx -port xxxx

-token 这个参数是当次使用的 token,可以在赛博云测平台的云真机使用页面上申请,每次的有效期半小时。

-port 这个参数是当前本地启动的服务的端口。

在设计客户端这部分的时候,为了尽可能降低大家的使用门槛,特意将参数设计的尽可能少,port 端口参数是必不可少的,那为什么还设计需要一个 token 参数呢,这个参数的初衷是为了识别用户的身份,类似于 ssh 协议的 key,使得行为可追溯,后来利用 token 来控制使用行为,比如单次使用有效期等等。其他的参数在不影响功能和安全的前提下,都被我排除掉了,希望它使用足够简单。

原理

整体工具分为三个部分:服务端,客户端,web 端。服务端和客户端是进行服务映射的主要部分,包含了建立通道,通道转发之类的逻辑。web 端提供了一些交互的接口,路由聚合代理转发的处理。

核心逻辑

localhost 最核心的部分就是内网穿透,它是由服务端和客户端共同完成实现的。众所周知本地启动的服务,只能本地或局域网内访问到,远程设备无法访问本地服务,但是本地的设备可以访问远程的服务,通过本地访问远程时建立的隧道进行通信,来达到远程设备能够访问本地服务的目的。

整体流程图如下:

首先在服务器中,启动了 web 端部分的服务,是整体服务中的底层服务的调度部分,其中提供了一些 client 端调用的 web 接口以及用户请求时的反向代理等功能,web 端服务是长期运行在远程服务器上,在下面会详细说明这部分做了什么。

client 端会分发给内部同学下载使用,在运行 client 端的时候,client 调用 web 的服务,启动对应的 server 端,并且将相关参数信息传入,并返回给 client 端。

server 端启动的时候,会启动监听两个端口服务,一个是监听用户请求的端口,一个是监听 client 端这边的隧道连接端口,当 client 端主动发起和远程服务器进行连接时,通过当前这个连接打通通信隧道,当用户请求进来时,通过已经建立的通信隧道,将请求报文转发到本地 client 端。

client 端启动完成,并且调用 web 端服务成功返回之后,client 端拿到相关信息连接对应的 server 端,隧道建立成功之后,等待服务端转发过来的请求信息。当监听到请求过来时,client 端会主动连接启动的指定端口的本地服务,并且将请求报文转发给当前的本地服务,同时,响应报文也会通过已有的链路原路返回,最终回到开始的请求方。

通过这种方式,就可以达到远程访问本地服务的目的,通过中转服务器进行服务的穿透,并且这种方式不需要用户关注中间过程,只需要启动提供的 client 端服务,使用简单,基本没有使用成本,不会影响代码。

路由聚合反向代理

使用过程中可能有的同学会有这样一个疑问,在 client 端启动完成之后,会返回显示访问的链接,为什么访问这个链接就可以直接访问到自己本地的服务呢?在 client 端启动时,会调用 web 端的接口服务,这个时候会记录当前的用户身份,并且在启动 server 端时,将启动的 server 端口与当前的用户 erp 形成一个映射关系,并且根据当前这个 erp 建立一个反向代理的规则。在 web 端启动的服务中,有一个监听当前请求的服务,当任何地方访问 web 端的服务时,会对访问的路由进行监听判断,如果能匹配到已有连接的 erp 信息,就会将当前访问请求报文转发到对应的 server 端服务中,然后 server 端再将请求转发到对应的 client 端。

流程图如下:

另外,在通过第一次通过聚合的 erp 路由访问之后,会记录当前访问的 ip,将 ip 与 erp 映射关系也对应上,这样,在后续的访问中,路由可以不用携带 erp 信息,也同样能够映射到当前自己的本地服务,这样可以解决一些静态资源的访问路径的问题,也可以用来解决 history 路由访问的情况。

未来

history路由处理

当前端工程的路由采用的 history 模式的时候,在上述的 erp 聚合的路由就会出现 history 路由访问不对的情况,虽然可以通过第一次访问 erp 路由之后去除 erp 来访问,但是总体来说还是会带来一些困扰,后续计划采用泛域名解析,去除路由上的处理,将用户标识通过域名来解析,路由回归用户原本的样子,这样不会造成额外的困扰和理解上的成本。

支持https

当前 localhost 工具在交互的过程中整体流程上还是 http 协议,目前只能通过把本地工程的 https 配置去除才能使用,但是和有的同学沟通下来发现有的工程中 https 请求是必须的,所以后续将会支持 https,后续设想在访问时只要是 https 的请求,就默认访问本地项目的 https,不需要额外的显式配置或声明。

结束

本地代码的远程之路,在整个过程中经历了很多方向,也产生了很多想法,最终诞生了 localhost 这个工具,在后续的时间会结合更多的场景,继续完善这个工具,希望能够让大家在工作的过程中,多快好省。

作者:京东零售 谢天

来源:京东云开发者社区 转载请注明来源

localhost工具:本地代码的远程之路的更多相关文章

  1. 5000字长文,kurryluo 的自学编程之路

    我是程序员.大众口中非科班的那种,带着高中时期对二进制的恐惧,在大学参加科研比赛后保研,再到和校友一起创业,现在在某大型互联网公司做前端开发,一路走来都是靠自己学习. 前端框架 VUE 的作者尤大说过 ...

  2. 远程之SSH

    SSH(Secure Shell的缩写),由 IETF 的网络工作小组(Network Working Group)所制定:SSH 为建立在应用层和传输层基础上的安全协议.SSH 是目前较可靠,专为远 ...

  3. 平板点餐软件编程体会---记我的Android编程之路

    前言 想开发一个平板点餐系统,研究下陈江根大侠分享的一个很高水准的实例,只是个单机版无实用意义. (如需运行源码请回复联系邮箱) 实现 Mysql 数据库+Tomcat WEb服务器,使用Servle ...

  4. 01-Python的介绍_Python编程之路

    首先用一句业内非常出名的话来介绍Python "人生哭短,我用Python" 这也是Python宣传时经常说的一句话 从这句话中,可以非常清楚Python他到底优点在哪里,为什么要 ...

  5. 07_Python的控制判断循环语句1(if判断,for循环...)_Python编程之路

    Python的数据类型在前几节我们都简单的一一介绍了,接下来我们就要讲到Python的控制判断循环语句 在现实编程中,我们往往要利用计算机帮我们做大量重复计算的工作,在这样的情况下,需要机器能对某个条 ...

  6. PHP并发IO编程之路

    并发IO问题一直是服务器端编程中的技术难题,从最早的同步阻塞直接Fork进程,到Worker进程池/线程池,到现在的异步IO.协程.PHP程序员因为有强大的LAMP框架,对这类底层方面的知识知之甚少, ...

  7. 使用localhost调试本地代码,setcookie无效

    今天在本地调试代码的时候,再域名中使用localhost,结果一直调试不成功,最后发现在登录时,setcookie()没有设置进去 于是发现了,在使用localhost调试时,保存cookie是无效的 ...

  8. 浅谈Service Manager成为Android进程间通信(IPC)机制Binder守护进程之路

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6621566 上一篇文章Android进程间通信 ...

  9. 02-Python的下载和安装_Python编程之路

    原文发布在特克斯博客www.susmote.com 之前给大家讲了关于python的背景知识,还有Python的优点和缺点,相信通过之前的介绍很多人已经清楚自己到底要不要选择学习Python,如果已经 ...

  10. 03-第一个脚本程序以及输入输出_Python编程之路

    上节课已经教大家安装了Python的解释器,那么这节课我们就可以正式来写代码了 说明:在下面的代码演示中,我将大部分使用python交互器演示代码的输入输出,注意">>>& ...

随机推荐

  1. windows访问linux分区文件

    正常情况下,linux可以访问windows系统的文件,而要想在windows下访问linux文件,需要借助第三方软件. 常用的有以下几款: 1.Linux Reader 2.Ext2 IFS 3.E ...

  2. 分布式存储系统举例剖析(elasticsearch,kafka,redis-cluster)

    1. 概述 对于分布式系统,人们首先对现实中的分布式系统进行高层抽象,然后做出各种假设,发展了诸如CAP, FLP 等理论,提出了很多一致性模型,Paxos 是其中最璀璨的明珠.我们对分布式系统的时序 ...

  3. 角度新奇!第一次看到这样使用MyBatis的,看得我一愣一愣的。

    你好呀,我是歪歪. 这期给大家分享一个读者给我分享的一个关于 MyBatis 的"编程小技巧",说真的,这骚操作,直接把我看得一愣一愣的. 我更情愿叫它:坑你没商量之埋雷大法. D ...

  4. nacos适配SqlServer、Oracle

    继上文<nacos适配达梦.瀚高.人大金仓数据库及部分源码探究>后补充nacos适配SqlServer.Oracle的贴码,主要区别是SqlServer.Oracle的分页SQL有点不一样 ...

  5. 使用阿里云ECS和RDS搭建个人博客

    一.ECS实例配置 1.重置云服务器ECS密码 前往ECS控制台,点击实例,找到刚才开通的ECS实例(找不到的话就看一下上方的地区是否是你的服务器的地域),点击右侧操作栏中的三个点,找到重置实例密码, ...

  6. 单节点 RAID6 可靠性模型

    介绍 独立磁盘冗余阵列(Redundant Arrays of Independent Disks, RAID)是存储业界为保证数据可用性.可靠性和完整性所采用的重要技术,即使在分布式多副本如此流行和 ...

  7. Go,从命名开始!Go的关键字和标识符全列表手册和代码示例!

    关注TechLeadCloud,分享互联网架构.云服务技术的全维度知识.作者拥有10+年互联网服务架构.AI产品研发经验.团队管理经验,同济本复旦硕,复旦机器人智能实验室成员,阿里云认证的资深架构师, ...

  8. 使用shuffle sharding增加容错性

    使用shuffle sharding增加容错性 最近在看kubernetes的API Priority and Fairness,它使用shuffle sharding来为请求选择处理队列,以此防止高 ...

  9. 【Python进阶-PyQt5】00搭建PyQt5环境

    1.创建独立开发虚拟环境 1.1虚拟环境简介 我们编写的程序,有时用到的Python库是不一样的,比如说开发桌面应用程序我们主要用到PyQt5相关的Python库.开发Web应用程序我们主要用到Dja ...

  10. Programming abstractions in C阅读笔记:p166-p175

    <Programming Abstractions In C>学习第58天,p166-p175总结. 一.技术总结 1.斐波那契数列(Fibonacci Sequenc) (1)斐波那契数 ...