微服务开源Benchmark系统TrainTicket V10隆重发布
12个月过去了,TrainTicket迎来第一次大版本更新,是否好奇TrainTicket到底做了哪些升级呢?快来看看TrainTicket究竟发生了什么样的变化吧!
可能还有小伙伴对TrainTicket感到陌生,首先让我们对TrainTicket做一个简单的介绍吧: TrainTicket是复旦大学CodeWisdom团队以12306订票业务为蓝本所开发的一个开源微服务基准系统。 自2017年正式开源以来,TrainTicket已在学术界和工业界得到了广泛应用! 作为一个中等规模的微服务Benchmark系统,TrainTicket包含40+个业务微服务,此外,还包括消息中间件服务、分布式缓存服务和数据库服务等基础服务,总的微服务数量达到了70多个!
除去可观的规模,TrainTicket还拥有丰富的生态! TrainTicket采用Java、Go、Python、Node.js等多种语言进行开发,还支持常见的微服务部署方式,例如Docker Compose、Kubernetes等。同时TrainTicket还支持使用Jaeger、Zipkin、Prometheus等可视化监控工具对服务进行监控和管理。
作为开源微服务Benchmark系统,TrainTicket一直致力于为微服务研究者和实践者提供一个贴近企业开发实践的参考系统实现 。在此前的版本中,我们也以此为目标,为TrainTicket带来了许多升级,分别实现了基本业务服务、UI界面优化、代码逻辑和质量重构,同时还在持续引入新技术和新方法。而这一次,我们又进一步以微服务企业开发实践为指引为大家带来了一次全新的主版本升级。
屏幕前的你一定在好奇:这次TrainTicket的大版本升级究竟包含了哪些内容呢? 这一次,我们分别从设计,实现,测试,治理,运维等软件工程的全流程对TrainTicket进行了重构更新。 总的来说,升级包含了以下内容:
系统重构 ,重新统一设计数据结构及服务间的调用关系,对Spring-Boot框架版本进行升级,对所有微服务的依赖进行升级及梳理,日志格式标准化,代码逻辑简化,已知缺陷修复,新增业务服务;全新的自动化测试脚本 ,可按场景进行功能测试及性能测试;多样的服务治理组件 ,添加了服务注册发现,微服务网关及流量控制的服务治理组件;全面的运维保障工具 ,增加了监控和分布式追踪的运维保障组件的支持。接下来,大家就一起来详细看看本次TrainTicket升级内容的细节吧~
1. 系统重构
1.1 全新架构
首先是升级后的TrainTicket的全新架构图!图里展示了TrainTicket中的服务、服务间调用关系以及所支持的各种治理和运维组件。黄色的服务表示了需要连接数据库的服务,而白色服务则只有网络调用不涉及数据库数据的直接读写。

1.2 数据结构重构
之前版本的TrainTicket在每一个服务中都维护一份自己使用到的数据结构的定义,数据结构的更新和统一非常困难。此次更新,我们将所有微服务架构公用的数据结构统一提取出来放至ts-common模块,并对数据结构的字段进行了统一更改,各微服务仅需维护自己服务数据库数据相关的数据结构。这样一来,各服务维护数据的成本大幅度降低,还保持了数据的一致性。
如下图的例子中,微服务preserve因为不需要连接数据库,因此根本不需要在代码中维护数据结构,直接引用ts-common中的定义即可,而其他需要连接数据库的服务(例如travel),也仅仅需要维护自己数据相关的数据定义即可。

1.3 数据库类型变更
因为TrainTicket的业务属性,各种数据结构之间关系联系紧密,因此新版本也为数据库带来了全面的升级:数据库不再是从前的MongoDB,而是全面升级为了关系型数据库MySQL!
不仅如此,我们还为TrainTicket采用了集群模式。数据库的稳定是一个服务系统稳定的基础。采用集群模式的MySQL可以保证数据的稳定高可用运行,为整个微服务系统的稳定性打下坚固的基础。
集群模式部署的MySQL包含两种角色,主数据库和从数据库,在集群中主数据库遇到故障崩溃时,其余的从数据库节点可以很快通过raft协议进行选举,选举出一个新的主节点,从而保证业务的不间断运行。
1.4 整体 框架及依赖升级
TrainTicket之前版本Spring-Boot框架一直保持在1.5.22RELEASE版本。此次更新,我们将spring-boot框架更新至2.3.12RELEASE版本,解决了多种依赖冲突问题,使得TrainTicket更加容易加入新功能使用新特性。方便使用人员进行二次开发!

1.5 服务 配置动态化
此前TrainTicket每个服务的数据库配置是以硬编码的形式写在服务的application.yaml文件中,对其他服务的调用也是硬编码形式写在代码中。此次更新使用Nacos服务发现解决了对其他服务调用时的配置问题,数据库配置也通过环境变量的形式对服务进行动态配置。

1.6 日志标准化
日志分析是软件工程领域重要的研究话题,在TrainTicket先前的版本中,每个服务的日志写法各异,没有形成统一的格式。此次更新中对每个服务中的日志都进行了标准化处理,日志文本使用‘[ ]’分隔不同内容,方便模板抽取或对特定字段进行监控。具体的日志规则如下:
• 关于 调用链调用失败、返回状态码错误、希望修改的资源不存在等情况引起的失败,采用Error级别的日志:格式为【函数名】【动作信息】【错误原因信息&错误堆栈信息】【资源信息(如果有,一般指变量或者执行动作)】
• 关于 新增对象已经存在、由于业务限制无法做出资源修改操作、获取资源但是资源为空的情况,采用Warn级别的日志: 格式为 【函数名】【动作信息】【自然语言原因信息】【资源信息(如果有)】
• 关于 正常业务行为等,使用Info 级别的日志,避免大量无意义日志
• Debug 级别的日志的格式标准同Info级别的日志,同时尽量少使用Debug 级别的日志
下图是更新前后的日志语句对比:

1.7 代码 优化及服务添加
对TrainTicket部分设计不合理之处进行优化。如:对travel服务多次循环调用route服务的相关逻辑进行更新,解决了travel服务与seat服务的循环调用问题。修复了一些已知缺陷。在服务级别,删除了此前只用于转发的ticket-info服务,将原有的food-map服务拆分为train-food和station-food两个服务,并增加了车票候补和站内食物配送服务。
2. 自动化测试脚本
为了支持大家更方便的使用TrainTicket进行实验。本次更新提供了自动化测试脚本用来进行TrainTicket的功能测试和性能测试。测试脚本提供了管理员操作,正常查询订票,重新预定,重新预定失败,搜索失败,带行李预定等业务场景。同时脚本支持QPS参数设置,可以轻松实现性能测试及实验数据生成。
脚本地址: https://github.com/FudanSELab/train-ticket-auto-query/tree/autoQuery。
如下图的例子中,是使用脚本对正常查询订票场景进行性能测试的结果:

