New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

天猫双11前端分享系列(七):如何精确识别终端 #32

Open
maisui99 opened this Issue Jan 19, 2016 · 0 comments

Comments

Projects
None yet
1 participant
@maisui99
Contributor

maisui99 commented Jan 19, 2016

首先,要先说声抱歉,因为,其实目前我们还没有做到精确地做到识别99%的终端设别,其中原因,一部分是因为终端类型和UA实在难以覆盖,另外一部分原因也是因为使用了一些错误的识别策略。

注1:后面会大量出现detector,其实就是我们给内部终端识别工具起的一个名字。
注2:天猫页面一直在实施一个url对应多份不同终端的页面,所以终端识别非常重要。

在哪一层进行识别

初期方案

由于当时处于业务mobile页面发展的初期,且大部分页面还在基于php进行开发,所以诞生了detector的第一个版本,php版本。识别逻辑也比较简单,纯正则匹配UA。

后来,node业务渐渐的增加,我们又重写了一份node版本,其中为了保持终端识别能力的一致,用于匹配UA的正则统一放到了一份json文件里,php和node都统一来读这一份文件。

正则主要还是收集了github上各种比较成熟的识别方案综合出来的。

改造期

在2014年底,为了保证pad用户的访问质量,我们对终端识别的工具进行了非常大的改造。其中,一直在坚持的一点就是将识别能力放到服务端进行。

当时面临的一个难题是,安卓pad和安卓phone之间的UA并没有差异,特别是4.2之前的版本,无法通过UA进行识别,但是又希望能够让用户在安卓pad上看到更合适的PC版本,我们设计并产出了MED的终端硬件信息获取方案。

MED

MED的运行逻辑其实很简单:用户第一次访问的时候,在nginx端插入一个脚本,计算设备宽高、像素宽高、是否支持触摸等信息,然后记录到cookie中,第二次访问的时候,nginx就可以拿到用户的终端信息了。

于是,我们就可以知道用户的物理宽度了。可惜这里埋了一些坑。

  1. 物理宽度的计算用到screen.width/screen.height,但是不同厂商的安卓设备,在不同的浏览器或者webview下给了各种不同的值,而并不是屏幕的分辨率。
  2. 安卓手机的屏幕越做越大,和PAD之间的分界线越来越模糊。

nginx-detector

由于nginx端包含了拿到终端硬件信息的能力,那么这里就有两个选择

  1. 将拿到的信息写到http头里,转发给应用的php/node detector
  2. 直接在nginx层进行识别,将识别结果转发给下游的应用

其实,这里并没有太多的纠结,服务端语言太多,针对各种不同的语言维护一份实在不太现实。于是,我们选择在nginx层做这些事情,这里用到了开源的tengine模块http_user_agent

具体的识别规则也是从正则切换到了nginx配置文件。整个流程就优化为

  1. nginx对UA进行解析
  2. 解析完成后,nginx再结合硬件信息,如果物理设备宽度较大,则识别为pad

这个方案逐渐部署到了各个应用上,支持了包括频道、活动、搜索等应用的终端识别,也顺利经过了双11的考验。

惊喜

nginx层做解析带来一个惊喜,就是原本只有一个url一份缓存的方案,由于天猫一个url对应的是多个端不同的内容,无法进行缓存。

在nginx层面能够识别用户终端后,我们可以让一个url针对多份缓存副本,从而实现在cdn上可以直接经过nginx转发请求到用户终端对应的副本。

策略变更

双11结束之后,我这边对已有方案进行了梳理,nginx方案已经暴露了一些问题,更新nginx配置文件成本相对发布前端文件或者后端文件都略高,且很多安卓phone都反馈了访问时看到了pc版本的页面。

前者的问题在于维护成本,后者的原因是来自前面提到的浏览器提供数值问题。

目前识别策略还是遵守安卓UA规范,包含android + mobile则判断是Phone,android不带phone就是pad,也算是面对未来的解决方案了。

最后,如果有更好的识别方案或者建议,欢迎找我沟通。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment