使用域名系统
Host 管理
host 管理一般会创建一个文件 /etc/hosts , 该文件记录了 Host -> ip 的映射关系,如下所示:
# example 公司主机表
10.1.2.3 oa.example.com # 办公
10.2.3.4 wiki.example.com # 文档
但是,随着 example 公司业务规模和员工数量的增长,使用该方法面临许多问题:
-
流量和负载:用户规模指数级增长,文件大小越来越大,同意分发引起较大的网络流量和 cpu 负载
-
名称冲突:无法保证主机名称的唯一性,同名主机添加导致服务故障
-
时效性:分发靠人工上传,时效性太差
使用域名系统
为了解决 Host 管理存在的问题,使用域名系统代替 hosts 文件。域名空间将被组织成树形结构,通过划分 zone 的方式进行分层授权管理,如下图所示:
开发外部用户访问
首先,租赁一个外网 ip, 专用于外部用户访问门户网站,将 www.example.com 解析到外网 ip 100.1.2.3, 将该 ip 绑定到一台物理机上,并发布公网 route, 用于外部用户访问。
自建 DNS 服务器
使用公有云托管,可能带来以下一些问题:
-
内网域名的解析也要去公网获取,效率低下。
-
外部用户看到内网 ip 地址,容易被 hacker 攻击。
-
云厂商权威 DNS 容易出故障,影响用户体验。
于是 example 公司想要搭建自己的权威 DNS 系统。权威 DNS 系统架构如下所示,用户向 Master 节点查询域名对应的 ip 地址, Master 根据记录返回结果。当应用服务更新后,会通知 Master 节点,同时 Master 节点也会通知 Slave 节点进行更新。
搭建好自建的权威 DNS 系统后,整个域名解析过程如下图所示:
接入 HTTPS 协议
HTTP 明文传输会带来一些列的安全问题,例如隐私数据窃取、信息截取篡改 ... 于是就有了 HTTPS 协议的提出, S 代表了 Security.
对称加密和非对称加密
对称加密指的是使用同一份秘钥对传输数据进行加密、解密。但是这存在一定问题,在最开始时,拥有秘钥的一方需要将秘钥发送给另一方,在这个过程中,可能会产生秘钥泄露的问题。
对此,非对称加密被提出来解决这个问题。加密钥匙被分为公钥和私钥,公钥只用于加密数据,私钥只用于解密数据。首先,客户端向服务器发送请求,服务器会将公钥返回给客户端。客户端生成密钥 KEY , 并用公钥对其进行加密,发送给服务端。服务端使用私钥解密,得到密钥 KEY。于是接下来,双方就可以使用密钥 KEY 进行对称加密传输数据。
接入全站加速
外网访问站点,可能存在以下一些问题:
-
源站容量低,可承载的并发请求数低,容易被打垮。
-
保温经过的网站设备多,出问题的概率越大,丢包、劫持。
-
自主选路网络链路长,时延高。
那么,解决方案有:
-
源站容量问题:增加后端机器扩容;静态内容,使用静态加速缓存。
-
网络传输问题:动态加速DCDN。
静态加速 CDN
它是针对静态文件传输的网络优化方式,类似于缓存机制。当客户端请求一个静态资源如图片时,直接从cdn节点获取即可,无需访问站点服务器群。
动态加速 DCDN
针对 POST 等非静态请求等不能在用户边缘缓存的业务,基于智能选路技术,从众多回源线路中选择最优的一条线路进行传输。
全站加速示例
-
用户首次登录抖音,注册用户名手机号等用户信息 --- 动态加速 DCDN
-
抖音用户点开某个特定的短视频加载后观看 --- 静态加速CDN
-
用户打开头条官网进行网页浏览 --- 静态加速CDN+动态加速DCDN
4层负载均衡
4层负载均衡指的是基于 IP + 端口,利用某种算法将报文转发给某个后端服务器,实现负载均衡地落到后端服务器上。
常见地调度算法
-
轮询:将所有地请求平均分配给每个真实服务器
-
加权轮询:给每个后端服务器一个权值比例,将请求按照比例分配。
-
最小连接:把新地连接请求分配到当前连接数最小地服务器
-
一致性 hash:将整个哈希值空间映射成一个虚拟的圆环,并通过哈希函数将请求和服务节点映射到这个圆环上。沿顺时针方向查找,遇到的第一个节点就是该请求访问的节点。
低成本将本地服务开放到外网访问 - 内网穿透
使用 Ngrok 工具,网址:ngrok | API Gateway, IoT Device Gateway, Secure Tunnels for Containers, Apps & APIs
编写本地服务
这里我们编写一个简单的 Hello World ! 服务,服务端口为8080。
package main
import (
"fmt"
"net/http"
)
func helloHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!")
}
func main() {
http.HandleFunc("/", helloHandler) // 设置路由
fmt.Println("Starting server at port 8080")
if err := http.ListenAndServe(":8080", nil); err != nil {
fmt.Println("Error starting server:", err)
}
}
本地端口暴露
首先,从 Ngrok 官网下载软件,运行可执行文件。从官网上复制 Your Authtoken , 这个代表了个人用户的身份凭证。接着,执行如下命令:
ngrok authtoken xxxx(Your Authtoken)
如果输出 Authtoken saved to configuration file... 则证明个人用户凭证设置成功。
接下来执行如下命令,该命令表示将本地8080端口暴露到某个特定域名的公网上:
ngrok http 8080
如果执行成功,可以看到返回的特定域名,例如:
Porwarding https://754e-234-68-23-123.ngrok.free.app -> http://localhost:8080
尝试在浏览器访问这个域名,可以看到成果访问后端服务: