博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于 Subversion 协议动态代理服务器
阅读量:5946 次
发布时间:2019-06-19

本文共 2667 字,大约阅读时间需要 8 分钟。

  hot3.png

##前言 在2015年下半年的时候,笔者的工作主要转向 GIT@OSC 分布式后端服务器的实现,GIT@OSC 分布式对于不同的接入有有不同的解决方案,HTTP 访问使用 nginx 模块实现动态代理,对于 ssh ,则是使用的端口转发。对于 svn, 早先是不使用分布式解决方案,也就是使用旧式的 NFS 方案,对于分布式来说,这非常的不彻底,NFS 依然是系统的一个瓶颈,并且 svn 服务器的奔溃影响的是所有的用户,某日开会,老大参与后,就问我,能不能实现 svn 协议的代理,我想了想,于是就答应下来,后来就有了 svnsrv 项目,2016 年春节前,svnsrv 作为 GIT@OSC svn 分布式解决方案率先上线,经过多次改进,svnsrv 逐渐稳定,目前已经稳定运行至今,春节期间遇到的访问故障经过分析均不是 svnsrv 的问题,而是后端 sserver 服务器的问题。

OSChina 创立在开源分享的精神之上,我们也将回馈社区。将 svnsrv 剥离核心路由库开源出来,项目地址:

##svnsrv 概览 svnsrv 是基于C++11 开发的 svn 协议动态代理服务器软件,原本运行在 linux 平台,网络框架使用了 Boost.Asio 库,全异步模式,在上线初期,我们曾经使用同步和异步混合的方式使用 Boost.Asio ,那段时间 svnsrv 经常运行若干个小时就无法接受新的连接,后来改成全异步模式就没有这个问题了。核心使用 Boost.Asio 库给移植到 windows 平台带来了便利,春节过后,笔者就将 svnsrv 移植到 Windows 平台了,支持 Visual Studio 2013, Visual Studio 2015, 使用 nuget 工具下载 boost 依赖库,同样也支持 MSYS2 的 Mingw64 编译,不支持 cygwin, 对于 BSD 类系统,daemon 功能是没有实现的。其他功能未测试。开发者可以 fork 改进后发起 Pull Request,实现 svnsrv 对于其他平台的支持和对 svnsrv bug 的修复,功能的改进。

##svn 协议代理实现 笔者曾经写过一篇博客: 在文中曾经介绍了 svn 协议的主要内容,并且提出里 svn 代理服务器的实现思路。svn 客户端连接到服务器时,最先会握手(handshake)交换握手信息,客户端的数据携带了访问的 URL, 我们解析 数据取得 URL 后,然后解析 URL 获得用户名,通过查询路由模块,便可以获得后端的服务器地址和端口,与后端建立连接后,svnsrv 交换两方数据,即实现了 svn 的代理。

svnsrv 使用线程池并发,源码在 SubversionServer, 并发线程数目可以在配置文件中配置。

顺序的操作有如下函数:

echo_downstream_handshake --> read_downstream_handshake -->async_connect_upstream -->read_upstream_handshake -->echo_upstream_handshake

代理的核心函数是这几个:

downstream_readdownstream_writeupstream_readupstream_write

代理功能实现 SubversionSession.cc 源码总共 200多行代码,使用 C++11 智能指针,避免了手动释放内存。

##服务器程序的套路 与 helloworld 显著不同的是,服务器程序通常需要在后台运行,从终端启动后需要脱离终端的掌控,在 posix 系统,可以实现 daemon (守护进程)机制的程序。

一个知识我们得知道,无论是 Linux 还是 Windows , 终端或者命令行启动进程本质上与 C 函数 system 是一致的,system 函数不讨论内部机制如何,启动进程后都将等待进程执行完毕,在 Windows 平台上,subsystem 不是 console 的进程除外( GUI 程序就是如此)。

守护进程的第一步就是让终端认为 进程已经结束,在 posix 平台,使用 fork 后结束父进程,道理就是如此,然后,为了避免子进程成为僵尸进程,让子进程被 init 进程收养就变得很重要,后面的就是修改 stdout stderr stdin 标准输入输出,重定向到特定设备文件,比如 /dev/null。

posix 的 fork 是一种写时复制的进程创建机制,fork 出来的程序会从 紧接着 fork() 调用后面的代码执行,除了 fork() 函数返回值和一些特殊的变量不一样,其他都是一致的。

在 Windows 上,可以使用 Windows 服务,为了避免需要修改更多的代码实现兼容,我在 daemonize 中,先取得 进程的 STARTUPINFO 信息,判断 wShowWindow 是否等于 SW_HIDE 来决定是否结束到进程自身,创建新的进程,在 svnsrv 代码中,调用 daemonize 前没有操作目录,可以直接使用 GetCommandLine 或得自身的 commandline ,将此值传递到 CreateProcess, 调用 CreateProcess 前设置 STARTINFO wShowWindow 的值为 SW_HIDE 即可。启动子进程成功后 使用 ExitProcess(0) 结束自身,这样便实现了 Windows 版的 daemon。

关于命令行的获取, linux 使用 read /proc/pid/cmdline , Windows 中有两种,一个是 MSVC 使用 COM WMI 类 Win32_Process 获得 cmdline, 另一种 Mingw 使用 ZwQueryInformationProcess 读取 特定进程 PEB ,得到 cmdline ,这个有个限制,目标进程和自身的架构得一致,也就是 32位智能读取 32位,64位智能读取 64位。

由于没有实现 BSD 的命令行读取,所以,没有实现 BSD 的 daemon 功能,命令行主要用于重启。

##结尾 svnsrv 也期待其他用户参与进来改进。

转载于:https://my.oschina.net/GIIoOS/blog/617821

你可能感兴趣的文章
在CentOS下,利用FFMPEG对视频进行转码
查看>>
SublimeText3系列(3)- HTML-CSS-JS Prettify美化代码&Markdown Preview写作
查看>>
理解 Redux
查看>>
填一填用了半个月 ionic 遇到的坑
查看>>
[译] 用 Haskell 写简单的 Monadic Parser
查看>>
bling_hash——Node.js 字符串哈希的包
查看>>
谷歌 .dev 顶级域名正式开放
查看>>
Android Q 将获得大量的隐私保护功能
查看>>
Android Volley库源码简析(Image Request部分)
查看>>
Firefox 密码管理器 Lockbox 推出 Android 版
查看>>
视频点播-资源用量
查看>>
好程序员分享大势所趋 HTML5成Web开发者最关心的技术 ...
查看>>
北汽集团荣辉:抓不住自动驾驶 就抓不住车企的命脉 | 自动驾驶这十年 ...
查看>>
豆瓣评分8.8,这本程序员案头必备宝典,10年沉淀,新版再现 ...
查看>>
运行 Spring Boot 应用的 3 种方式!
查看>>
【内容安全】虚拟化及云环境下数据库审计优缺点分析
查看>>
crmeb电商系统
查看>>
xttprep.tmpl
查看>>
mycat垂直分库
查看>>
无需停机,手把手教您将 Docker CE 切换为 Docker EE
查看>>