3. 服务治理组件
3.1 服务注册和发现及负载均衡机制:Nacos+restTemplate
动态服务发现对以服务为中心的(例如微服务和云原生)应用架构方式非常关键。TrainTicket之前的版本使用Kubernetes的Service机制进行服务注册发现,其不足之处是只能根据Kubernetes Service获取到服务实例的Host, 而无法获取其Port, 因此每个服务的Port信息只能通过硬编码或者配置的形式让其他的服务知晓。本次更新针对这个问题增加了服务注册、发现组件Nacos。
使用 Nacos 可以简化服务发现、配置管理、服务治理及管理,让微服务的发现、管理、共享、组合更加容易。而且目前Nacos已经支持Spring Cloud生态,使用起来非常方便。同时TrainTicket使用restTemplate的@LoadBalanced注解负载均衡的 实现 。
3.2 网关:Spring-Cloud-Gateway
微服务网关是微服务架构中的一个关键的角色,用来保护、增强和控制对于微服务的访问,微服务网关是一个处于应用程序或服务之前的组件,这样微服务就会被微服务网关保护起来,对所有的调用者透明。例如在前端上进行展示的时候,我们通常需要在一个界面上展示很多数据,这些数据大多数来自于不同的微服务中。因此使用微服务网关可以使得前端只需要调用网关服务的接口而不需要了解每个微服务的具体接口。其次,微服务可以用来进行统一的管理授权、访问控制和流量限制等功能,对微服务的治理至关重要。
本次更新增加了微服务网关组件,使用Spring-Cloud-Gateway实现了网关功能。并在网关上集成了Sentinel进行流量管理功能。
3.3 流量控制机制:Sentinel
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。同时Sentinel支持对Spring-Cloud-Gateway进行限流。
4. 运维保障工具
4.1 监控机制:Prometheus+Grafana
指标作为微服务系统监控的重要组成部分,本次更新添加了Prometheus监控组件在Kubenetes环境中的一键部署支持,并支持主机、Pod、容器等不同级别的监控指标。使用者可以通过Grafana看板查看整个TrainTicket的各种监控指标信息。
4.2 分布式追踪:SkyWalking + ElasticSearch
分布式追踪可以支撑微服务系统中业务理解、故障定位等应用,本次更新添加了SkyWalking + ElasticSearch在Kubenetes环境中的一键部署,同时支持带有SkyWalking Agent的服务部署版本。
登录SkyWalking UI界面可以收集和查看整个微服务系统的trace信息,进行错误排查:

还没抢到票吗?实测两款 GitHub 开源抢票插件,所有坑我们都帮你踩过了
优质文章,及时送达

晓查 郭一璞 发自 凹非寺
量子位 报道 | 公众号 QbitAI
今天,已经可以抢过完年回来的火车票了。

如果你对自己手速和市面上的各种“加速包”都没什么信心的话,不妨试试用程序员的手段抢票?
况且,12306官方宣布屏蔽了一大批付费抢票软件,这也意味着你即使给这些软件付了会员费,也依旧抢不到票。
所以只能回到最初的手动抢票?No!No!No!
GitHub上有两个“年经”项目,每到春运前一段时间,就会定时定点的登顶热榜,助力一代又一代程序员和姿势丰富的非程序员们抢票回家。

那么,这两个项目究竟怎么用?好不好用?
和手动抢票、第三方软件抢票比起来优势是否明显?
安装使用过程中,会不会遇到不可名状的bug?
今天为大家一一横评。
霸占热榜的两个项目
排在GitHub热榜第1的项目名字简单粗暴,就直接叫12306 ,已经有21300星,来自ID为testerSunshine的作者。
testerSunshine的12306项目可以自动登录用户账户,能卡点抢票,也能捡漏候补,抢到票后会通过邮件进行通知。
排在热榜第2位的,叫做py12306 ,目前已有8300星,今年初就已经非常火了。
我该选哪个抢票软件
那么整体来看,这两款开源软件,哪个更好用呢?
py12306从去年开始就已经被大家广泛使用,其优点是设置比较简洁,甚至还有图形界面。但是它在验证码登录过程中容易出现下载失败的情况,如果把打码接口从free换成“若快”平台,还需要充值。

如果你对运行代码一无所知,建议使用py12306.
testerSunshine的12306插件设置比较复杂,自动获取cookie经常失败,因此需要手动填写,这一点比不上py12306;但是它自带了开发者的12306图片识别模型,我们可以在本地完成图片识别码的登录过程。
从实际使用效果来看,我们更推荐testerSunshine的12306,目前它在GitHub上的高人气,也反映的用户们的选择。
测评细节&使用教程
两个抢票插件的关键都在配置文件的修改:testerSunshine/12306的关键在于TickerConfig.py,而py12306的关键在于env.py。
热榜第一:12306
我们先开始测试现在趋势榜第一的12306,先将项目复制到本地:
git clone https://github.com/testerSunshine/12306cd 12306
再安装依赖项,为了避免多python环境产生问题,建议以root用户方式安装:
pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt
下面到了整个过程最关键 的环节,配置TickerConfig.py文件,这一步将决定你的成败!非常重要!
看到配置文件里一长串字符,你是不是觉得很头疼呢?我们经过测试,找到了其中的几个关键点:
1、如果你没有抢到票,寄希望于其他人退票后捡漏,令TICKET_TYPE = 2,否则设置为1;
# 刷票模式:1=刷票 2=候补+刷票TICKET_TYPE = 1
2、STATION_TRAINS 可以填入一串你想要抢的车次,比如北京到合肥方向,你想购买G267、G29次列车,就设置为STATION_TRAINS = [“G267”, “G29”],中间用逗号隔开,不填写等于抢当日全部车次;
# 出发日期(list) "2018-01-06", "2018-01-07"STATION_DATES = ["2020-01-30"]# 填入需要购买的车次(list),"G1353"# 修改车次填入规则,注:(以前设置的车次逻辑不变),如果车次填入为空,那么就是当日乘车所有车次都纳入筛选返回# 不填车次是整个list为空才算,如果不是为空,依然会判断车次的,这种是错误的写法 [""], 正确的写法 STATION_TRAINS = ["G267","G29"]
3、STATION_DATES 填入你出发的日期,这一步不难;
4、出发站FROM_STATION和到达站TO_STATION不必精确到具体的站,只需填入城市,除非你想从特定站点出发;
# 出发城市,比如深圳北,就填深圳就搜得到FROM_STATION = "北京"# 到达城市 比如深圳北,就填深圳就搜得到TO_STATION = "合肥"
5、乘车人填入你12306账号中常用联系人的姓名,比如TICKET_PEOPLES = [“张三”],如果没有,需要登录12306手动添加;
# 乘车人(list) 多个乘车人ex:# "张三",# "李四"TICKET_PEOPLES = ["李雷","韩梅梅"]
6、填入你的12306账户名和密码;
# 12306登录账号USER = "Lilei"PWD = "123456"
7、如果不需要邮箱和Server酱提醒,请把EMAIL_CONF和SERVER_CHAN_CONF的第一项都设置为False;
8、开放抢票时间根据自己车次填入,可以提前几秒,比如下午一点开发抢票,则填入OPEN_TIME = “12:29:57” ;
# 预售放票时间, 如果是捡漏模式,可以忽略此操作OPEN_TIME = "12:29:57"
9、cookie设置这一步尤为关键,经过我们实测,COOKIE_TYPE设置为1或2都有些问题,建议设置为3;
# 1=使用selenium获取devicesID# 2=使用网页端/otn/HttpZF/logdevice获取devicesId,这个接口的算法目前可能有点问题,如果登录一直302的请改为配置1# 3=自己打开浏览器在headers-Cookies中抓取RAIL_DEVICEID和RAIL_EXPIRATION,这个就不用配置seleniumCOOKIE_TYPE = 3
10、上一步设置为3以后,还需要手动设置后面的两个参数RAIL_EXPIRATION 和RAIL_DEVICEID 。
# 如果COOKIE_TYPE=3, 则需配置RAIL_EXPIRATION、RAIL_DEVICEID的值RAIL_EXPIRATION = "1577327361278"RAIL_DEVICEID = "jFAKbAeAInPnm0pAdqdCNG0ID_dU6SW6L8gaX7zDEewcWVJC5w7nTSw63oMK9sd9c6FcdhyDMsuVUV4aknfXwzHhO8c_Z-nLU4W8F4_gj_HlrOrsrR29U82HR4pnMRqoRFBKuCZ3tKAgQrhuYnR5RWsBCe5g7goV"# RAIL_EXPIRATION = "1577034103293"# RAIL_DEVICEID = "CDno29Erc_Pf3FSXb4dzq-Op64EhWrsi5yUZKVIKR1MAfYo2qFlCeXD8VkexY7_1qg-ClV-fE8j9jgVlPZxRh3wVc2iqLe_5A8sdr62qZx4B22JPF8lFCjpgTKZ5ODW90HJd5tiQsJ1KR9nOqHRxHj1FT5LEIwfw"
如何找到这两个参数?先用Chrome浏览器打开12306.cn,点击网站地址左边的“锁形”图标:再点击下发的Cookie

接着会出现一组Cookie,选择来自12306.cn的Cookie:

看到RAIL_EXPIRATION 和RAIL_DEVICEID 两个参数,点击它,将内容里的一串字符复制到配置文件中。

需要注意的是RAIL_DEVICEID参数很长,可能显示不全,请完整复制。
至此,准备工作已全部完成,启动前请先筛选cdn,这点很重要!
python3 run.py c
接着启动服务:
python3 run.py r
接着它会提出登录成功,并列出当日所有相关车次信息,然后开始抢票:

抢票成功后,这个软件不能帮你完成支付,你还需要在手机或者电脑上登录12306网站,在30分钟内完成支付动作,否则你辛辛苦苦抢的票就没了。

热榜第二:py12306
py12306的安装方式与前者类似:
git clone https://github.com/pjialin/py12306cd py12306pip3 install -r requirements.txt
然后修改配置文件,现更改后缀名
cp env.py.example env.py
默认配置文件中需要修改的选项有:
1、你的12306账户和密码;
# 12306 账号USER_ACCOUNTS = [# 目前已支持仅查询,不下单,屏蔽掉下面的账号即可{'key': 'lilei', # 如使用多个账号 key 不能重复'user_name': 'Lilei','password': '123456'},
2、查询任务QUERY_JOBS中的各项参数,包括出发日期left_dates、出发站left和到达站arrive、乘客姓名members、坐席seats、车次train_numbers;
# 查询任务QUERY_JOBS = [{# 'job_name': 'bj -> yl', # 任务名称,不填默认会以车站名命名,不可重复'account_key': 0, # 将会使用指定账号下单'left_dates': [ # 出发日期 :Array"2020-01-22",],'stations': { # 车站 支持多个车站同时查询 :Dict or :List'left': '北京','arrive': '合肥',},'members': [ # 乘客姓名,会根据当前账号自动识别乘客类型 购买儿童票 设置两个相同的姓名即可,程序会自动识别 如 ['张三', '张三']"李雷","韩梅梅"#在姓名前加*表示学生购买成人票# 7, # 支持通过序号确定唯一乘客,序号查看可通过 python main.py -t 登录成功之后在 runtime/user/ 下找到对应的 用户名_passengers.json 文件,找到对应的 code 填入],'allow_less_member': 0, # 是否允许余票不足时提交部分乘客'seats': [ # 筛选座位 有先后顺序 :Array# 可用值: 特等座, 商务座, 一等座, 二等座, 软卧, 硬卧, 动卧, 软座, 硬座, 无座'二等座'],'train_numbers': [ # 筛选车次 可以为空,为空则所有车次都可以提交 如 [] 注意大小写需要保持一致"G267",],'except_train_numbers': [ # 筛选车次,排除车次 train_numbers 和 except_train_numbers 不可同时存在],'period': { # 筛选时间'from': '00:00','to': '24:00'}},
接着运行程序:
python3 main.py
如果你不善于使用命令行模式,还可以使用图形界面观察抢票任务。
将配置中的WEB_ENABLE打开,启动程序后访问当前主机地址+端口号 (默认 8008) 即可,然后在浏览器中输入http://127.0.0.1:8008。

现在,就可以让程序帮你抢票啦。
不过,抢票软件并非万能,巧coder难为无票之炊,除了技术,你可能还需要一点点运气。
无论采取哪种交通方式,祝大家都能开开心心过年回家,平平安安回来搬砖~
2020已经开始,量子位也祝大家新年快乐^_^
传送门
testerSunshine/12306
https://github.com/testerSunshine/12306
py12306
https://github.com/pjialin/py12306
- END -
相关问答
海报制作一般用什么软件?海报制作哪个软件好-ZOL问答
对于海报制作,常用的软件有AdobePhotoshop、GIMP和Paint.NET等。这些软件都提供了丰富的编辑功能和设计模板,可以满足不同用户的需求。在选择海报制作软件时...