Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
wangbjun committed Jun 30, 2023
1 parent b3b48aa commit 5001ac7
Show file tree
Hide file tree
Showing 10 changed files with 3,758 additions and 4,016 deletions.
7 changes: 3 additions & 4 deletions _config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,9 @@ deploy:
# repository: [email protected]:wangbjun/wangbjun.github.io.git
# branch: master
- type: sftp
host: 192.168.1.2
user: root
pass:
host: 158.101.15.46
user: ubuntu
remotePath: /opt/blog
port: 22
privateKey: /home/jwang/.ssh/id_rsa
concurrency: 10
concurrency: 10
7,539 changes: 3,531 additions & 4,008 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"dependencies": {
"hexo": "^4.0.0",
"hexo-deployer-git": "^2.1.0",
"hexo-deployer-rsync": "^1.0.0",
"hexo-deployer-sftp": "^0.4.1",
"hexo-generator-archive": "^1.0.0",
"hexo-generator-baidu-sitemap": "^0.1.6",
Expand All @@ -25,9 +26,9 @@
"hexo-generator-sitemap": "^2.0.0",
"hexo-generator-tag": "^1.0.0",
"hexo-renderer-ejs": "^1.0.0",
"hexo-renderer-marked": "^2.0.0",
"hexo-renderer-marked": "^5.0.0",
"hexo-renderer-stylus": "^1.1.0",
"hexo-server": "^1.0.0",
"hexo-wordcount": "^6.0.1"
}
}
}
136 changes: 136 additions & 0 deletions source/_posts/coding/restful-api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
---
title: 要不要使用RESTful?
date: 2023-06-30 22:52:33
tags: 编程
category: Coding
---

从事Web开发的童鞋对RESTful API很多人都不陌生,不同项目的接口形式千奇百怪,有些声称使用RESTful,但是实际上并不完全符合规范,不禁让我思考,到底要不要使用RESTful API的风格?

举个例子,相信大家见过不少下面风格的API:

| 用途 | 请求方法 | 命名 |
|----------|------|-------------------|
| 获取用户列表 | GET | /getUserList |
| 获取单个用户信息 | GET | /getUserInfo?id=1 |
| 新增用户 | POST | /createUser |
| 更新用户 | POST | /updateUser |
| 删除用户 | POST | /deleteUser |

这是一个最简单的CURD接口,说实话,我并不反对这种形式的API,虽然说看上去俗了点,但是至少见名知意,除了获取数据使用GET,其它一律POST,简单粗暴,没什么大问题。

如果展开说,上面的这种形式在复杂的情况下,无法更好的表达接口的含义,比如说假设你要写一个获取用户的好友列表接口,那可能就得这么写:

```bash
获取用户好友列表 GET /getUserFriends?user_id=1
```

这种命名方式在复杂情况下会导致接口名字越来越长。。。可读性就变的差了,而且一眼看不出来数据之间的关系,不好分类,假设有些人名字写的差就更难解读了。

如果使用RESTful则可以采用这种形式:

```bash
获取用户好友列表 GET /users/:id/friends
```

传统的接口采用动词+接口名称的形式来表达含义,而RESTful推荐使用HTTP请求方式来定义,比如GET用于获取数据、POST用于创建、PUT用于修改、DELETE用于删除。

<!--more-->

上面这些接口如果使用RESTful形式改写就是这样:

| 用途 | 请求方法 | 命名 |
|----------|--------|-----------|
| 获取用户列表 | GET | /user |
| 获取单个用户信息 | GET | /user/:id |
| 新增用户 | POST | /user |
| 更新用户 | PUT | /user/:id |
| 删除用户 | DELETE | /user/:id |

关于是用user还是users这块也有一个分歧,有些人觉得应该是用复数,因为有多个用户,所以获取用户得用getUsers,这个问题同样存在数据表名称上面。

我觉得接口用不用复数取决于数据表名称用不用,如果数据表就是users,那接口最好也用,保持一致。

至于说数据表名称该不该用复数,很多人都有不同的看法,在项目开始的时候统一明确的一个规范就行了,如果你要问我,我建议使用单数。

除此之外,RESTful还推荐通过HTTP状态码来区分结果,比如200表示正常,403表示没有权限,传统的接口往往统一使用200,然后在响应内容里面去区分。

简单说,RESTful的设计初衷是把这些数据实体当成一种资源,通过URL去定位资源,用HTTP描述操作,达到以下几个目标:

- 看URL就知道要什么
- 看HTTP方法就知道干什么
- 看HTTP状态码就知道结果如何

在我的职业生涯里面见过很多看似的RESTful的风格,但是实际上也不完全是,比如说PUT、DELETE的时候id是以http query string的方式传递,而不是path:
```bash
删除用户 DELETE /user?id=1
```
还有接口是直接把所有参数放到body里面传递,虽然说这些方式都可以,也不麻烦,因为现在很多Web框架都这些参数的处理都很方便,但是感觉还是不伦不类,当然有时候也是逼不得已,比如有些表的设计没有单一id主键,只有一个复合主键,这就很难使用path这种形式。

## 并非完美
RESTful的设计规范很理想,但是并不适合所有的项目,因为很多接口不是纯粹的CURD操作,它不仅仅是对一张表的增删改查,这导致很难通过URL去表达含义。

对于单纯的获取数据、修改数据的接口RESTful比较合适,但是当你的接口里面包含非常复杂的业务逻辑的时候,RESTful就非常麻烦了,根本无处下手。

举个例子,一个根据用户的住址获取附近的超市的接口,这样的接口如果使用传统的方式可能是这样:
```bash
/getUserNearbySupermarket?user_id=1
```
如果采用RESTful就存在一个问题,这到底是围绕着用户还是超市来设计呢?
```bash
/user/:id/nearby_supermarket
/supermarket/nearby?user_id=1
/user_nearby_supermarket?user_id=1
```
以上这3个例子你们觉得哪个好?对此我也纠结了很久,最后在参考了很多云厂商的API之后,个人觉得第一种比较合适。

有些时候RESTful API定义的GET、POST、PUT、DELETE4个常用方式并不能满足所有的应用场景,或者不够清晰,比如说业务有个场景是要清空用户黑名单,这属于PUT还是DELETE?

从用户的角度来说说PUT,因为我是修改了用户的附属属性,但是从黑名单的角度是删除了数据,都有一定的道理。

或许,我们可以这么设计
```bash
POST /user/:id/blacklist/empty
```
我们可以认为blacklist是用户的属性,empty是一种动作,是不是更加清晰一点,至于方法是用POST还是PUT,区别都不大。


## 最佳实践
对于开放平台的接口,比如说一个云厂商,需要提供对应的sdk或者api给用户使用,推荐使用RESTful,实际上国外很多大厂的api是非常标准的RESTful风格,国内某大厂除外。

云服务本身就是提供资源,无论是服务器、IP、域名,它都是一种网络资源,而RESTful天生就是为了描述资源,并且云服务的操作逻辑简单,没有复杂的业务逻辑,对于服务器无法就是创建、查看、修改、删除、重启等。

以前用过vultr的API,就是非常规范的RESTful风格,看着很舒服:

| 用途 | 请求方法 | 命名 |
|--------|--------|----------------------|
| 获取实例 | GET | /instances |
| 获取单个实例 | GET | /instances/:id |
| 新增实例 | POST | /instances |
| 更新实例 | PUT | /instances/:id |
| 删除实例 | DELETE | /instances/:id |
| 启动实例 | POST | /instances/:id/start |
| 批量启动实例 | POST | /instances/start |

值得一说的是启动这个操作,它有2种形式,一个是操作单个实例,参数放在path里面,还有一个是批量操作,是有多个id,这时候参数是放在json body里面。

但是对于很多公司内部系统的接口,RESTful往往并不是最佳的选择,如果为了简单方便,不考虑这些乱七八糟的规范,我建议除了获取数据使用GET,其它一律使用POST。

| 用途 | 请求方法 | 命名 |
|--------|------|-------|
| 获取用户列表 | GET | /user |
| 新增用户 | POST | /user |
| 更新用户 | POST | /user |
| 删除用户 | POST | /user |

比如上面这个写法,第一个GET接口要支持多个参数过滤,比如说可以这么写/user?id=1,相当于获取单个用户,除了GET之外的接口参数全部放到body里面,而且统一采用JSON形式。

还有一个响应状态码的问题,个人觉得还是统一200比较合适,在响应体内部另外定义code来表达结果,也就是说不依赖HTTP状态码,虽然有点不符合RESTful的规范,但是兼容性好,因为你不知道哪个中间件会怎么处理。

**最后总结一下**

对于要不要使用RESTful风格的API这个问题没有明确的答案,如果你的应用逻辑简单,大多数是对一些数据表的增删改查,可以考虑使用RESTful风格的接口,相反如果你的应用业务逻辑复杂,也可以不用。

如果考虑到这是一个对外公开的OpenAPI,建议使用RESTful风格,毕竟这也算是一种业界共识,你整个什么getXXXByXXX显的确实有点low啊。

其实我们也可以2者混用,根据实际情况来决定,毕竟这只是一个接口路由,没必要纠结太多,大部分Web框架都支持各种形式的路由参数,对于简单的CURD可以使用RESTful,对于复杂的业务逻辑则特殊处理。
2 changes: 1 addition & 1 deletion source/_posts/life/remember-working-log.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: 那些年,那些事
date: 2022-06--3 23:59:59
date: 2022-06-03 23:59:59
tags: Life
category: Life
---
Expand Down
83 changes: 83 additions & 0 deletions source/_posts/linux/free-v2ray-proxy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
---
title: 终极免费“白嫖”科学上网攻略
date: 2023-06-22 11:28:27
category: Linux
tags: Linux
---
在国内搞计算机网络开发基本上必备梯子,不仅仅是为了使用Google,其实很多海外网站,不是打开慢就是偶尔彻底打不开,还有类似最近大火的ChatGPT,有梯子还不一定能用上。

为了解决这个问题,必须需要一个VPN,也就是俗称的梯子,梯子哪里来呢?

- 免费,网上有很多免费梯子,网速慢也不稳定,凑合用一下没问题,不过存在信息泄露风险,毕竟天下没有免费的午餐,不建议长期使用。
- 收费,网上卖梯子的也很多,可用节点多,网速好,但是很多都是有流量限制,比如一个月100GB大概是20-30块钱,不过同样存在安全风险,另外购买包年的话小心商家跑路。
- 自建,网上搭建教程一大把,很多搞技术开发的童鞋对于Linux都不陌生,看着教程搭建一个并不难,但是依然需要花钱购买服务器、域名等

作为一个资深互联网爱好者,早在Google退出中国之前就注册了账号,一直延用至今,这些年也没少折腾,从shadowsocks到v2ray,各式各样的梯子技术都尝试过,也算是稍微有点经验,今天就来分享一个永久免费的方案,一分钱不花享受高速梯子服务。

<!--more-->
其实在我发现这个方案之前,我也都是在花钱购买VPS,一直用的vutlr的服务,至今账号里面还有10多刀没花完,vultr的话其实还可以,一个月大概是5刀,最便宜的是2.5刀,对比国内的云云服务器来说算是便宜了。现在不仅是vultr,很多海外的小VPS厂商的IP可用的真不多,而且容易被封,因为被拿来搭梯子用的太多了,网速也比较慢。

不过vultr有一些好处,首先它支持支付宝付款,这个方便了很多国内用户,众所周知,很多海外的平台都需要外币信用卡,难倒了不少人。其次它是按秒计费的,实例删除就不计费了,此外vultr还提供了api,可以利用这个实现一个自动化操作,我之前就写了一个程序自动检测IP可用性,如果发现被封后重建实例。

<img src="/images/2023/2023-06-221201.png">

另外还提供了免费的DNS服务,我目前就在用,有人回好奇为什么不用阿里云或者dnspod等来解析,我想说,我的目标是不使用任何国内云服务厂商的东西,原因你们都懂。

如果有人需要自费购买的话,可以通过我的邀请码注册一波:https://www.vultr.com/?ref=6891627

言归正传,今天我想说的是一套完全免费的方案,包括以下几个方面:

## 1.免费服务器
其实国外很多云服务厂商都有免费试用期,比如微软云、Google云、亚马逊云通常都会有一个免费6个月-12个月的试用期,在此期间会提供一定免费额度可用拿来使用,比如说可以创建一个2核4G内存的实例。

虽然还是有时间限制的,不过你都白嫖一遍的话应该也够你用好几年了,只需要你拥有一个外币信用卡,因为在国外很多平台都流行信用消费,通常都需要你绑定信用卡,然后先消费后付账单。

注册账号之后需要绑定信用卡,第一次会扣取你0.1刀的钱,然后返还给你,这是为了验证你的信用卡的有效性。

但是我今天要说的是Oracle甲骨文云的**【永久免费】**服务,对,你没听错是永久免费,只是存在一个使用量的限制,这个使用量对于个人来说绰绰有余,商业服务那肯定不够用的。

<img src="/images/2023/2023-06-222235.png">

简单说,就是Oracle云免费提供一个双核1G内存的x86实例或者一个16核24G内存的arm实例,10G的存储,还有很多其它的服务,只不过咱们都用不到。

但是也不是完全没有限制的,Oracle不允许你浪费,所谓不允许浪费就是你不能把实例闲置了,系统会检测你的实例负载,如果过低就会暂停实例,比如说在7天内满足以下条件的实例:

- 95%时间的CPU使用率不足10%
- 网络利用率低于10%
- 内存利用率低于10%(仅适用于A1 ARM免费实例)

如果你的服务器只是拿来搭梯子的话,用的不多的话这个负载还真达不到要求,但是可以用一些手段故意把负载提上来,Github上面有人写了“保活”脚本运行去一些命令来加大负载。其实万一真的被检测到问题也不大,系统并不会删除实例,只是会把你实例停止了,然后给你发一封邮件告诉你,你只需登录到控制台里面再启动就行了。

具体的话可以参考其官网介绍:https://www.oracle.com/cloud/free/

## 2.免费的CDN加速
cdn加速并不是必须的,但有免费的不用白不用,cdn加速有很多好处的,第一个是提高网速和稳定性,虽然亚马逊云在国内没有cdn节点,但是可以用到亚洲的节点,比如韩国、日本、新加坡的加速节点,这比你直接连美国的服务器还是要快的吧。

另外,使用cdn加速之后,我们可以用cdn提供的加速域名来配置,意味着不用对外暴露真实的服务器IP,这样被封禁的可能性就很小。GFW一般情况下不会去封这些云服务器的加速域名,因为这样误杀的就太多了,毕竟国内很多互联网公司出海还是需要用到海外这些云厂商的服务的。

<img src="/images/2023/2023-06-222240.png">

亚马逊云提供了每个月免费1TB流量的cdn服务,只要不超过这个流量都不要钱,放心用。说实话,自己一个人用,就算你一天到晚看油管也用不了这么多。。。这个额度已经很豪横了。

具体的话可以参考其官网介绍:https://aws.amazon.com/cn/cloudfront/?nc2=h_ql_prod_nt_cf

有一点需要大家注意,据说这个1TB流量只是cdn下载,如果是上传的话量大了可能要收费,因为平时咱们流量网页上传的流量是极少的,除非你有特殊需求,比如说在油管上传视频,这可能会消耗大量的上传流量然后产生账单,具体情况我也不清楚,因为我也不上传视频,所以用了很久没有产生过账单。

## 3.免费的域名和证书
我们的方案需要需要域名和ssl证书,这2个其实自己买也不要多少钱,很多垃圾域名只要几块钱1年,但是我还是不推荐使用国内的云厂商的服务,所以选择从国外平台申请免费的。

免费域名的平台很多,我是从freenom上面申请的,可以免费用1年,另外ssh证书的话可以从Let's Encrypt申请免费的,一般也都是1年有效期,所以就是稍微有点麻烦,至少1年得维护一次。

对于证书,如果你是使用一些v2ray搭建脚本的话,像caddy是可以自动申请免费的证书的,都不用你操心。。。

---

最后说说搭建方案,那自然是基于v2ray的**vmess+ws+tls+cdn**组合,这套组合安全性非常高,我用了这么久没被封过,虽然说延迟高一点,但是你又不是拿来打游戏,看看网页问题不大。

具体的搭建教程网上很多我就不多说了,Github上面还有那种一键脚本,已经非常简单方便了,只是cdn这块需要单独配置一下。这套下来基本上不用花一分钱了,甚至还可以共享给自己熟悉的朋友一起用,一个月省它5刀不香吗?一年下来还能省几百块呢,哈哈。

最后说个缺点,这套方案大概率是无法解锁Netfix、迪士尼这种区域限制的流媒体服务,因为涉及到版权因素,这些服务每个国家的运营政策都不一样,而通常这些公司都是通过访问的IP来判断用户所在的国家。

但是由于咱们使用的是云服务器的IP,一看就知道不是正常用户,所以这些公司把很多VPS、云厂商的IP都封禁了,虽然不是所有,但是很多都封了,包括ChatGPT也是这样,据说ChatGPT只有微软云的IP可用,其它的都不行。

所以不是说完全不行,有时候多试试多换IP可能会找到可用的,这就很尴尬了,如果你对这些服务有需求的话这时候购买收费的梯子的好处就体现了,不过也有一些技术手段来解除这个限制,只是比较复杂这里就不多说了。
Binary file added source/images/2023/2023-06-221201.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added source/images/2023/2023-06-222235.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added source/images/2023/2023-06-222240.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion themes/next/source/css/_common/scaffolding/base.styl
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ blockquote {
img {
display: block;
margin: auto;
max-width: 70%;
max-width: 80%;
height: auto
}

Expand Down

0 comments on commit 5001ac7

Please sign in to comment.