Skip to content

nai6514531/wx-pms

Folders and files

NameName
Last commit message
Last commit date

Latest commit

f22b4f3 · Jul 6, 2020

History

6 Commits
Jul 5, 2020
Jul 6, 2020
Jul 6, 2020
Jul 6, 2020
Jul 6, 2020
Jul 6, 2020
Jul 3, 2020
Jul 6, 2020
Jul 6, 2020
Jul 3, 2020
Jul 6, 2020
Jul 1, 2020
Jul 5, 2020
Jul 1, 2020
Jul 3, 2020

Repository files navigation

问题

终端扣费管理系统·设计:

  • 实现一个扣费服务管理系统的客户端和服务端。
  • 拥有查看服务列表,开通扣费服务,关闭扣费服务,新增扣费服务等功能。
  • C++gRPC 实现,Bazel 编译管理依赖,考虑数据、传输等安全。

设计

组件和模块

分二个模块:

1)客户端,发送操作请求(获取扣费服务列表,新增扣费服务,开通扣费服务,关闭扣费服务)。

2)服务端,接收和处理客户端的请求。

其中客户端与服务端交互有:

  • 获取正常状态的扣费服务列表(getlist)
  • 获取已失效状态的扣费服务列表(getexpiredlist)
  • 开通扣费服务(open {"id":1})
  • 关闭扣费服务(close {"id":1})
  • 新增扣费服务记录(create {"title":"深圳市地铁微信免密支付","desc":"深圳市地铁相关运营主体"})

数据流

用户与 client 端交互时,采用 命令 JSON包体 的格式,client 解析 JSON 包体并转为 protobuf 格式, clientserver 交互采用 grpc/protobufserver端再与 mysql 进行通信;

client 收到 server 返回,做了转 JSON 输出,方便查看。

接口和协议

DeductionResp 的一些说明:

  • success 表示服务端处理是否成功
  • message 消息提示信息
  • code 返回码,定义了系统异常的枚举
  • data 服务端返回的数据结构体

详细 proto 设计可见 ./apis/protocol/v1/deduction.proto

错误码和结构体等定义

相关的有 消息提示信息,返回码 定义都在 ./apps/utils/enum.hpp 中。

库表设计

共一张表:

  • deduction 用户的扣费服务列表,对应接口的增加,修改,查询都是操作这张表。

详细的数据表的 schema 可见 ./confs/deduction.sql

安全性

由于时间原因,并没有设计传输安全相关的操作,但是有调研这方面的技术实现。

  • 开启 gRPCsecure credentials,添加证书操作可参考示例
  • 用户输入校验。对每个具体字段的长度,大小,格式等,也包括sql注入,这里没有做校验。
  • 对于水平越权以及垂直越权的校验。

代码组织

apis 目录下定义的是proto相关的内容, proto 文件通过 protoc 工具链来生成(build_proto.sh),并且将生成的代码文件一起上库,这样操作主要是考虑到协议变更不频繁,客户端和服务端可以共用一份协议文件。

apps 目录下,utils3rd 为公用依赖。

执行文件的 main 入口文件直接置于 apps 下,如当前 client.cc, server.cc。由于目前接口不多并且时间也比较紧张,所以也将具体执行类和 main 置于同一文件中。随着接口和逻辑复杂性的提高,应单独提取出执行类到具体的业务目录下。

.
├── Makefile                          # 对 bazel 构建和清理等命令的简单包装
├── README.md                         # 本文档
├── WORKSPACE                         # bazel 的 workspace
├── apis                              # proto 协议和其生成文件目录
│   ├── BUILD                         # apis 的 build 文件,供 apps 依赖
│   ├── cpp                           # 以下是根据协议生成的 cpp 代码
│   │   └── protocol
│   │       └── v1
│   │           ├── deduction.grpc.pb.cc
│   │           ├── deduction.grpc.pb.h
│   │           ├── deduction.pb.cc
│   │           └── deduction.pb.h
│   └── protocol                      # 协议目录,按版本分
│       └── v1                        # v1 为实验中用到的 proto
│           └── deduction.proto
├── apps                              # 服务代码主目录
│   ├── 3rd                           # 三方依赖,由于多是单文件,所以放在一起
│   │   ├── bin2ascii.hpp             #    十六进制和字符串间的转换
│   │   ├── json.hpp                  #    json 处理相关
│   │   ├── md5.cc                    #    md5
│   │   ├── md5.hpp             
│   │   └── sql                       #    mysqlplus第三方库
│   │       ├── mysqlplus.h
│   │       └── (sub dirs omitted)
│   ├── BUILD                         # 服务端 build 文件,依赖了 apis 的build
│   ├── client.cc               # client app的主逻辑
│   ├── server.cc               # server app的主逻辑
│   └── utils                         # 工具箱
│       ├── config.cc                 # 定义获取配置文件的类
│       ├── config.hpp
│       ├── strings.cc                # 常用字符串处理函数
│       ├── strings.hpp
│       └── enum.hpp                  # 枚举相关定义
├── build_proto.sh                    # proto 文件处理脚本
├── confs                             # 配置
│   ├── deduction.sql                 # 库表结构
│   └── server.json                   # server 配置
└── mysql.BUILD                       # mysql的build,依赖处理

