V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  lesismal  ›  全部回复第 53 页 / 共 56 页
回复总数  1111
1 ... 45  46  47  48  49  50  51  52  53  54 ... 56  
我尝试了上一楼的 1.5 个包,没法返回单个包给业务层。算是 bug
@guonaihong “设计的时候支持分段传入,内部是一个状态机。”—— 试一下一次读 1.5 个包的内容

var data = []byte(
"POST /joyent/http-parser HTTP/1.1\r\n" +
"Host: github.com\r\n" +
"DNT: 1\r\n" +
"Accept-Encoding: gzip, deflate, sdch\r\n" +
"Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4\r\n" +
"User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) " +
"AppleWebKit/537.36 (KHTML, like Gecko) " +
"Chrome/39.0.2171.65 Safari/537.36\r\n" +
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9," +
"image/webp,*/*;q=0.8\r\n" +
"Referer: https://github.com/joyent/http-parser\r\n" +
"Connection: keep-alive\r\n" +
"Transfer-Encoding: chunked\r\n" +
"Cache-Control: max-age=0\r\n\r\nb\r\nhello world\r\n0\r\n" +

"POST /joyent/http-parser HTTP/1.1\r\n" +
"Host: github.com\r\n" +
"DNT: 1\r\n" +
"Accept-Encoding: gzip, deflate, sdch\r\n" +
"Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4\r\n" +
"User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) " +
"AppleWebKit/537.36 (KHTML, like Gecko) " +
"Chrome/39.0.2171.65 Safari/537.36\r\n" +
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9," +
"image/webp,*/*;q=0.8\r\n" +
"Referer: https://github.com/joyent/http-parser\r\n" +
"Connection: keep-alive\r\n" +
"Transfer-Encoding: chunked\r\n" +
"Cache-Control: max-age=0\r\n\r\nb\r\nhello world\r\n0\r\n")

p := httparser.New( httparser.REQUEST)
fmt.Printf("req_len=%d\n", len(data)/2)
data1, data2 := data[:600], data[600:]
sucess, err := p.Execute(&setting, data1)
if err != nil {
panic(err.Error())
}
if sucess != len(data1) {
panic(fmt.Sprintf("sucess 111 length size:%d", sucess))
}

sucess, err = p.Execute(&setting, data2)
if err != nil {
panic(err.Error())
}
if sucess != len(data2) {
panic(fmt.Sprintf("sucess 222 length size:%d", sucess))
}

p.Reset()
@guonaihong "标准库的 http.ReadRequest,每秒只能处理 124MB 。相比之下 httparser 可以 300MB,性能还是可以的。" —— 这么说不太公平,标准库的是返回了 Request 、url header body 各段落字段都做了解析的
还想要 TLS 之类的支持,都搞细搞全了,也是个大工程。。。
我之前也想写一份 httpparser 来着,细想了下,没时间,放弃了。。。
大概看了下,不确定是否准确:
1. "粘包"可能有问题,不只是一个包可能拆成多段被应用层分多次读取到,也可能是多个包的数据放一块、被应用层从任意中间位置分多次读取到,比如 3 个包被两次读到、两次分别读到前 1.5 个和后 1.5 个包
2. 好像只是解析一个完整包的功能,并没有返回一个 Request/Response 类似的结构,所以 header 、body 之类的还是要业务层自己解析一道,这样的话业务层仍需要重复解析一次长度相关、比较浪费

建议也解析 header 、body 相关内容,一个完整包解析完之后返回一个 Request/Response 给业务层处理,在这基础之上 parser 内置 buf 的缓存,一个段落或者一个完整包后剩余的 half 部分由 parse 自己存上,有新数据来了加一块继续解析,这样业务层不必通过 success 再截断数据跟下次数据放一块,也免去重复解析 half 的浪费
2021-01-29 12:23:56 +08:00
回复了 fewuliu 创建的主题 Vue.js 尤雨溪承认 Vite 在之后会取代 Vue CLI,你开始学 Vite 了吗?
原生 js 足够用,只是以前的大多数前端工程师们缺乏工程性系统性思考。工程管理、性能优化,试试我这个:

https://www.v2ex.com/t/747412#reply8

https://www.v2ex.com/t/743590#reply20
端口数量通常不是问题,文件描述符上限设置个 10w 、100w,其他的几个内核参数设置合理就行,只要你硬件配置足够。不过还真有的站点设置的不合理,golang 中国报错文件打开数量过多我就遇到过好多次。socket 是 4 元组,单 IP 自己过来的最大端口 65535,不代表服务器对所有 IP 加起来只能 65535,而且单 IP 除非故意写 bug 或者攻击、否则也不至于有这么多,而且这些 CDN 、防火墙那里就能挡,还轮不到业务层来处理这个(并且业务曾代码也没有这个能力处理)

如果是觉得某个设备只要超过两三个连接就算过多,那就看我上一楼说过,限制机制自己订制下就好
另外,怕连接数过多的话,单节点配置好最大在线数,新连接进来的时候判断下、超过了就拒绝掉,这个可以在网关或者业务节点的 upgrader checkorigion 里做,更好点的方式是自己 wrap 下 net.Listener,serve(listener),Accept 的地方直接做
节点数不多、redis 的话,每个节点每秒 hset 、hmget 下就行了,没啥压力,而且实时性也足够
BTW,我这有个 ARPC 的 golang 框架提供了 websocket 聊天的简单示例

https://github.com/lesismal/arpc/tree/master/examples/webchat

另外 ARPC 支持发布订阅,如果想自己实现个管理服务器进行多个服务节点的在线数统计,管理服务器接收上报人数、然后把多节点的业务服在线总和发布就行了

想简单处理的话轮询写、读 redis 就好了
跨站点劫持楼主已经写了,check origin + 业务层认证

单设备连接数限制这个不太合理,通常应该按照身份限制比较好:既然有业务层认证,每个连接都有身份,如果不允许同一个身份多个连接、认证后就把之前的踢掉,如果允许,那就自己服务节点配置提高、节点数量增加之类的(如果怕统一身份的连接散到多个服务节点上,可以加个网关层,网关层按身份指定到实际的业务节点、由业务节点进行踢下线处理)。如果实在是想按照设备限制,那策略里使用身份的地方就改用 ip 或者你的算法能够生成的设备 id

统计人数通常不需要太精确,即使是多个服务节点,每个节点定时(比如 5s )更新自己节点在线数到 redis/sql 都可以、更新多节点在线数量总和就可以了,实时在线本来就是不停跳动的,精确的意义不大。如果实在要求精确,自己再写个服务进行统计、并且同步到所有节点,或者直接用 redis incr 之类的,每秒查询、更新,但是都没法保证百分百精确,实时的本来就是跳动的数据,即使是股票 K 线的蜡烛图也都是按时间段的起值、止值、最高值、最低值进行统计的
完整的例子可以看这里:
https://github.com/lesismal/pm/tree/master/examples/bind_src_dst

还有个项目是 fork 了个别人的 admin template,用 pm.js 改造了下,可以直接对比 fork 的原作,性能提升太明显了。。
https://github.com/3rdrepo/adminkit
@bmwh123 其实就是把老方案的内容摘出来放到单独的 html 子页面,index.html 里放上对应的 dom 元素,用 pm.bindPages 绑定这些 dom 元素的 id 和对应的子页面 url,可以手动 $pm.select 切换页面 也可以带上 src 配置项在对应的 dom onclick 时自动切换内容,或者配置的 dst 值就用 router,然后 $pm.listenRouter 用路由的方式自动切换,比如:

<div id="menu" class="side_bar">
<div style="height: 2px;">&nbsp;</div>
<button class="button">
<a href="#page_1" class="button">Page 1<br>Click Me</a>
</button>
<div style="height: 2px;">&nbsp;</div>
<button class="button">
<a href="#page_2">Page 2<br>Click Me</a>
</button>
</div>

dom 树上两个 <a> 分别路由到:
href="#page_1"
href="#page_2"

// 页面配置 && 绑定
let pages = [
{
dst: "page_1",
url: "page/page_1.html",
},
{
dst: "page_2",
url: "page/page_2.html",

// lazy 为 true 时则第一次显示时才进行加载,否则进入页面就开始加载
lazy: true,
},
];
$pm.bindPages(pages);

// 显示 page_1
$pm.select("page_1");

// 监听路由变化、自动切换页面,比如路由切换到 #page_2 时,相当于执行 $pm.select("page_2")
$pm.listenRouter();
@alan0liang 是啊,我找了好几个 bootstrap admin template,都差不多的情况。可能这些主要是为了展示 template 功能、没做优化,但是既然是作为 template,别人拿来用也是希望快速实现功能,所以性能问题还是太不友好了。
还有很大程度上其实应该是使用传统原生 js 方式的的老技术、工程体系的锅,react vue 崛起之前的前端社区的大部分人缺少工程思维,react vue 崛起后框架强行工程优化了
not lazy 的是进来就加载的,都可配,业务层自由管理
@bmwh123 抱歉才看懂问题,前面的回答默认以为大家知道实际的机制了呢。。。

实际上单个大页面分为主页面和子页面,主页面里大概是这样子的:

<div class="main">
<div id="nav"></div>

<div id="dashboard.html"></div>
<div id="charts-chartjs.html"></div>
<div id="forms-basic-inputs.html"></div>
<div id="forms-layouts.html"></div>
<div id="icons-feather.html"></div>
<div id="maps-google.html"></div>
<div id="pages-blank.html"></div>
<div id="pages-invoice.html"></div>
<div id="pages-profile.html"></div>
<div id="pages-settings.html"></div>
<div id="pages-sign-in.html"></div>
<div id="pages-sign-up.html"></div>
<div id="tables-bootstrap.html"></div>
<div id="ui-alerts.html"></div>
<div id="ui-buttons.html"></div>
<div id="ui-cards.html"></div>
<div id="ui-general.html"></div>
<div id="ui-grid.html"></div>
<div id="ui-modals.html"></div>
<div id="ui-typography.html"></div>

<div id="footer"></div>
</div>

每个子 div 的 id 对应一个子页面,然后才是上面 lazy 相关的回答,如果 lazy 默认是不加载的、而等用户首次点击触发 $pm.select(...) 或者代码 $pm.select(...) 时才去加载的,并不是进到主页默认就把所有加载进来
@bmwh123 还提供了$pm.release(page),可以用于释放单个 page 的内容,如果应用层子页面内容太多想减少总资源占用压力,可以根据自己的需要、在 onhide(page) 中选择是否对该子页面内容释放,就是对该 dom 元素的 innerHTML 设置为""。
@bmwh123 有个 lazy 选项,lazy: true 的子页面是等到需要展示的时候才进行异步加载的,比如:

https://github.com/3rdrepo/adminkit/blob/dev/static/js/init.js#L18

每个页面可以配置:

{
src: "pages-profile.src", // 这个 id 的元素 onclick 时会切换内容到 dst
dst: "pages-profile.html",
url: "page/pages-profile.html",
lazy: true, //如果 url 不为空,lazy 为 true 则等到首次显示 dst 内容时加载 url 对应的子页面
init: function() {...}, //首次显示时调用
onshow: function(){...}, //被显示时调用
onhide: function(){...}, //被隐藏时调用
}
2021-01-22 15:02:28 +08:00
回复了 lesismal 创建的主题 JavaScript 发布 pm.js,包括但不限于帮助构建 web 原生单页面
@otato 对 hash 路由切换页面内容做了支持,fork 了个 admin 模板项目,用 pm.js 改造了下,去掉了多个页面大量的重复内容、避免不必要的重复加载、重复下载之类的,对比 fork 原作,切换内容顺滑、性能基本能达到极致了

欢迎来指点、给些批评建议( v 站不让每个回复都带外链,只能加另外一个帖子的链了):

https://www.v2ex.com/t/747412#reply0
2021-01-22 14:43:48 +08:00
回复了 lesismal 创建的主题 JavaScript 发布 pm.js,包括但不限于帮助构建 web 原生单页面
@shunia 感谢之前指出的相关知识点,最近研究了下 history 和 hash 路由,选择了对 hash 路由做点支持、根据路由切换内容,hash 路由确实不算复杂,但是内容管理本身还是需要原来的部分

随便找了个 admin 的模板项目,用 pm.js 、hash 路由切换内容的方式改造了下,去掉了多个页面大量的重复内容、去掉不必要的重复加载、重复下载之类的,切换内容更加顺滑、性能要好太多。我对前端不熟悉,各位交流中指出的问题能方便我更快去找到相关知识点、改进计划。

如有兴趣欢迎多来指点、给些批评建议:

https://github.com/3rdrepo/adminkit

:smile::smile:
1 ... 45  46  47  48  49  50  51  52  53  54 ... 56  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1412 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 26ms · UTC 17:44 · PVG 01:44 · LAX 10:44 · JFK 13:44
Developed with CodeLauncher
♥ Do have faith in what you're doing.