短连接系统设计

短连接服务原理和系统设计

Posted by Liangjf on July 20, 2020

短连接服务原理和系统设计

项目源码地址github

原理

长链连接映射, 301/302

算法

  • hash算法
  • 原子自增(mysql/redis)[进制法]
  • 元数据中心发号器(zk/etcd)[进制法]

hash算法

todo

redis原子自增分布式

负载均衡器+n个短连接服务

比如起10个短连接服务, 每个分别以0~9结尾, 负债均衡器采用轮训方式转发请求, 每次短连接服务由单点的自增1改为自增10

这样, 就可以分布式部署并且保持id递增, 即使机器挂了, 可以重启机器并且设置起始生成id为当前同个数量级的或者后面数量级的数字, 继续作为发号器服务

etcd/zk元数据中心号段发放分布式

负载均衡器+n个短连接服务

短连接服务启动时会先获取分布式锁, 然后去元数据中心取id号段, 并且更新元数据中心id号段

  • etcd作为元数据中心存储已分发id的id段区间(比如区间是10000, 0~10000 10001~20000…)
  • 各个发号服务启动时到etcd/zk取id区间, 并且更新etcd/zk的id段区间为下一阶段(同一个事务/分布式锁)
  • 即使有发号服务挂了/重启也只是丢失一段id区间, id还是保持递增

分布式部署

redis原子自增分布式

负载均衡器+n个短连接服务

比如起10个短连接服务, 每个分别以0~9结尾, 负债均衡器采用轮训方式转发请求, 每次短连接服务由单点的自增1改为自增10

这样, 就可以分布式部署并且保持id递增, 即使机器挂了, 可以重启机器并且设置起始生成id为当前同个数量级的或者后面数量级的数字, 继续作为发号器服务

etcd/zk元数据中心号段发放分布式

负载均衡器+n个短连接服务

短连接服务启动时会先获取分布式锁, 然后去元数据中心取id号段, 并且更新元数据中心id号段

基于etcd+发号服务组成的分段分发, etcd作为元数据中心存储已分发id的id段区间(比如区间是10000), 各个发号服务到etcd取id区间, 并且更新etcd的id段区间为下一阶段(同一个事务) 所以, 即可有发号服务挂了也只是丢失一段id区间, id还是保持递增

优化

  • 读写分离,分库分表(可以借助中间件)
  • 缓存
  • 防攻击
  • 限流
  • 短码反推?(不希望:洗牌算法, 希望:固定位插入字符,还原时删除就行)

测试

nginx反向代理

```nginx
upstream domain {
  server 172.16.7.16:9097 weight=1;
  server 172.16.7.16:9098 weight=1;
  server 172.16.7.16:9099 weight=1;
}
server {
    listen              80;
    server_name         shortlink.test.com;
    access_log  /var/www/nginx_access.log  main;
    location / {
        proxy_pass http://domain;
        proxy_set_header Host $host;
        proxy_set_header  X-Real-IP        $remote_addr;
        proxy_set_header  X-Forwarded-For  $proxy_add_x_forwarded_for;
        proxy_set_header X-NginX-Proxy true;
    }
}
```

启动三个发号服务

若是单机端口号记得修改

```shell
./shortlink    #172.16.7.16:9097
./shortlink    #172.16.7.16:9098
./shortlink    #172.16.7.16:9099
```

curl请求短连接服务生成长连接的短连接

```shell
curl -XPOST elk.code.com/v1/shorten -d '{"longLink":"https://www.google.com/search?q=22"}'
curl -XPOST elk.code.com/v1/shorten -d '{"longLink":"https://www.google.com/search?q=23"}'
curl -XPOST elk.code.com/v1/shorten -d '{"longLink":"https://www.google.com/search?q=24"}'
```

mysql中长短连接的映射

etcd元数据变化

```shell
etcdctl --endpoints "http://172.16.7.16:9002,http://172.16.7.16:9004,http://172.16.7.16:9006" get /shortLink/
```

启动三个发号器服务的对比:

```shell
{"startNum":31,"endNum":40}
{"startNum":41,"endNum":50}
{"startNum":51,"endNum":60}
```

可以看到每启动一个发号器服务就会去etcd元数据中心取id段并且更新元数据的id段为下一段; 通过分布式锁可以实现每个时刻只会有一个发号服务可用修改etcd元数据中心的id段; 从而实现分布式发号服务.