Open maisui99 opened 8 years ago
首先,要先说声抱歉,因为,其实目前我们还没有做到精确地做到识别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的运行逻辑其实很简单:用户第一次访问的时候,在nginx端插入一个脚本,计算设备宽高、像素宽高、是否支持触摸等信息,然后记录到cookie中,第二次访问的时候,nginx就可以拿到用户的终端信息了。
于是,我们就可以知道用户的物理宽度了。可惜这里埋了一些坑。
由于nginx端包含了拿到终端硬件信息的能力,那么这里就有两个选择
其实,这里并没有太多的纠结,服务端语言太多,针对各种不同的语言维护一份实在不太现实。于是,我们选择在nginx层做这些事情,这里用到了开源的tengine模块http_user_agent。
具体的识别规则也是从正则切换到了nginx配置文件。整个流程就优化为
这个方案逐渐部署到了各个应用上,支持了包括频道、活动、搜索等应用的终端识别,也顺利经过了双11的考验。
nginx层做解析带来一个惊喜,就是原本只有一个url一份缓存的方案,由于天猫一个url对应的是多个端不同的内容,无法进行缓存。
在nginx层面能够识别用户终端后,我们可以让一个url针对多份缓存副本,从而实现在cdn上可以直接经过nginx转发请求到用户终端对应的副本。
双11结束之后,我这边对已有方案进行了梳理,nginx方案已经暴露了一些问题,更新nginx配置文件成本相对发布前端文件或者后端文件都略高,且很多安卓phone都反馈了访问时看到了pc版本的页面。
前者的问题在于维护成本,后者的原因是来自前面提到的浏览器提供数值问题。
目前识别策略还是遵守安卓UA规范,包含android + mobile则判断是Phone,android不带phone就是pad,也算是面对未来的解决方案了。
最后,如果有更好的识别方案或者建议,欢迎找我沟通。
首先,要先说声抱歉,因为,其实目前我们还没有做到精确地做到识别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就可以拿到用户的终端信息了。
于是,我们就可以知道用户的物理宽度了。可惜这里埋了一些坑。
nginx-detector
由于nginx端包含了拿到终端硬件信息的能力,那么这里就有两个选择
其实,这里并没有太多的纠结,服务端语言太多,针对各种不同的语言维护一份实在不太现实。于是,我们选择在nginx层做这些事情,这里用到了开源的tengine模块http_user_agent。
具体的识别规则也是从正则切换到了nginx配置文件。整个流程就优化为
这个方案逐渐部署到了各个应用上,支持了包括频道、活动、搜索等应用的终端识别,也顺利经过了双11的考验。
惊喜
nginx层做解析带来一个惊喜,就是原本只有一个url一份缓存的方案,由于天猫一个url对应的是多个端不同的内容,无法进行缓存。
在nginx层面能够识别用户终端后,我们可以让一个url针对多份缓存副本,从而实现在cdn上可以直接经过nginx转发请求到用户终端对应的副本。
策略变更
双11结束之后,我这边对已有方案进行了梳理,nginx方案已经暴露了一些问题,更新nginx配置文件成本相对发布前端文件或者后端文件都略高,且很多安卓phone都反馈了访问时看到了pc版本的页面。
前者的问题在于维护成本,后者的原因是来自前面提到的浏览器提供数值问题。
目前识别策略还是遵守安卓UA规范,包含android + mobile则判断是Phone,android不带phone就是pad,也算是面对未来的解决方案了。
最后,如果有更好的识别方案或者建议,欢迎找我沟通。