编译

本地环境

MacOS Mojave 10.14.5

gcc version 6.5.0

Bazel: 3.3.0

对编译做了个简单的 Makefile 包装:

proto:
	./build-proto.sh

apis:
	bazel build //apis:all

apps:
	bazel build -c dbg --spawn_strategy=standalone --cxxopt='-std=c++17' //apps:all

all: proto apis build

clean:
	rm -rf ./apis/cpp/*
	rm -f *.log
	bazel clean
  • make proto: 用于生成c++版本的proto。
  • make apis: 构建接口的依赖。
  • make apps: 构建app的依赖。
  • 用户需要在项目目录下运行make all,启动客户端执行./bazel-bin/apps/client,启动服务端执行./bazel-bin/apps/server。

三方依赖

设计上尽量减少依赖或尽量使用轻量级依赖。除了gRPCprotobuf,还有以下依赖:

  • JSON , 对自定义结构体的序列化和反序列化处理非常方便(自定义 to_jsonfrom_json

  • mysql modern cpp MySQL 包装。

操作

首先需要配置对应的数据库和服务器,配置可见 confs 目录。对配置文件的说明如下:

配置里的对象全部可以 JSON 对象序列化和反序列化,关联的 JSON 字段见 config.hpp

{
  // server 配置
  "server": {
      "endpoint": "127.0.0.1:50051"
  },
  // 数据库配置
  "db": {
      "server": "127.0.0.1",
      "port": 3306,
      "username": "root",
      "password": "password",
      "dbname": "payment"
  }
}

对客户端操作的命令: 执行客户端,输入 help 命令。

--------------------------------------------------------------------------------
| command |   sub command/data  |                   descriptions               |
--------------------------------------------------------------------------------
|close     (args)                eg:close {"id":1}                             |
--------------------------------------------------------------------------------
|create    (args)                eg:create {"title":"测试","desc":"程序添加进去的"}|
--------------------------------------------------------------------------------
|exit      (no args)             exit program. `exit` can also be `quit`, `bye`|
--------------------------------------------------------------------------------
|getexpiredlist(no args)         eg:getexpiredlist                             |
--------------------------------------------------------------------------------
|getlist   (no args)             eg:getlist                                    |
--------------------------------------------------------------------------------
|help                                                                          |
|          (no args)             `help` can also be `man`, `info`              |
|          specific_cmd          help info on specific command                 |
--------------------------------------------------------------------------------
|open      (args)                eg:open {"id":1}                              |
--------------------------------------------------------------------------------

遇到的问题

  1. 安装集成开发环境遇到的问题,安装grpc, protoc, bazel以及在vscode如何调试c++项目总结
  2. 如何将命令行的json字符串映射到proto中(通过JsonStringToMessage方法)。
  3. 如何将结构体和mysql进行映射?(未解决)
  4. 客户端会偶现内存溢出的问题(未解决)。
  5. 系统升级到macOs Catalina后,在vscode中无法调试(未解决)。
  6. 如何将现有服务端分离成controller和service层。并且提供数据库连接池(现有的方式是一个请求进行一次数据库连接释放操作)的操作。

TODO

  1. 增加系统日志,方便调试以及定位bug。
  2. 将服务端的接口实现分离成具体的执行类。提供数据model层(可以减少大量重复代码)。减轻server.cc中的代码量。
  3. 增加程序的健壮性,对于异常的错误处理以及偶现的内存溢出提供更完善的容错机制,而不是让程序直接崩溃。
  4. 添加ssl层,对数据进行水平越权和垂直越权的校验。
  5. 对接性能监控平台,当程序运行异常时,可以收到相应的告警服务。
  6. 对接google test。增加测试用例。
  7. 集成cicd,将服务进行docker化部署。

About

扣费管理系统

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages