[请教+讨论] 前端做负载均衡,如何判断 css 成功加载?

2019-05-12 23:57:34 +08:00
 jamblues

一个前端自动切换负载均衡的方案,请教 V 友一下。

有个前端项目,部署了 N 台 CDN,每台机器都分配了独立域名:

cdn1.xxx.com

cdn2.xxx.com

...

步骤一:

进入页面执行前,先判断 Cookie 中是否有 CDN 变量,如果没有,从以上域名中随机挑出一个写入 Cookie 的 CDN 变量中。

步骤二:

加载 css 和 js 的时候,都是通过此类格式加载:

<script>document.write('<link href="'+CDN+'/css.css" />')</script>
<script>document.write('<script src="'+CDN+'/js.js"><\/script>')</script>

步骤三:

页面加载完成后,如果通过判断页面正常加载了,那么就不做任何操作。如果没有正常加载,则可能是该 CDN 挂掉了,然后重新挑 CDN 域名写入 Cookie,然后刷新页面重走步骤一,确保用户看到的是完整的页面。


这样做的好处:

  1. 低成本的负载均衡

  2. 能快速切换有问题机器,对于 DNS 负载均衡,生效有时间局限性。

  3. 机器方面可减少人工运维,降低成本

坏处:

  1. 每个页面都得加入一段冗余的判断

  2. 增加 Cookie 和冗余的脚本浪费 HTTP 传输(当然,Cookie 也可以用 localStorage 解决)

  3. CDN 域名更新起来会稍有些麻烦


那么重点来了,有哪些方法,可以用来判断 JS 或者 CSS 正常加载?

方案一,已投入使用:

加入 cdn.js 文件写入一行:

var CDN_LOADED=1;

引用 cdn.js 后,使用判断

<script>
if(typeof CDN_LOADED =='undefined'){
	// 切换 CDN
}
</script>

因为第一种每次都要多请求一个文件,所以不是特别理想。

引出方案二。

方案二,求大神指导:

<script>document.write('<link rel="stylesheet" type="text/css" href="'+CDN+'/css.css" />')</script>

在样式表后,使用

var styles = document.styleSheets || document.styleSheetList;

if(???) {
   // 切换 CDN
}

这个??? 地方,我试了各种

// 不行,rules 报错
if(styles[0].rules == 0)
// 不行,rules 异常
if(typeof styles[0].rules != 'undefined')
...

也试过 onerror 事件,似乎是没用的。。。

都不行,请问哪位大神可以指点一二?

要求:

P.S. 这种文案实际是可行的,好像应用的企业不多?

4116 次点击
所在节点    程序员
34 条回复
azh7138m
2019-05-13 00:02:24 +08:00
9102 年了,怎么还 document.write ?
前厂用的 onerror 来处理,简单说就是自己实现一个 fallback 的逻辑,页面有一个 CDN 列表,资源传多个 CDN,优先加载某一个,一旦有报错就加载另一个,需要配合 AMD loader (其实也不用配合,都是符合 AMD 规范的 js )。
azh7138m
2019-05-13 00:09:55 +08:00
样式需要封装成 js,onerror 目前无法处理 style 的网络问题。
不过操作 stylesheet 的性能低的可怕.......
不过话说回来,service worker 提供了 FetchEvent,可以代理掉所有的请求,也是可以做的,这个倒是没有见到有人这么实现,可能是还要兼容老的浏览器?
jamblues
2019-05-13 00:45:25 +08:00
@azh7138m 老哥,可能我把问题写太长,让你误解啦~ TAT。。

现在情况简短描述一下:

```

用户只能访问到 html 页面,CDN 域名因为服务器或者用户网络原因加载失败了,

可以通过哪些前端(简单、高效)的手段,来判断用户载加失败这个问题?

```

我举 document.write 也只是尽可能简单的说明问题。

样式封装成 JS 或者引用 AMD Loader 之类的,都是有可能加载失败的,不但没有解决问题,而且还会增加问题的复杂度。。。(当然如果把库或者 css 写入页面就另说,例如百度的大搜索,就是这么做的)
xylophone21
2019-05-13 00:56:31 +08:00
第一感觉这个方案很奇怪,关注一下听听大家的说法
azh7138m
2019-05-13 01:22:02 +08:00
@jamblues 封装到 js 里面是为了能用 onerror 监听到错误,还能重新加载。在用 style 加载样式的时候没法直接做 reload,我是想表达这个意思。
你不用 AMD 规范也行,最后还是会重新发明 AMD。

或者就是直接放弃 chrome 40 以下用户,使用 FetchEvent 来做这个事情。

Q:如何知道失败了
A:
- 将 css 封装成 js,使用 onerror
- 使用 FetchEvent 自己封装逻辑
Accat1024
2019-05-13 03:25:03 +08:00
客户端代理一般好像都是 vpn 用的,对比 nginx 负载均衡优势好像不明显。
KuroNekoFan
2019-05-13 08:31:57 +08:00
要知道 css 有问题的,可以有这样一个方法:写一个特殊一点的 css rule (反正能覆盖 user agent style 即可),然后在一个不影响 ui 的元素上应用这个 rule,再检测这个元素的 computedstyle,超过一定时间的阈值之后,就认为对应的 css 没有加载到
sm0king
2019-05-13 08:50:07 +08:00
判断其中一个 css 是否生效可以否?
zephyru
2019-05-13 09:14:33 +08:00
感觉,如果说 CDN 的目的是为了快速的展示网页..这个方案在很多情况下收益是负的....
要实现效果..无论是 CSS 封装 JS 还是,定时器去判断某个样式是否生效..效率都太低了...
尤其是后者,如果有多个 CSS 文件的情况下基本不可用...
即使有一个简单的判断方式...总觉得还是负收益..关注看看...
mytry
2019-05-13 09:20:08 +08:00
这话题过去研究了好长时间,可以参考之前写的文章: https://yq.aliyun.com/articles/236582
Tomorr
2019-05-13 09:31:50 +08:00
opengps
2019-05-13 09:34:57 +08:00
负载均衡是自动的,手动负载均衡的目的是什么?
防止一个节点失效,自动切换另外一个节点吗?
opengps
2019-05-13 09:36:40 +08:00
另外还有个问题,文中描述肚的是 CDN,这跟负载均衡又是另外一码事
opengps
2019-05-13 09:38:09 +08:00
如果非要手动判断失效的 cdn,那么应该考虑的是使用备用域名,而不是同域名的备用二级解析
因为域名故障,域名阻断等情况,往往是整个域名出问题,这种同域名下的节点切换,仅仅是针对单个二级域名解析出故障有效果
jamblues
2019-05-13 10:04:44 +08:00
@sm0king 只需要判断任何一个 css 是否正常加载即可(前提是 css 最好不要有特征依赖)
jamblues
2019-05-13 10:09:44 +08:00
@zephyru 不一定是快速展示页面的需求 就像上边二楼老哥说的 而应该算是一个 fallback 的备选方案;相比如果用 dns 做负载的话 生效时间有延迟。如果用 nginx 做负载的话 不一定能实时检测出用户和服务器网络是否通畅。所以才会想出这样的方案
jamblues
2019-05-13 10:15:35 +08:00
@mytry 老哥 你这个应该和我的需求差不太多 但是感觉写文章理论偏多 实际应用上还有很多细节没考虑到呃…
RainFinder
2019-05-13 10:15:36 +08:00
楼上说得很对
jamblues
2019-05-13 10:16:53 +08:00
@Tomorr 老哥 看了代码 你这个只能做接口的 fallback 没法满足我这需求哇😂
jamblues
2019-05-13 10:22:57 +08:00
@opengps 其他疑问我在楼上解释了一下。老哥优秀~考虑的比较远哈,域名多样性,服务器稳定性会做为第二步继续考虑…只是第一步都还没解决…

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/563462

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX