移动开发

移动开发

2
回复

【环信官方外包一个项目】利用环信IM实现一个在线白板 环信

KevinGong 回复了问题 • 3 人关注 • 734 次浏览 • 2017-09-25 17:48 • 来自相关话题

0
评论

【开源项目】一个基于环信IM开发的开源的私密社交APP-Baby 即时通信 Baby

seven。 发表了文章 • 853 次浏览 • 2017-08-31 14:49 • 来自相关话题

Baby这个开源项目基于环信IM开发,刚开始选择IM的时候,看到知乎上黑环信的人挺多的,就亲自下载了几家IM的demo源码跑一遍,从功能、集成难易和消息稳定几个方面对比,最终还是选择了环信。集成这方面环信做的真不错,尤其是有了EaseUi这个包,基本上一天就能集成完毕。项目运行至今没有出现过什么问题,发送消息挺稳定的。先上效果图




开屏页的登录和注册




编辑个人信息




相册页面




首页的Moment
版本更新:
 
version 1.6
加入Tinker 热修复更新部分依赖修复大量细节问题,加入部分注释

version 1.5
bug fixupdate sth

version 1.4
增加长按删除功能优化Rxbus订阅加载数据外国友人优化的一些细节等等

version 1.3
增加了评论功能优化了相册加载修复了一些内存泄漏等等

version 1.2
修复了一些Bug把登陆注册事件换了个Zip操作符更符合流的思想

version 1.1
修复了主页背景无法切换的问题修复了聊天推送的问题修了语音视频的问题做了一些细节修改
Download



安装包下载体验
 
github地址
github源码
 Development Environment & Library
 
MVP

这个项目是基于MVP框架写的(大体上,聊天那块直接用环信的了),大部分Base类参考FastAndroid里边的基类,参考这个很快就能布好基本的MVP架构。本来是有考虑过MVVM后来想想还是先学习一下MVP吧,看过几个MVVM项目感觉还是挺好用的,不过还是BETA版不知道有没有什么坑。

Material Design

早就手痒想体验一把V7包里边的各种控件了,特喜欢coordinatorlayout和collapsingtoolbarlayout的互动让Tollbar隐藏又现的感觉,但是看起来好看还是要点代价的,在这里捣鼓了不少时间,尤其是collapsingtoolbarlayout的Expanded固定让我Google了好久,因为用英文搜索可能我表达的不太好,最后竟然是一句nestedScroll(false)就可以了。。。。 还是感谢Stackoveflow里边的大腿吧。

Dagger2

依赖注入Dagger2,也是我早就想用的一个框架了,理由是各种配合Mvp十分方便和好用,渐渐也能体会到一次注入到处可用的快感。不过一个新技术真的学习成本,国内没什么中文文档介绍,看国外的看的云里雾里。原理看的明白,用起来好像不太知道如何使用,尤其是在@inject之后对象,也可以在别的地方Inject,原本是被Inject方后来也成了Module提供方。虽然到最后原理还不是特别明白这里,但还是不阻碍用起来的快感。

Realm

一开始被新技术吸引到的是不会放过任何新东西的包括Realm,不过进了坑不代表这个坑可以跳阿。由于我这次用到了leacncloud,Realm感觉会和LeanCloud的子类化冲突让你只能选择其中之一,不过这个也算了,Leancloud提供了类似Map的Put方法也可以接受就是麻烦了点。但是被坑到的地方是Realm所谓的自动数据同步竟然是一改就是改真实的数据,并不是数据的拷贝。。。感觉和我使用到要缓存的数据有点冲突,因为这个Moment里边的项是有点赞的,点赞要修改当前Recycleview的数据(修改数据要开事务)。修改数据后会出现一些很奇怪的现象,不在Recycleview当前Item会跳到当前Item,点赞的动画也会消失。。。真的是想破脑袋也解决不了,就直接跳坑了。最后感觉这个Realm在保存不跟服务器需要同步的数据会好点。

LeanCloud

用LeanCloud是因为在知乎太多吹它的人了而且它的确在BAAS这方面功能比较多(后来才发现即时通信没有语音和视频),所以就尝试使用了,SDK整体来说是不错的都挺好用的,满足了我对存储方面的要求。不过就在我开发的这几天,貌似稳定性没有想象中那么好,好几次上传个头像都会SocketTimeOut,查询也会有点慢,不过还好都在接受范围内(不过要是到了收费的标准我就接受不了)。

环信

baby这个开源项目基于环信IM开发,刚开始选择IM的时候,看到知乎上黑环信的人挺多的,就亲自下载了几家IM的demo源码跑一遍,从功能、集成难易和消息稳定几个方面对比,最终还是选择了环信。集成这方面环信做的真不错,尤其是有了EaseUi这个包,基本上一天就能集成完毕。项目运行至今没有出现过什么问题,发送消息挺稳定的。

Rxjava、RxAndroid

Rxjava我从第一眼看到了就喜欢上了(个人特喜欢那种通过.设置完成的感觉),接触也有几个月,一开始就和Retrofit 、Okhttp一起使用。学习成本还是要有的阿,看了不知道多少篇关于Rxjava使用的文章和例子,对里边的操作符也仅仅停留在那几个最常用的,其他一大堆好多都没用过,看来还用得不够。

Glide

Glide也是一个后来居上让我喜欢的图片加载库,一开始我喜欢picasso 是觉得轻巧而且好用有保证(主要是我偶像Jake Wharton主导,有加成),慢慢觉得Picasso对内存没有Glide来的友好,Glide在加载速度方面也领先,虽然整个库代码量是Picasso的几倍,但是比起重要的内存和用户体验来说还是Glide的领先一筹。

Butterknife、Ucrop等等

当让还有其他的一些润色的轮子啦,不过不是那么重要就不一一感谢啦。

Thanks
感谢Github、LeanCloud、环信、还有造那么多轮子给我们用的Square FaceBook Google的大大们。Thanks for improving my code m-ezzat.

Contacts
Email:379489343zhi@gmail.comQQ:379489343
 Copyright 2016 Roger ou

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. 查看全部
   Baby这个开源项目基于环信IM开发,刚开始选择IM的时候,看到知乎上黑环信的人挺多的,就亲自下载了几家IM的demo源码跑一遍,从功能、集成难易和消息稳定几个方面对比,最终还是选择了环信。集成这方面环信做的真不错,尤其是有了EaseUi这个包,基本上一天就能集成完毕。项目运行至今没有出现过什么问题,发送消息挺稳定的。
先上效果图

003.png

开屏页的登录和注册


001.png

编辑个人信息


002.png

相册页面


004.png

首页的Moment


版本更新:
 
version 1.6
  1. 加入Tinker 热修复
  2. 更新部分依赖
  3. 修复大量细节问题,加入部分注释


version 1.5
  1. bug fix
  2. update sth


version 1.4
  1. 增加长按删除功能
  2. 优化Rxbus订阅加载数据
  3. 外国友人优化的一些细节
  4. 等等


version 1.3
  1. 增加了评论功能
  2. 优化了相册加载
  3. 修复了一些内存泄漏
  4. 等等


version 1.2
  1. 修复了一些Bug
  2. 把登陆注册事件换了个Zip操作符更符合流的思想


version 1.1
  1. 修复了主页背景无法切换的问题
  2. 修复了聊天推送的问题
  3. 修了语音视频的问题
  4. 做了一些细节修改

Download

 
github地址

 Development Environment & Library
 
MVP

这个项目是基于MVP框架写的(大体上,聊天那块直接用环信的了),大部分Base类参考FastAndroid里边的基类,参考这个很快就能布好基本的MVP架构。本来是有考虑过MVVM后来想想还是先学习一下MVP吧,看过几个MVVM项目感觉还是挺好用的,不过还是BETA版不知道有没有什么坑。

Material Design

早就手痒想体验一把V7包里边的各种控件了,特喜欢coordinatorlayout和collapsingtoolbarlayout的互动让Tollbar隐藏又现的感觉,但是看起来好看还是要点代价的,在这里捣鼓了不少时间,尤其是collapsingtoolbarlayout的Expanded固定让我Google了好久,因为用英文搜索可能我表达的不太好,最后竟然是一句nestedScroll(false)就可以了。。。。 还是感谢Stackoveflow里边的大腿吧。

Dagger2

依赖注入Dagger2,也是我早就想用的一个框架了,理由是各种配合Mvp十分方便和好用,渐渐也能体会到一次注入到处可用的快感。不过一个新技术真的学习成本,国内没什么中文文档介绍,看国外的看的云里雾里。原理看的明白,用起来好像不太知道如何使用,尤其是在@inject之后对象,也可以在别的地方Inject,原本是被Inject方后来也成了Module提供方。虽然到最后原理还不是特别明白这里,但还是不阻碍用起来的快感。

Realm

一开始被新技术吸引到的是不会放过任何新东西的包括Realm,不过进了坑不代表这个坑可以跳阿。由于我这次用到了leacncloud,Realm感觉会和LeanCloud的子类化冲突让你只能选择其中之一,不过这个也算了,Leancloud提供了类似Map的Put方法也可以接受就是麻烦了点。但是被坑到的地方是Realm所谓的自动数据同步竟然是一改就是改真实的数据,并不是数据的拷贝。。。感觉和我使用到要缓存的数据有点冲突,因为这个Moment里边的项是有点赞的,点赞要修改当前Recycleview的数据(修改数据要开事务)。修改数据后会出现一些很奇怪的现象,不在Recycleview当前Item会跳到当前Item,点赞的动画也会消失。。。真的是想破脑袋也解决不了,就直接跳坑了。最后感觉这个Realm在保存不跟服务器需要同步的数据会好点。

LeanCloud

用LeanCloud是因为在知乎太多吹它的人了而且它的确在BAAS这方面功能比较多(后来才发现即时通信没有语音和视频),所以就尝试使用了,SDK整体来说是不错的都挺好用的,满足了我对存储方面的要求。不过就在我开发的这几天,貌似稳定性没有想象中那么好,好几次上传个头像都会SocketTimeOut,查询也会有点慢,不过还好都在接受范围内(不过要是到了收费的标准我就接受不了)。

环信

baby这个开源项目基于环信IM开发,刚开始选择IM的时候,看到知乎上黑环信的人挺多的,就亲自下载了几家IM的demo源码跑一遍,从功能、集成难易和消息稳定几个方面对比,最终还是选择了环信。集成这方面环信做的真不错,尤其是有了EaseUi这个包,基本上一天就能集成完毕。项目运行至今没有出现过什么问题,发送消息挺稳定的。

Rxjava、RxAndroid

Rxjava我从第一眼看到了就喜欢上了(个人特喜欢那种通过.设置完成的感觉),接触也有几个月,一开始就和Retrofit 、Okhttp一起使用。学习成本还是要有的阿,看了不知道多少篇关于Rxjava使用的文章和例子,对里边的操作符也仅仅停留在那几个最常用的,其他一大堆好多都没用过,看来还用得不够。

Glide

Glide也是一个后来居上让我喜欢的图片加载库,一开始我喜欢picasso 是觉得轻巧而且好用有保证(主要是我偶像Jake Wharton主导,有加成),慢慢觉得Picasso对内存没有Glide来的友好,Glide在加载速度方面也领先,虽然整个库代码量是Picasso的几倍,但是比起重要的内存和用户体验来说还是Glide的领先一筹。

Butterknife、Ucrop等等

当让还有其他的一些润色的轮子啦,不过不是那么重要就不一一感谢啦。

Thanks
  • 感谢Github、LeanCloud、环信、还有造那么多轮子给我们用的Square FaceBook Google的大大们。
  • Thanks for improving my code m-ezzat.


Contacts

 
Copyright 2016 Roger ou

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
6
评论

【新手快速入门】集成环信常见问题+解决方案汇总 常见问题

dujiepeng 发表了文章 • 6066 次浏览 • 2017-05-22 15:51 • 来自相关话题

   这里整理了集成环信的常见问题和一些功能的实现思路,希望能帮助到大家。感谢热心的开发者贡献,大家在观看过程中有不明白的地方欢迎直接跟帖咨询。
 
ios篇
APNs证书创建和上传到环信后台头像昵称的简述和处理方案音视频离线推送Demo实现环信服务器聊天记录保存多久?离线收不到好友请求IOS中环信聊天窗口如何实现文件发送和预览的功能ios集成常见问题环信推送的一些常见问题实现名片|红包|话题聊天室等自定义cell
 
Android篇
环信3.0SDK集成小米推送教程EaseUI库中V4、v7包冲突解决方案Android EaseUI里的百度地图替换为高德地图android扩展消息(名片集成)关于会话列表的置顶聊天java.lang.UnsatisfiedLinkError: 的问题android 端 app 后台被杀死收不到消息的解决方案
昵称头像篇
android中如何显示开发者服务器上的昵称和头像 Android中显示头像(接上一篇文章看)环信(Android)设置头像和昵称的方法(最简单暴力的基于环信demo的集成)IOS中如何显示开发者服务器上的昵称和头像【环信公开课第12期视频回放】-所有关于环信IM昵称头像的问题听这课就够了
 
直播篇
一言不合你就搞个直播APP
 
客服集成
IM-SDK和客服SDK并存开发指南—Android篇IM-SDK和客服SDK并存开发指南—iOS篇
 
开源项目
Android简版demoios简版demo凡信2.0:超仿微信的开源项目 凡信3.0:携直播和红包而来高仿微信:Github 3,515 Star方圆十里:环信编程大赛冠军项目泛聊:定一个小目标写一个QQSlack聊天机器人:一天时间做一个聊天机器人TV视频通话:在电视上视频通话视频通话:Android手机视频通话酷信:ios高仿微信公众号助手:与订阅用户聊天沟通
 
持续更新ing...小伙伴们还有什么想知道欢迎跟帖提出。
  查看全部
   这里整理了集成环信的常见问题和一些功能的实现思路,希望能帮助到大家。感谢热心的开发者贡献,大家在观看过程中有不明白的地方欢迎直接跟帖咨询。
 
ios篇

 
Android篇

昵称头像篇

 
直播篇
  1. 一言不合你就搞个直播APP

 
客服集成
  1. IM-SDK和客服SDK并存开发指南—Android篇
  2. IM-SDK和客服SDK并存开发指南—iOS篇

 
开源项目

 
持续更新ing...小伙伴们还有什么想知道欢迎跟帖提出。
 
0
评论

【环信征文】请不要说自己是Android程序员 移动开发

钢笔布莱恩特 发表了文章 • 109 次浏览 • 2017-08-12 10:31 • 来自相关话题

经常在网上看到各种标题为“Android程序员”、“Java程序员”、“PHP程序员”、“C/C++程序员”的招聘帖子,但这种招聘方式,很难找到好的人才。语言只是一种工具,对一个聪明的程序员来说,用没用过什么工具主要是由他原来的工作需要决定,并不能代表他全部的技能。

软件行业是一个非常强调人的价值的行业,价值就体现在有效的推动产品前进,而语言只是实现这个价值的工具。





一个软件产品往往涉及很多方面的知识,比如网络、数据库、Cache、编译环境工具等。如果这些必要基础知识不足,很难很好的独立完成一个产品的某个部分。

另一方面,一个人的聪明程度、对新知识的好奇心、自我驱动意识、为问题找到最佳解决方案的决心,才是他能不能成为一个好程序员的关键。举个例子,我的一位在某米当cto学长的告诉我,有位同事本来是服务器端以C#语言为主做开发的,完全没有过android开发经验,但他表现出对移动开发很有兴趣,并且在做服务器端开发时,表现出良好的学习能力,后来我把他调到Android组,负责android SDK和APNs相关的工作,结果只花了几个星期,Android SDK的稳定性大幅提升,解决了多个致命问题。

不要仅仅把自己定位为某种语言的程序员,说自己是Java程序员,C#程序员,Python程序员等等。一方面会限制自己的发展,一方面对团队整体的能力提升也不利。几乎所有的语言都有它自己的适用场景,在合适的地方用合适的语言,才能极大的提升生产效率。
正确的做法是,首先要有良好的基础知识,深刻的掌握2~3门语言,然后适用于不同场景的语言要了解概念。基础知识包括各种计算机原理、数据方面的知识,在学校没认真学的,现在有时间也要补充。语言方面比如掌握了C/Java,那C++/Python/Bash/Javascript/CSS等都可以了解下概念,至少要理解在一个完整的产品链里,它们分别适用于哪个环节。

标题用“请不要说自己是Android程序员”没有贬低Android程序员的意思,Java是目前被采用得最多的语言,主要用Java的程序员里,也是有大量牛人。另外,同样的,也不要说自己是C程序员、Python程序员。

 古语说的好,“书中自有黄金屋”。这句话告诉我们书籍是学习知识的第一大根本方向。在与Java相关的专业书籍中,相继记述着关于这门课程的基础知识及进阶内容,先易后难、步步深入,非常适合初学者去学习。
  虚心求教不可少。
往往很多高深莫测,经验丰富,功力深厚的人都埋藏在自己的身边,不容自己去察觉。所以如果大家想要从事Java行业,不妨请假身边从事过该行业的朋友,求学不在高低贵贱之分,只要碰到不懂的地方,就去虚心求教,世界这么大,而且这门知识又是如此让人追捧,比自己懂的人岂止千百?从这些人身上自己一定能够受益匪浅。

现在以Java语言为主的工作非常之多,另外在学校里就以学习Java为主的人也越来越多。但是,从学校就以学习Java这种高级语言为主的人,很多基础知识比较薄弱。高级语言掩盖了太多细节,提高了生产力,但在学习阶段,却不利于基础知识累积。




“Nicholas C. Zakas是全世界最著名的JavaScript程序员之一,之前是在雅虎将近工作5年。三年前,他写了一篇长文,回顾自己的职业生涯,提到七个对他来说最重要的建议,希望对大家的职业生涯有帮助:

1、 不要别人点什么,就做什么

我的第一份工作,只干了8个月,那家公司就倒闭了。我问经理,接下来我该怎么办,他说:"小伙子,千万不要当一个被人点菜的厨师,别人点什么,你就烧什么。不要接受那样一份工作,别人下命令你该干什么,以及怎么干。你要去一个地方,那里的人肯定你对产品的想法,相信你的能力,放手让你去做。"

我从此明白,单单实现一个产品是不够的,你还必须参与决定怎么实现。好的工程师并不仅仅服从命令,而且还给出反馈,帮助产品的拥有者改进它。

2、 推销自己




我进入雅虎公司以后,经理有一天跟我谈话,他觉得我还做得不够。

"你工作得很好,代码看上去不错,很少出Bug。但是,问题是别人都没看到这一点。为了让其他人相信你,你必须首先让别人知道你做了什么。你需要推销自己,引起别人的注意。"

我这才意识到,即使做出了很好的工作,别人都不知道,也没用。做一个角落里静静编码的工程师,并不可取。你的主管会支持你,但是他没法替你宣传。公司的其他人需要明白你的价值,最好的办法就是告诉别人你做了什么。一封简单的Email:"嗨,我完成了XXX,欢迎将你的想法告诉我",就很管用。

3、 学会带领团队
工作几年后,已经没人怀疑我的技术能力了,大家知道我能写出高质量的可靠代码。有一次,我问主管,怎么才能得到提升,他说:"当你的技术能力过关以后,就要考验你与他人相处的能力了。"
于是,我看到了,自己缺乏的是领导能力,如何带领一个团队,有效地与其他人协同工作,取到更大的成果。

4、 生活才是最重要的
有一段时间,我在雅虎公司很有挫折感,对公司的一些做法不认同,经常会对别人发火。我问一个同事,他怎么能对这种事情保持平静,他回答:"你要想通,这一切并不重要。有人提交了烂代码,网站下线了,又怎么样?工作并不是你的整个生活。它们不是真正的问题,只是工作上的问题。真正重要的事情都发生在工作以外。我回到家,家里人正在等我,这才重要啊。"
从此,我就把工作和生活分开了,只把它当作"工作问题"看待。这样一来,我对工作就总能心平气和,与人交流也更顺利了。
5、 自己找到道路
我被提升为主管以后,不知道该怎么做。我请教了上级,他回答:"以前都是我们告诉你做什么,从现在开始,你必须自己回答这个问题了,我期待你来告诉我,什么事情需要做。"
很多工程师都没有完成这个转变,如果能够做到,可能就说明你成熟了,学会了取舍。你不可能把时间花在所有事情上面,必须找到一个重点。
6、 把自己当成主人

我每天要开很多会,有些会议我根本无话可说。我对一个朋友说,我不知道自己为什么要参加这个会,也没有什么可以贡献,他说:"不要再去开这样的会了。你参加一个会,那是因为你参与了某件事。如果不确定自己为什么要在场,就停下来问。如果这件事不需要你,就离开。不要从头到尾都静静地参加一个会,要把自己当成负责人,大家会相信你的。"
从那时起,我从没有一声不发地参加会议。我确保只参加那些需要我参加的会议。
7、 找到水平更高的人
最后,让我从自己的经历出发,给我的学员一个建议。
"找到那些比你水平更高、更聪明的人,尽量和他们在一起,吃饭或者喝咖啡,向他们讨教,了解他们拥有的知识。你的职业,甚至你的生活,都会因此变得更好。"
 我的感受是IT行业是当今社会的热门行业,说它热门是因为它的发展潜力是无穷的,所以我们能进入到这个行业是一种幸运。在此,我特别感谢上家公司带我教我前辈们和师傅,在学习期间给了我莫大的帮助,在我遇到困难时,给我很大的鼓励和帮助,让我更加有信心坚持下来,找到工作。最后送大家一句话:相信自己没有选错行业,相信自己有立足的能力,为自己制定明确的目标,然后努力地去学习、体会、感悟、进步!
  查看全部
经常在网上看到各种标题为“Android程序员”、“Java程序员”、“PHP程序员”、“C/C++程序员”的招聘帖子,但这种招聘方式,很难找到好的人才。语言只是一种工具,对一个聪明的程序员来说,用没用过什么工具主要是由他原来的工作需要决定,并不能代表他全部的技能。

软件行业是一个非常强调人的价值的行业,价值就体现在有效的推动产品前进,而语言只是实现这个价值的工具。
(W[}_`X~BVTQM{3A`@HN4JU.png


一个软件产品往往涉及很多方面的知识,比如网络、数据库、Cache、编译环境工具等。如果这些必要基础知识不足,很难很好的独立完成一个产品的某个部分。

另一方面,一个人的聪明程度、对新知识的好奇心、自我驱动意识、为问题找到最佳解决方案的决心,才是他能不能成为一个好程序员的关键。举个例子,我的一位在某米当cto学长的告诉我,有位同事本来是服务器端以C#语言为主做开发的,完全没有过android开发经验,但他表现出对移动开发很有兴趣,并且在做服务器端开发时,表现出良好的学习能力,后来我把他调到Android组,负责android SDK和APNs相关的工作,结果只花了几个星期,Android SDK的稳定性大幅提升,解决了多个致命问题。

不要仅仅把自己定位为某种语言的程序员,说自己是Java程序员,C#程序员,Python程序员等等。一方面会限制自己的发展,一方面对团队整体的能力提升也不利。几乎所有的语言都有它自己的适用场景,在合适的地方用合适的语言,才能极大的提升生产效率。
正确的做法是,首先要有良好的基础知识,深刻的掌握2~3门语言,然后适用于不同场景的语言要了解概念。基础知识包括各种计算机原理、数据方面的知识,在学校没认真学的,现在有时间也要补充。语言方面比如掌握了C/Java,那C++/Python/Bash/Javascript/CSS等都可以了解下概念,至少要理解在一个完整的产品链里,它们分别适用于哪个环节。

标题用“请不要说自己是Android程序员”没有贬低Android程序员的意思,Java是目前被采用得最多的语言,主要用Java的程序员里,也是有大量牛人。另外,同样的,也不要说自己是C程序员、Python程序员。

 古语说的好,“书中自有黄金屋”。这句话告诉我们书籍是学习知识的第一大根本方向。在与Java相关的专业书籍中,相继记述着关于这门课程的基础知识及进阶内容,先易后难、步步深入,非常适合初学者去学习。
  虚心求教不可少。
往往很多高深莫测,经验丰富,功力深厚的人都埋藏在自己的身边,不容自己去察觉。所以如果大家想要从事Java行业,不妨请假身边从事过该行业的朋友,求学不在高低贵贱之分,只要碰到不懂的地方,就去虚心求教,世界这么大,而且这门知识又是如此让人追捧,比自己懂的人岂止千百?从这些人身上自己一定能够受益匪浅。

现在以Java语言为主的工作非常之多,另外在学校里就以学习Java为主的人也越来越多。但是,从学校就以学习Java这种高级语言为主的人,很多基础知识比较薄弱。高级语言掩盖了太多细节,提高了生产力,但在学习阶段,却不利于基础知识累积。
MSBFLGP1I{8KVLTCJ9)Q46.png

“Nicholas C. Zakas是全世界最著名的JavaScript程序员之一,之前是在雅虎将近工作5年。三年前,他写了一篇长文,回顾自己的职业生涯,提到七个对他来说最重要的建议,希望对大家的职业生涯有帮助:

1、 不要别人点什么,就做什么

我的第一份工作,只干了8个月,那家公司就倒闭了。我问经理,接下来我该怎么办,他说:"小伙子,千万不要当一个被人点菜的厨师,别人点什么,你就烧什么。不要接受那样一份工作,别人下命令你该干什么,以及怎么干。你要去一个地方,那里的人肯定你对产品的想法,相信你的能力,放手让你去做。"

我从此明白,单单实现一个产品是不够的,你还必须参与决定怎么实现。好的工程师并不仅仅服从命令,而且还给出反馈,帮助产品的拥有者改进它。

2、 推销自己




我进入雅虎公司以后,经理有一天跟我谈话,他觉得我还做得不够。

"你工作得很好,代码看上去不错,很少出Bug。但是,问题是别人都没看到这一点。为了让其他人相信你,你必须首先让别人知道你做了什么。你需要推销自己,引起别人的注意。"

我这才意识到,即使做出了很好的工作,别人都不知道,也没用。做一个角落里静静编码的工程师,并不可取。你的主管会支持你,但是他没法替你宣传。公司的其他人需要明白你的价值,最好的办法就是告诉别人你做了什么。一封简单的Email:"嗨,我完成了XXX,欢迎将你的想法告诉我",就很管用。

3、 学会带领团队
工作几年后,已经没人怀疑我的技术能力了,大家知道我能写出高质量的可靠代码。有一次,我问主管,怎么才能得到提升,他说:"当你的技术能力过关以后,就要考验你与他人相处的能力了。"
于是,我看到了,自己缺乏的是领导能力,如何带领一个团队,有效地与其他人协同工作,取到更大的成果。

4、 生活才是最重要的
有一段时间,我在雅虎公司很有挫折感,对公司的一些做法不认同,经常会对别人发火。我问一个同事,他怎么能对这种事情保持平静,他回答:"你要想通,这一切并不重要。有人提交了烂代码,网站下线了,又怎么样?工作并不是你的整个生活。它们不是真正的问题,只是工作上的问题。真正重要的事情都发生在工作以外。我回到家,家里人正在等我,这才重要啊。"
从此,我就把工作和生活分开了,只把它当作"工作问题"看待。这样一来,我对工作就总能心平气和,与人交流也更顺利了。
5、 自己找到道路
我被提升为主管以后,不知道该怎么做。我请教了上级,他回答:"以前都是我们告诉你做什么,从现在开始,你必须自己回答这个问题了,我期待你来告诉我,什么事情需要做。"
很多工程师都没有完成这个转变,如果能够做到,可能就说明你成熟了,学会了取舍。你不可能把时间花在所有事情上面,必须找到一个重点。
6、 把自己当成主人

我每天要开很多会,有些会议我根本无话可说。我对一个朋友说,我不知道自己为什么要参加这个会,也没有什么可以贡献,他说:"不要再去开这样的会了。你参加一个会,那是因为你参与了某件事。如果不确定自己为什么要在场,就停下来问。如果这件事不需要你,就离开。不要从头到尾都静静地参加一个会,要把自己当成负责人,大家会相信你的。"
从那时起,我从没有一声不发地参加会议。我确保只参加那些需要我参加的会议。
7、 找到水平更高的人
最后,让我从自己的经历出发,给我的学员一个建议。
"找到那些比你水平更高、更聪明的人,尽量和他们在一起,吃饭或者喝咖啡,向他们讨教,了解他们拥有的知识。你的职业,甚至你的生活,都会因此变得更好。"
 我的感受是IT行业是当今社会的热门行业,说它热门是因为它的发展潜力是无穷的,所以我们能进入到这个行业是一种幸运。在此,我特别感谢上家公司带我教我前辈们和师傅,在学习期间给了我莫大的帮助,在我遇到困难时,给我很大的鼓励和帮助,让我更加有信心坚持下来,找到工作。最后送大家一句话:相信自己没有选错行业,相信自己有立足的能力,为自己制定明确的目标,然后努力地去学习、体会、感悟、进步!
 
0
评论

【转载】组合式测试:移动测试服务的发展趋势 移动开发 移动互联网 app开发 APP测试

chieei 发表了文章 • 709 次浏览 • 2016-03-15 15:37 • 来自相关话题

由于国内移动设备和系统版本的碎片化,移动测试对于应用的质量保证变得至关重要,同时也催生了一批提供第三方测试服务的创业公司,BAT也都发布了自己的测试服务。但是,单一的测试服务往往不能完全满足开发者需求,测试服务的提供商也都在探索满足开发者需求的新方式。

自动化测试不能满足开发者需求

因为碎片化原因,开发者不可能手动测试所有的移动设备和系统版本,因此自动化测试对于移动测试来说是必须的。传统的第三方测试服务就是从这一点入手,以庞大 的云端真机测试为卖点,受到了开发者的认可。在社区里,自动化测试也最受关注,自动化测试的框架层出不穷,如何搭建自动化测试系统、编写测试脚本的内容最 受欢迎。一时间,自动化测试有一种彻底取代人工测试的势头。

但是,自动化测试实际上存在着一些问题,导致它并不实用,至少不能完全满足开发者的需求。据顾昕彪介绍,自动化测试的主要问题有:

新的功能很难做自动化测试。自动化测试大多数的作用是回归以前已经稳定下来的功能,对于一个新的功能,开发完以后要编写相应的测试用例,再进行自动化测试,这个时间比人工测试更长,因为人工测试可以直接开始测试,自动化测试有一个编写过程。

自动化测试需要有一些测试用例的积累,在版本大的迭代之后,很多测试用例可能就失效了,需要重新编写。因为移动应用发版很快,测试用例维护成本相对比较高。

自动化测试质量取决于编写测试用例的人的能力。有些时候测试用例能通过,但实际功能并不能用,要避免这点需要有丰富的测试经验和对移动开发的透彻的理解,而这对测试人员的要求太高了。

因此,自动化测试只能帮助开发者解决一部分兼容性问题,通常为了保证质量,开发者仍然需要采取其它测试手段。

施佳樑认为,人工测试之所以没有被市场所重视,是因为第三方人工测试服务的成本太高,如果能把人工测试的成本降下来,那么开发者还是会选择更有效的方式来满足测试需求,众测解决了这个问题。

众测成为测试工程师的业余职业

众包测试是在国外兴起的一种测试模式,通过将测试分配到多人手里,从而解决碎片化问题,并且避免自动化测试的一些弊端。

施佳樑介绍道,他们的众测平台拥有1500万用户,在这些用户中经过培训筛选,筛选出1000多个测试专家。这些测试专家已经能够像专业的测试人员一样,提供标准的测试报告来帮助开发者定位问题。

值得一提的是,这些测试专家里有些本来就是专业的测试人员,比如百度众测里会有百度的测试工程师利用业余时间来帮助别人做测试。事实上测试是一个需要经验和知识积累的职业,一般的众测人员只能模拟普通用户,效率较低,只有专业的测试人员才能高效的找出问题并提出报告。

通过众测这种模式,开发者能够以较低的成本请到多个较专业的测试人员进行测试,而测试工程师也能够在业余时间用职业技能赚些外快,这是一个双赢的事情。笔者认为这很可能成为众测模式的发展方向。

移动应用测试的未来:一体化服务

自动化测试和人工测试结合,能够得到一个较好的测试结果。但是,有一些情况没有包含在其中,比如应用crash,不借助辅助工具,要定位问题仍然比较困难,而crash上报服务正是为解决这个问题而生。

另外,对于应用性能,特别是不同网络条件下的应用表现的监测,使用应用性能管理服务(APM)更加有针对性。

要使用第三方服务来完全测试一个应用里可能出现的问题,开发者需要注册不同的服务,登录不同网站的管理后台来进行,这显然是很不方便的。而提供所有这些服务,同时将它们整合起来,将是移动测试服务未来一段时间的发展方向。

届时,开发者将只需登录一个网站,提交一次应用就可以得到一个多维度的、完整的测试报告,只有发展到这个阶段,移动测试服务才真正满足开发者的需求。



基于全球首创的对象识别技术,TestBird可以为客户提供深入到移动APP&游戏内部所有功能的深度解析能力。通过自助功能测试、远程真机调试、真机兼容性测试、真人体验测试、 真人压力测试和崩溃分析等产品,TestBird建立了云手机、云测试和云分析三大测试平台,为移动应用提供从研发到上线再到运营的一站式质量管理服务,帮助移动应用企业建立完善的质量管理体系和能力,全面提高移动应用的DAU、留存率以及付费情况。 查看全部


由于国内移动设备和系统版本的碎片化,移动测试对于应用的质量保证变得至关重要,同时也催生了一批提供第三方测试服务的创业公司,BAT也都发布了自己的测试服务。但是,单一的测试服务往往不能完全满足开发者需求,测试服务的提供商也都在探索满足开发者需求的新方式。

自动化测试不能满足开发者需求

因为碎片化原因,开发者不可能手动测试所有的移动设备和系统版本,因此自动化测试对于移动测试来说是必须的。传统的第三方测试服务就是从这一点入手,以庞大 的云端真机测试为卖点,受到了开发者的认可。在社区里,自动化测试也最受关注,自动化测试的框架层出不穷,如何搭建自动化测试系统、编写测试脚本的内容最 受欢迎。一时间,自动化测试有一种彻底取代人工测试的势头。

但是,自动化测试实际上存在着一些问题,导致它并不实用,至少不能完全满足开发者的需求。据顾昕彪介绍,自动化测试的主要问题有:

新的功能很难做自动化测试。自动化测试大多数的作用是回归以前已经稳定下来的功能,对于一个新的功能,开发完以后要编写相应的测试用例,再进行自动化测试,这个时间比人工测试更长,因为人工测试可以直接开始测试,自动化测试有一个编写过程。

自动化测试需要有一些测试用例的积累,在版本大的迭代之后,很多测试用例可能就失效了,需要重新编写。因为移动应用发版很快,测试用例维护成本相对比较高。

自动化测试质量取决于编写测试用例的人的能力。有些时候测试用例能通过,但实际功能并不能用,要避免这点需要有丰富的测试经验和对移动开发的透彻的理解,而这对测试人员的要求太高了。

因此,自动化测试只能帮助开发者解决一部分兼容性问题,通常为了保证质量,开发者仍然需要采取其它测试手段。

施佳樑认为,人工测试之所以没有被市场所重视,是因为第三方人工测试服务的成本太高,如果能把人工测试的成本降下来,那么开发者还是会选择更有效的方式来满足测试需求,众测解决了这个问题。

众测成为测试工程师的业余职业

众包测试是在国外兴起的一种测试模式,通过将测试分配到多人手里,从而解决碎片化问题,并且避免自动化测试的一些弊端。

施佳樑介绍道,他们的众测平台拥有1500万用户,在这些用户中经过培训筛选,筛选出1000多个测试专家。这些测试专家已经能够像专业的测试人员一样,提供标准的测试报告来帮助开发者定位问题。

值得一提的是,这些测试专家里有些本来就是专业的测试人员,比如百度众测里会有百度的测试工程师利用业余时间来帮助别人做测试。事实上测试是一个需要经验和知识积累的职业,一般的众测人员只能模拟普通用户,效率较低,只有专业的测试人员才能高效的找出问题并提出报告。

通过众测这种模式,开发者能够以较低的成本请到多个较专业的测试人员进行测试,而测试工程师也能够在业余时间用职业技能赚些外快,这是一个双赢的事情。笔者认为这很可能成为众测模式的发展方向。

移动应用测试的未来:一体化服务

自动化测试和人工测试结合,能够得到一个较好的测试结果。但是,有一些情况没有包含在其中,比如应用crash,不借助辅助工具,要定位问题仍然比较困难,而crash上报服务正是为解决这个问题而生。

另外,对于应用性能,特别是不同网络条件下的应用表现的监测,使用应用性能管理服务(APM)更加有针对性。

要使用第三方服务来完全测试一个应用里可能出现的问题,开发者需要注册不同的服务,登录不同网站的管理后台来进行,这显然是很不方便的。而提供所有这些服务,同时将它们整合起来,将是移动测试服务未来一段时间的发展方向。

届时,开发者将只需登录一个网站,提交一次应用就可以得到一个多维度的、完整的测试报告,只有发展到这个阶段,移动测试服务才真正满足开发者的需求。



基于全球首创的对象识别技术,TestBird可以为客户提供深入到移动APP&游戏内部所有功能的深度解析能力。通过自助功能测试、远程真机调试、真机兼容性测试、真人体验测试、 真人压力测试和崩溃分析等产品,TestBird建立了云手机、云测试和云分析三大测试平台,为移动应用提供从研发到上线再到运营的一站式质量管理服务,帮助移动应用企业建立完善的质量管理体系和能力,全面提高移动应用的DAU、留存率以及付费情况。
0
评论

环信移动客服助力58到家打造一站式客服体验闭环 移动开发

admin 发表了文章 • 1217 次浏览 • 2015-08-17 19:37 • 来自相关话题

近日,环信B轮融资及移动客服新品发布会在北京顺利举行。发布会上,环信CEO刘俊彦宣布,环信成功获得B轮1250万美元融资,同时环信CTO马晓宇宣布环信移动客服3.0产品正式上线,主打移动、智能、全渠道。而环信将以“连接人与商业”为愿景,开启万亿级企业云服务市场。






58到家客服总监王辉现场解读环信移动客服是怎么服务客户的

58到家客服总监王辉表示:“58到家原来只有呼叫中心一条服务渠道,对及时响应问题做得非常不好,虽然我们服务水平一直维持在85%以上,但是我们仍有客户打不进来电话,这些客户意味着订单的损失。O2O行业特点就是客户要求及时响应,快速解决,同时要满足任何下单需求。接入环信移动客服以后解决了58到家业务量暴增导致客服资源严重不足的问题,同时环信移动客服支持全渠道接入把服务渠道统一,把客户引流到在线客服上,提供了一站式的客户服务体验解决方案。同时帮助58到家把客服部门完成了从成本中心向盈利和营销中心的变革。”






据悉,环信移动客服产品已经有国美在线、58到家、楚楚街9块9等大批互联网巨头企业签约,累计签约客服座席已经达4万个,据艾媒咨询《2015年中国移动客服市场发展研究报告》显示,环信移动客服在新兴的移动客服市场占有率第一。

环信CTO马晓宇介绍,环信之所以受到市场如此欢迎,是因为环信移动客服是有别于传统客服的划时代产品。在环信CTO马晓宇看来,客服经历了三个时代传统callcenter的时代,互联网尚未普及,电话客服客户等待时间长,客户服务人员压力大,工作重复内容多;到了PC网页客服时代,随着互联网的普及,网页客服的成本明显小于电话客服,客户服务人员工作量较小,客户满意度有所提高,但相应依然不能及时有效;当今,随着智能手机用户的快速增长,客户要求能够随时在移动端获取咨询服务。移动端客服的重要性将不断上升。移动客服时代随之到来。

然而在环信基于IM长连接技术推出移动客服之前,业界并没有一款真正适合移动端和社交化时代的可靠的云端移动客服产品。此前,业界普遍存在的是两种移动客服产品,一类是工单客服,可以被视为移动客服1.0,基于工单方式和客服交互,技术实现简单,但无法做到实时交互,沟通效率低,用户体验差。另一类是轮询技术客服,可以被视为移动客服2.0,基于HTTP轮询技术,通过不断向服务器发送查询请求来准实时的收取消息。不能做到实时收取消息,流量和电量消耗高,APP在后台时无法接收消息,容易丢失客户。

而环信推出的移动客服产品是业界唯一一款具有IM长连接技术的移动客服产品,这被视为更适合移动端的客服产品。这一类型的移动客服可以定义为“交互型智能移动客服”,可以被视为移动客服3.0,以环信为代表的这一类新型移动客服是基于亿级IM长连接,系统稳定;智能机器人技术可处理大部分重复问题。相较环信移动客服的能力,传统的电话、工单、轮询客服在移动端和社交趋势下就显得捉襟见肘,有些OUT了。

环信移动客服实现了跨平台多渠道接入:支持 App、微信公众账号、微博、网页等,均可以快速统一接入客户服务后台管理。

其次,满足了开放性与自定义信息:这种新型的移动客服实现了代码开源、UI开源,还提供多套UI模版,便于与APP快速集成,平滑接入。同时第三方集成功能也很强大,可与第三方工单、知识库、CRM 系统等进行扩展集成。

第三,富媒体消息交互体验:移动客服平台提供了基于IM技术的类似微信体验的友好富媒体消息交互,不仅可以实时收发文字、表情,还可以即时收发图片、位置、实时语音、还可自定义消息,大大方便了与客户的沟通交流。

第四,精准客户画像功能:移动客服的IM沟通帮助企业辅助判断客户需求与诉求,通过自定义客户分类标签,客户再次访问时可获知客户的类型。并且还支持自定义会话小结,根据会话小结统计会话的分类,通过会话小结追踪客户诉求。通过轨迹分析功能,即通过发送客户访问页面的轨迹,判断客户意图,获取客户个性化细节,了解客户基础信息,分析客户行为,可以极大提高订单效率。

第五,“智能机器人+智能知识库”:作为一套智能化的客服系统,让企业建立基于业务的智能知识库,智能辅助归结业务信息和应答客户信息,历史常见问题系统梳理,提高客服效率。“智能机器人+智能知识库”组合目前可自动回复80%常见问题,随着智能知识库的不断训练,这一比例能够提高到90%。 查看全部
近日,环信B轮融资及移动客服新品发布会在北京顺利举行。发布会上,环信CEO刘俊彦宣布,环信成功获得B轮1250万美元融资,同时环信CTO马晓宇宣布环信移动客服3.0产品正式上线,主打移动、智能、全渠道。而环信将以“连接人与商业”为愿景,开启万亿级企业云服务市场。

113R92H4-0.png


58到家客服总监王辉现场解读环信移动客服是怎么服务客户的

58到家客服总监王辉表示:“58到家原来只有呼叫中心一条服务渠道,对及时响应问题做得非常不好,虽然我们服务水平一直维持在85%以上,但是我们仍有客户打不进来电话,这些客户意味着订单的损失。O2O行业特点就是客户要求及时响应,快速解决,同时要满足任何下单需求。接入环信移动客服以后解决了58到家业务量暴增导致客服资源严重不足的问题,同时环信移动客服支持全渠道接入把服务渠道统一,把客户引流到在线客服上,提供了一站式的客户服务体验解决方案。同时帮助58到家把客服部门完成了从成本中心向盈利和营销中心的变革。”

113R95c2-1.png


据悉,环信移动客服产品已经有国美在线、58到家、楚楚街9块9等大批互联网巨头企业签约,累计签约客服座席已经达4万个,据艾媒咨询《2015年中国移动客服市场发展研究报告》显示,环信移动客服在新兴的移动客服市场占有率第一。

环信CTO马晓宇介绍,环信之所以受到市场如此欢迎,是因为环信移动客服是有别于传统客服的划时代产品。在环信CTO马晓宇看来,客服经历了三个时代传统callcenter的时代,互联网尚未普及,电话客服客户等待时间长,客户服务人员压力大,工作重复内容多;到了PC网页客服时代,随着互联网的普及,网页客服的成本明显小于电话客服,客户服务人员工作量较小,客户满意度有所提高,但相应依然不能及时有效;当今,随着智能手机用户的快速增长,客户要求能够随时在移动端获取咨询服务。移动端客服的重要性将不断上升。移动客服时代随之到来。

然而在环信基于IM长连接技术推出移动客服之前,业界并没有一款真正适合移动端和社交化时代的可靠的云端移动客服产品。此前,业界普遍存在的是两种移动客服产品,一类是工单客服,可以被视为移动客服1.0,基于工单方式和客服交互,技术实现简单,但无法做到实时交互,沟通效率低,用户体验差。另一类是轮询技术客服,可以被视为移动客服2.0,基于HTTP轮询技术,通过不断向服务器发送查询请求来准实时的收取消息。不能做到实时收取消息,流量和电量消耗高,APP在后台时无法接收消息,容易丢失客户。

而环信推出的移动客服产品是业界唯一一款具有IM长连接技术的移动客服产品,这被视为更适合移动端的客服产品。这一类型的移动客服可以定义为“交互型智能移动客服”,可以被视为移动客服3.0,以环信为代表的这一类新型移动客服是基于亿级IM长连接,系统稳定;智能机器人技术可处理大部分重复问题。相较环信移动客服的能力,传统的电话、工单、轮询客服在移动端和社交趋势下就显得捉襟见肘,有些OUT了。

环信移动客服实现了跨平台多渠道接入:支持 App、微信公众账号、微博、网页等,均可以快速统一接入客户服务后台管理。

其次,满足了开放性与自定义信息:这种新型的移动客服实现了代码开源、UI开源,还提供多套UI模版,便于与APP快速集成,平滑接入。同时第三方集成功能也很强大,可与第三方工单、知识库、CRM 系统等进行扩展集成。

第三,富媒体消息交互体验:移动客服平台提供了基于IM技术的类似微信体验的友好富媒体消息交互,不仅可以实时收发文字、表情,还可以即时收发图片、位置、实时语音、还可自定义消息,大大方便了与客户的沟通交流。

第四,精准客户画像功能:移动客服的IM沟通帮助企业辅助判断客户需求与诉求,通过自定义客户分类标签,客户再次访问时可获知客户的类型。并且还支持自定义会话小结,根据会话小结统计会话的分类,通过会话小结追踪客户诉求。通过轨迹分析功能,即通过发送客户访问页面的轨迹,判断客户意图,获取客户个性化细节,了解客户基础信息,分析客户行为,可以极大提高订单效率。

第五,“智能机器人+智能知识库”:作为一套智能化的客服系统,让企业建立基于业务的智能知识库,智能辅助归结业务信息和应答客户信息,历史常见问题系统梳理,提高客服效率。“智能机器人+智能知识库”组合目前可自动回复80%常见问题,随着智能知识库的不断训练,这一比例能够提高到90%。
0
评论

环信ONE SDK架构介绍 移动开发

admin 发表了文章 • 1301 次浏览 • 2015-08-10 15:41 • 来自相关话题

环信即时通讯SDK自2014年6月正式发布2.0版本至今已走过一个年头,从基本的单聊功能,到群聊功能,再到聊天室的实现,SDK不管是功能,稳定性,还是易集成性都在一步一步的走向完善与稳定,感谢开发者们给与提供的反馈与帮助,使我们的SDK迅速的在诸多方面得到提高与改进。

随着现在物联网的兴起,环信现在的SDK的架构对应对未来物联网平台还是略有不足,使我们不得不在今年年初就考虑到如何去改善我们的架构,使之能够较容易的适配到各个主流平台和物联网平台。

现在的Android, IOS, SDK都是各自维护了自己逻辑,给2.0开发带来了很多不便,相同的功能需要维护两份代码,同一个bug要在不同的平台修复两次,由于不同平台的实现,导致Android,IOS架构设计不统一,API不一致,再加上在不同的平台开发的工程师之间由于不同的实现导致沟通问题诸多,这样导致的问题就是,不同平台的开发进度大多数情况下都不相同。

所以针对以上的问题,我们今年年初就计划我们SDK3.0的开发,我们称之为ONE SDK,基本的理念就是我们实现共同IM 内核,使代码可被不同的平台最大化的重用,但是设计和实现却是面临着巨大的挑战,如何适配到不同的平台,如何最大化的重用代码都是要面临的问题。

ONE SDK 架构设计
总体设计






ONE SDK的设计总体分为3层,平台层-Platfrom layer,适配层-Porting layer,核心层-Common layer.

平台层会根据各平台的不同,实现不同的接口,开放符合平台层的API给第三方开发者。

适配层主要要适配到ONE SDK 核心层所需要的一些接口,起到承上启下的作用。

核心层主要提供IM 功能和业务逻辑,保证最大化的代码重用。

考虑到跨平台共享代码,我们ONE SDK主要是用C++这种跨平台的语言来实现。

平台层

我们计划要支持的平台为Android,IOS,MAC OS,Windows,Windows phone, Linux,Embedded Linux, 还有较为广泛应用的物联网平台-IOT OS。

我们会针对不同平台提供给开发者,和平台一致API规范,使各平台的开发者无难度的集成SDK,例如我们会提供JAVA给Android,Objective-C 给IOS和MAC, C++ 给Linux, IOT平台。


适配层






适配层主要就是各平台需要实现核心层所需要的一些接口类例如,上图给出的线程模型,定时器模型,数据库模型,还有HTTP模型。

这些模型都是和平台相关的,例如有的平台提供sqllite的访问,有的没有,有的线程模型和定时器模型都有自己的实现方式例如物联网IOT OS,所以实现了上述的模型,就可以使核心层可以工作,不过也可能会遇到一些问题,这都会在具体的实现中会具体的应对,但结构是清晰的。

其实例如Android,Linux, IOS, Mac OS,Windows都是支持C++11,也就是说都是支持C++11所提供的线程模型,所以这几个操作系统的线程模型的实现应该是同样的,所以代码是可以共享的, 但是数据库Anroid NDK是不支持sqlite访问,所以这部分Android有两种策略一个是集成sqlite源代码,二是回调给JAVA层,前一种策略是代码逻辑清晰,但坏处就是增加了代码量。

还有就是HTTP模型,默认的android,iOS,Mac OS,windows都有自己的API提供,所以ONE SDK策略就是如果有平台有原生的HTTP API 支持我们就会尽量用平台的,但是类似linux,就需要第三方库的支持例如libcurl.

所以综上所述适配层的意义重大,保证我们ONE SDK代码共享最大化的目的。

核心层

核心层是具体实现环信相关功能的模块,它里面也包含的几个部分,核心业务逻辑API实现,抽象协议层,和独立实时音视频模块。

Core Common






业务逻辑层,负责提供基本的IM功能。

会话管理
消息收发
登录鉴权
连接管理

Audio/Video Call

实时音视频模块是一个独立的模块,可以单独存在,这样可以灵活处理,不需要时不用加载此模块。






实时音视频
多人语音

Abstract Protocol Layer

协议抽象层,主要用来处理具体的IM底层协议,这层是比较独立的主要实现环信定义的IM传输协议,也为为日后协议改造,扩展提供承上启下的作用。





定义抽象消息载体基本的消息发送基本的消息回调定义基本的通知
上述ONE SDK架构是我们计划要实现的,现在一些基本的设计已经在Linux SDK上得到了实现,下面让我们继续了解下Linux SDK。

Linux SDK

经过几个月的开发,我们已经推出了Linux SDK测试版,有兴趣的开发者可以小试一下去我们的官网 http://www.easemob.com/downloads 下载。

通过EMChatClient Facade类开发者可以访问到任何IM停供的功能
登录注册消息收发,支持TXT, IMAGE, VIDEO, AUDIO, FILE, LOCATION, 类型的message会话管理联系人管理

在开发linux SDK的时候我们利用了C++11提供的很多优良feature,例如lambda,shared ptr,thread等较新的功能,通过这些功能的使用,让我们能够迅速并且高效的开发出Linux SDK测试版。

Lambda是我们的代码逻辑阅读起来更清楚,shared ptr使我们对内存的管理更为简单,thread的使用使我们能迅速的建立好线程模型,加快开发的速度。

我们在Linux SDK porting layer实现了线程模型,数据库模型,定时器模型和HTTP模型
线程模型,利用C++11的thread进行封装数据库模型,使用Linux的sqliteHTTP模型,我们使用了Libcurl进行了封装定时器模型,我们使用了C++11进行了封装

我们对Linux SDK还在紧锣密鼓,夜以继日的紧张开发中,群组和实时音视频功能还在开发中,但是在开发过程中我们也遇到了些的问题,例如不linux平台对库的支持也不尽相同,所以势必会对我们的架构有些改变,有些重构的工作也在进行中,我们希望8月底能够实现大部分的功能。

选择linux SDK为开始主要是因为大多数的嵌入式智能平台还是以linux为主,所以首先开发Linux 版SDK也是必先的一步,感谢我们的工程师,我么的Linux SDK已经能够支持树莓派的开发环境,这对于很多开发者来说确实是个好消息。

如果想了解如何集成Linux SDK请参考环信IM Linux SDK 集成说明

展望

Linux SDK 只是实现我们ONE SDK 的第一步,我们下半年还要实现基于ONE SDK 的Android ,IOS,MAC OS, 还有主流物联网平台的SDK,通过借鉴Linux SDK的实现方式,我们认为实现ONE SDK是可以做到的。

我们还会进一步和主要IOT平台供应商合作,实现某个具体IOT平台的环信SDK,使环信即时通讯平台生态圈更加壮大。 查看全部
环信即时通讯SDK自2014年6月正式发布2.0版本至今已走过一个年头,从基本的单聊功能,到群聊功能,再到聊天室的实现,SDK不管是功能,稳定性,还是易集成性都在一步一步的走向完善与稳定,感谢开发者们给与提供的反馈与帮助,使我们的SDK迅速的在诸多方面得到提高与改进。

随着现在物联网的兴起,环信现在的SDK的架构对应对未来物联网平台还是略有不足,使我们不得不在今年年初就考虑到如何去改善我们的架构,使之能够较容易的适配到各个主流平台和物联网平台。

现在的Android, IOS, SDK都是各自维护了自己逻辑,给2.0开发带来了很多不便,相同的功能需要维护两份代码,同一个bug要在不同的平台修复两次,由于不同平台的实现,导致Android,IOS架构设计不统一,API不一致,再加上在不同的平台开发的工程师之间由于不同的实现导致沟通问题诸多,这样导致的问题就是,不同平台的开发进度大多数情况下都不相同。

所以针对以上的问题,我们今年年初就计划我们SDK3.0的开发,我们称之为ONE SDK,基本的理念就是我们实现共同IM 内核,使代码可被不同的平台最大化的重用,但是设计和实现却是面临着巨大的挑战,如何适配到不同的平台,如何最大化的重用代码都是要面临的问题。

ONE SDK 架构设计
总体设计

20150806175739849.png


ONE SDK的设计总体分为3层,平台层-Platfrom layer,适配层-Porting layer,核心层-Common layer.

平台层会根据各平台的不同,实现不同的接口,开放符合平台层的API给第三方开发者。

适配层主要要适配到ONE SDK 核心层所需要的一些接口,起到承上启下的作用。

核心层主要提供IM 功能和业务逻辑,保证最大化的代码重用。

考虑到跨平台共享代码,我们ONE SDK主要是用C++这种跨平台的语言来实现。

平台层

我们计划要支持的平台为Android,IOS,MAC OS,Windows,Windows phone, Linux,Embedded Linux, 还有较为广泛应用的物联网平台-IOT OS。

我们会针对不同平台提供给开发者,和平台一致API规范,使各平台的开发者无难度的集成SDK,例如我们会提供JAVA给Android,Objective-C 给IOS和MAC, C++ 给Linux, IOT平台。


适配层

20150806181806647.png


适配层主要就是各平台需要实现核心层所需要的一些接口类例如,上图给出的线程模型,定时器模型,数据库模型,还有HTTP模型。

这些模型都是和平台相关的,例如有的平台提供sqllite的访问,有的没有,有的线程模型和定时器模型都有自己的实现方式例如物联网IOT OS,所以实现了上述的模型,就可以使核心层可以工作,不过也可能会遇到一些问题,这都会在具体的实现中会具体的应对,但结构是清晰的。

其实例如Android,Linux, IOS, Mac OS,Windows都是支持C++11,也就是说都是支持C++11所提供的线程模型,所以这几个操作系统的线程模型的实现应该是同样的,所以代码是可以共享的, 但是数据库Anroid NDK是不支持sqlite访问,所以这部分Android有两种策略一个是集成sqlite源代码,二是回调给JAVA层,前一种策略是代码逻辑清晰,但坏处就是增加了代码量。

还有就是HTTP模型,默认的android,iOS,Mac OS,windows都有自己的API提供,所以ONE SDK策略就是如果有平台有原生的HTTP API 支持我们就会尽量用平台的,但是类似linux,就需要第三方库的支持例如libcurl.

所以综上所述适配层的意义重大,保证我们ONE SDK代码共享最大化的目的。

核心层

核心层是具体实现环信相关功能的模块,它里面也包含的几个部分,核心业务逻辑API实现,抽象协议层,和独立实时音视频模块。

Core Common

20150806191008517.png


业务逻辑层,负责提供基本的IM功能。

会话管理
消息收发
登录鉴权
连接管理

Audio/Video Call

实时音视频模块是一个独立的模块,可以单独存在,这样可以灵活处理,不需要时不用加载此模块。

20150806191418690.png


实时音视频
多人语音

Abstract Protocol Layer

协议抽象层,主要用来处理具体的IM底层协议,这层是比较独立的主要实现环信定义的IM传输协议,也为为日后协议改造,扩展提供承上启下的作用。

20150806192326297.png

  • 定义抽象消息载体
  • 基本的消息发送
  • 基本的消息回调
  • 定义基本的通知

上述ONE SDK架构是我们计划要实现的,现在一些基本的设计已经在Linux SDK上得到了实现,下面让我们继续了解下Linux SDK。

Linux SDK

经过几个月的开发,我们已经推出了Linux SDK测试版,有兴趣的开发者可以小试一下去我们的官网 http://www.easemob.com/downloads 下载。

通过EMChatClient Facade类开发者可以访问到任何IM停供的功能
  • 登录注册
  • 消息收发,支持TXT, IMAGE, VIDEO, AUDIO, FILE, LOCATION, 类型的message
  • 会话管理
  • 联系人管理


在开发linux SDK的时候我们利用了C++11提供的很多优良feature,例如lambda,shared ptr,thread等较新的功能,通过这些功能的使用,让我们能够迅速并且高效的开发出Linux SDK测试版。

Lambda是我们的代码逻辑阅读起来更清楚,shared ptr使我们对内存的管理更为简单,thread的使用使我们能迅速的建立好线程模型,加快开发的速度。

我们在Linux SDK porting layer实现了线程模型,数据库模型,定时器模型和HTTP模型
  • 线程模型,利用C++11的thread进行封装
  • 数据库模型,使用Linux的sqlite
  • HTTP模型,我们使用了Libcurl进行了封装
  • 定时器模型,我们使用了C++11进行了封装


我们对Linux SDK还在紧锣密鼓,夜以继日的紧张开发中,群组和实时音视频功能还在开发中,但是在开发过程中我们也遇到了些的问题,例如不linux平台对库的支持也不尽相同,所以势必会对我们的架构有些改变,有些重构的工作也在进行中,我们希望8月底能够实现大部分的功能。

选择linux SDK为开始主要是因为大多数的嵌入式智能平台还是以linux为主,所以首先开发Linux 版SDK也是必先的一步,感谢我们的工程师,我么的Linux SDK已经能够支持树莓派的开发环境,这对于很多开发者来说确实是个好消息。

如果想了解如何集成Linux SDK请参考环信IM Linux SDK 集成说明

展望

Linux SDK 只是实现我们ONE SDK 的第一步,我们下半年还要实现基于ONE SDK 的Android ,IOS,MAC OS, 还有主流物联网平台的SDK,通过借鉴Linux SDK的实现方式,我们认为实现ONE SDK是可以做到的。

我们还会进一步和主要IOT平台供应商合作,实现某个具体IOT平台的环信SDK,使环信即时通讯平台生态圈更加壮大。
2
评论

开发经验:如何优雅的进行页面间的跳转 移动开发 iOS

oscar1212 发表了文章 • 1759 次浏览 • 2015-07-31 14:57 • 来自相关话题

在你的开发过程中,是否遇到过如下的需求:
在tableView类型的展示列表中,点击每个cell中人物头像都可以跳转到人物详情,可参见微博中的头像,同理包括转发、评论按钮、各种链接及linkcard。跳转到任意页面
产品要求,某个页面的不同banner图,点击可以跳转到任何一个页面,可能是原生的页面A、页面B,或者是web页C。在web页面,可以跳转到任何一个原生页面。在远程推送中跳转到任意指定的页面。

以上2种需求,我想大多数开发者都遇到过,并且可以实现这种功能。毕竟,这是比较基础的功能。但是代码未必那么优雅。

一般处理办法

针对1.,一般初学者会用target或者block等方法在tableView的代理方法拿到事件,并把要执行的跳转写到controller里。功能是可以实现的,但问题是这种cell及相似的cell(布局有些变化,或者多几个少几个控件)一般出现在多个页面。这样的话相同的代码就会出现在多个地方。就算把跳转方法抽取出来写成category,但是target或者block总是每个地方都要写的。
针对2.,初级的方法是每个地方写一坨判断及跳转,高级一些是抽取出来写在基类或者category。

优雅的解决办法

纵观上面各种情况,总结起来就是一句话,在任意的地方触发事件(可以是推送,拦截的js跳转,各种控件的点击事件)可以跳转到任意界面。所以我们可以统一用一个控制跳转的manager来完成跳转。
与后端约定好数据结构,例如:
NSDictionary *target = @{@"action" : @"user",
@"data" : @{@"user_id" : @(123456)}};



就是跳转到id为123456的用户页面,如果跳转需要更多的数据,可以在data的value里面继续添加。
创建一个用来跳转的类,可以起的牛x的名字,XXCoreActionManager。
创建一个类方法:+ (BOOL)doActionForTarget:(NSDictionary *)target{
//根据你的app结构,来取得你当前的controller,由它来进行跳转
UIApplication *application = [UIApplication sharedApplication];
AppDelegate *myAppDelegate = (AppDelegate *)[application delegate];
UIViewController *viewController;
if ([myAppDelegate getTabbarSelectedView]) {
viewController = [myAppDelegate getTabbarSelectedView].visibleViewController;
}else {
return NO;
}

if([json[@"action"] isEqualToString:@"film_view"]){
MFMaterialListViewController *materialListVC = [[MFMaterialListViewController alloc] initWithNibName:@"MFMaterialListViewController" bundle:nil];
materialListVC.hidesBottomBarWhenPushed = YES;
materialListVC.filmId = json[@"data"][@"film_id"];
[viewController.navigationController pushViewController:materialListVC animated:YES];
return YES;
}else if([json[@"action"] isEqualToString:@"home"]){
[myAppDelegate getTabbar].selectedIndex = 0;
[viewController.navigationController popToRootViewControllerAnimated:YES];
return YES;
}

return NO;
}在刚才定义的数据结构中,action的值为需要跳转的页面,data的值跳转所需要要的参数,比如id、type等。服务器只需要传入相应的数据就可以用[XXCoreActionManager doActionForTarget:target];




针对头像、评论、转发等多处使用的子控件,可以把事件由自己接收,通过XXCoreActionManager来进行跳转。即做到了代码分离,使之成为真正独立的控件,便于复用。

下面是一个简单例子:implementation MFUserHeadButton
-(void)awakeFromNib{
[self addTarget:self action:@selector(toUserDetail) forControlEvents:UIControlEventTouchUpInside];

}

- (void)toUserDetail{
NSDictionary *target = @{@"action":@"user",
@"data":@{@"user_id":@(self.tag)}};
[XXCoreActionManager doActionForTarget:target];

}这就是一个简单的实现跳转到个人页功能的头像控件实现。

如果你问user_id的值怎么来的?

当然是configCell的时候传给view的tag的。

你可能会说,我的跳转需要多个参数啊,你一个tag不够用啊亲。

可以定义一个NSDictionary属性接收啊。

如果你用原生的UI控件,那让强大的runtime给你加喽- (void)setDict:(NSDictionary *)dict {
objc_setAssociatedObject(self, dictKey, dict, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (NSDictionary *)dict {
return objc_getAssociatedObject(self, dictKey);
}总结
通过XXCoreActionManager,你可以做到无论你身在何处(哪一个controller),要到何处去(跳转到哪一个controller),你只需要叫来XXCoreActionManager,告诉它你的目的地(target)。你就可以做到想跳就跳。真正的write once,use anywhere。针对各种有跳转功能的控件,可以做到真的解耦。只需要把它放到他需要显示的位置。告诉它对应的参数就可以了。方便复用和后期的维护。这次想说的只是一个思路,代码很简单。其实可以使用的地方还有很多。不只是跳转各位童鞋可以自己思考。有什么不明白的可以留言,如果觉得那里不合适更欢迎留言指教或交流。

写在后面的废话

从读大学接触到计算机技术这一领域,我就被这个圈子的氛围深深的触动了,这是一个如此自由、分享、开放的圈子。我从无数人的的分享中汲取着知识(开源的代码,分享的博客),我受益于这种环境,我就想对它做出回馈,写出这篇文章,即希望能帮助一些人,也希望能与大家有更多的交流。最后,谢谢那些无私的做出各种奉献的人。
 
来源:csdn 查看全部
在你的开发过程中,是否遇到过如下的需求:
  1. 在tableView类型的展示列表中,点击每个cell中人物头像都可以跳转到人物详情,可参见微博中的头像,同理包括转发、评论按钮、各种链接及linkcard。
  2. 跳转到任意页面

  • 产品要求,某个页面的不同banner图,点击可以跳转到任何一个页面,可能是原生的页面A、页面B,或者是web页C。
  • 在web页面,可以跳转到任何一个原生页面。
  • 在远程推送中跳转到任意指定的页面。


以上2种需求,我想大多数开发者都遇到过,并且可以实现这种功能。毕竟,这是比较基础的功能。但是代码未必那么优雅。

一般处理办法

针对1.,一般初学者会用target或者block等方法在tableView的代理方法拿到事件,并把要执行的跳转写到controller里。功能是可以实现的,但问题是这种cell及相似的cell(布局有些变化,或者多几个少几个控件)一般出现在多个页面。这样的话相同的代码就会出现在多个地方。就算把跳转方法抽取出来写成category,但是target或者block总是每个地方都要写的。
针对2.,初级的方法是每个地方写一坨判断及跳转,高级一些是抽取出来写在基类或者category。

优雅的解决办法

纵观上面各种情况,总结起来就是一句话,在任意的地方触发事件(可以是推送,拦截的js跳转,各种控件的点击事件)可以跳转到任意界面。所以我们可以统一用一个控制跳转的manager来完成跳转。
  • 与后端约定好数据结构,例如:

NSDictionary *target = @{@"action" : @"user",
@"data" : @{@"user_id" : @(123456)}};



就是跳转到id为123456的用户页面,如果跳转需要更多的数据,可以在data的value里面继续添加。
  • 创建一个用来跳转的类,可以起的牛x的名字,XXCoreActionManager。

创建一个类方法:
+ (BOOL)doActionForTarget:(NSDictionary *)target{
//根据你的app结构,来取得你当前的controller,由它来进行跳转
UIApplication *application = [UIApplication sharedApplication];
AppDelegate *myAppDelegate = (AppDelegate *)[application delegate];
UIViewController *viewController;
if ([myAppDelegate getTabbarSelectedView]) {
viewController = [myAppDelegate getTabbarSelectedView].visibleViewController;
}else {
return NO;
}

if([json[@"action"] isEqualToString:@"film_view"]){
MFMaterialListViewController *materialListVC = [[MFMaterialListViewController alloc] initWithNibName:@"MFMaterialListViewController" bundle:nil];
materialListVC.hidesBottomBarWhenPushed = YES;
materialListVC.filmId = json[@"data"][@"film_id"];
[viewController.navigationController pushViewController:materialListVC animated:YES];
return YES;
}else if([json[@"action"] isEqualToString:@"home"]){
[myAppDelegate getTabbar].selectedIndex = 0;
[viewController.navigationController popToRootViewControllerAnimated:YES];
return YES;
}

return NO;
}
在刚才定义的数据结构中,action的值为需要跳转的页面,data的值跳转所需要要的参数,比如id、type等。服务器只需要传入相应的数据就可以用
[XXCoreActionManager doActionForTarget:target];




  • 针对头像、评论、转发等多处使用的子控件,可以把事件由自己接收,通过XXCoreActionManager来进行跳转。即做到了代码分离,使之成为真正独立的控件,便于复用。


下面是一个简单例子:
implementation MFUserHeadButton
-(void)awakeFromNib{
[self addTarget:self action:@selector(toUserDetail) forControlEvents:UIControlEventTouchUpInside];

}

- (void)toUserDetail{
NSDictionary *target = @{@"action":@"user",
@"data":@{@"user_id":@(self.tag)}};
[XXCoreActionManager doActionForTarget:target];

}
这就是一个简单的实现跳转到个人页功能的头像控件实现。

如果你问user_id的值怎么来的?

当然是configCell的时候传给view的tag的。

你可能会说,我的跳转需要多个参数啊,你一个tag不够用啊亲。

可以定义一个NSDictionary属性接收啊。

如果你用原生的UI控件,那让强大的runtime给你加喽
- (void)setDict:(NSDictionary *)dict {
objc_setAssociatedObject(self, dictKey, dict, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (NSDictionary *)dict {
return objc_getAssociatedObject(self, dictKey);
}
总结
  1. 通过XXCoreActionManager,你可以做到无论你身在何处(哪一个controller),要到何处去(跳转到哪一个controller),你只需要叫来XXCoreActionManager,告诉它你的目的地(target)。你就可以做到想跳就跳。真正的write once,use anywhere。
  2. 针对各种有跳转功能的控件,可以做到真的解耦。只需要把它放到他需要显示的位置。告诉它对应的参数就可以了。方便复用和后期的维护。
  3. 这次想说的只是一个思路,代码很简单。其实可以使用的地方还有很多。不只是跳转各位童鞋可以自己思考。有什么不明白的可以留言,如果觉得那里不合适更欢迎留言指教或交流。


写在后面的废话

从读大学接触到计算机技术这一领域,我就被这个圈子的氛围深深的触动了,这是一个如此自由、分享、开放的圈子。我从无数人的的分享中汲取着知识(开源的代码,分享的博客),我受益于这种环境,我就想对它做出回馈,写出这篇文章,即希望能帮助一些人,也希望能与大家有更多的交流。最后,谢谢那些无私的做出各种奉献的人。
 
来源:csdn
0
评论

环信移动客服3.0上线签约国美在线、58到家、楚楚街9块9等龙头企业 开发者 移动开发 环信

admin 发表了文章 • 2125 次浏览 • 2015-07-29 11:23 • 来自相关话题

7月28日,环信B轮融资及移动客服新品发布会在北京JW万豪酒店举行。发布会上,环信CEO刘俊彦宣布,环信成功获得B轮融资,同时环信移动客服3.0产品也正式上线,而环信将以“连接人与商业”为愿景,开启万亿级企业云服务市场。






据悉,环信移动客服产品已经有国美在线、58到家、楚楚街等大批龙头企业签约,累计签约客服座席已经达4万个,而按艾媒咨询的报告显示,环信已占据市场份额第一的宝座。

发布会现场,据启动环信移动客服3.0产品上线的环信CTO马晓宇介绍,环信之所以受到市场如此欢迎,是因为环信移动客服是有别于传统客服的划时代产品。在环信CTO马晓宇看来,客服经历了三个时代——
传统 call center的时代: 互联网尚未普及,电话客服客户等待时间长,客户服务人员压力大,工作重复内容多;到了PC网页客服时代,随着互联网的普及,网页客服的成本明显小于电话客服,客户服务人员工作量较小,客户满意度有所提高,但相应依然不能及时有效;当今,随着智能手机用户的快速增长,客户要求能够随时在移动端获取咨询服务。移动端客服的重要性将不断上升。移动客服时代随之到来。





然而在环信基于IM长连接技术推出移动客服之前,业界并没有一款真正适合移动端和社交化时代的可靠的云端移动客服产品。此前,业界普遍存在的是两种移动客服产品,
一类是工单客服,可以被视为移动客服1.0,基于工单方式和客服交互,技术实现简单,但无法做到实时交互,沟通效率低,用户体验差。另一类是轮询技术客服,可以被视为移动客服2.0,基于HTTP轮询技术,通过不断向服务器发送查询请求来准实时的收取消息。不能做到实时收取消息,流量和电量消耗高,APP在后台时无法接收消息,容易丢失客户。
而环信推出的移动客服产品是业界唯一一款具有IM长连接技术的移动客服产品,这被视为更适合移动端的客服产品。

这一类型的移动客服可以定义为“交互型智能移动客服”,可以被视为移动客服3.0,以环信为代表的这一类新型移动客服是基于亿级IM长连接,系统稳定;智能机器人技术可处理大部分重复问题。相较环信移动客服的能力,传统的电话、工单、轮询客服在移动端和社交趋势下就显得捉襟见肘,有些OUT了。
 
环信移动客服实现了跨平台多渠道接入:支持 App、微信公众账号、微博、网页等,均可以快速统一接入客户服务后台管理。





其次,满足了开放性与自定义信息:这种新型的移动客服实现了代码开源、UI开源,还提供多套UI模版,便于与APP快速集成,平滑接入。同时第三方集成功能也很强大,可与第三方工单、知识库、CRM 系统等进行扩展集成。第三,富媒体消息交互体验:移动客服平台提供了基于IM技术的类似微信体验的友好富媒体消息交互,不仅可以实时收发文字、表情,还可以即时收发图片、位置、实时语音、还可自定义消息,大大方便了与客户的沟通交流。第四,精准客户画像功能:移动客服的IM沟通帮助企业辅助判断客户需求与诉求,通过自定义客户分类标签,客户再次访问时可获知客户的类型。并且还支持自定义会话小结,根据会话小结统计会话的分类,通过会话小结追踪客户诉求。通过轨迹分析功能,即通过发送客户访问页面的轨迹,判断客户意图,获取客户个性化细节,了解客户基础信息,分析客户行为,可以极大提高订单效率。第五,“智能机器人+智能知识库”:作为一套智能化的客服系统,让企业建立基于业务的智能知识库,智能辅助归结业务信息和应答客户信息,历史常见问题系统梳理,提高客服效率。“智能机器人+智能知识库”组合目前可自动回复80%常见问题,随着智能知识库的不断训练,这一比例能够提高到90%。第六、真正实现不丢订单:环信是中国乃至全球领先的即时通讯云服务提供商,上线1年来,已成为唯一一家经历了亿级长连接真实稳定运行的即时通讯云平台,中国主流的采用第三方即时通讯云服务的App几乎都是环信的客户,每日环信平台的消息量达到数亿条,有着即时通讯云领域亿级长连接的绝对垄断优势。环信基于IM长连接技术,帮助企业实现超线拉取排队会话,让等待时间过长或有订单需求的客户得到优先服务,提升客服效率,即使客户关闭会话,退出App,甚至关闭手机,基于IM长连接技术依然能找回客户会话,提升客服效率,不丢客户订单。同时,基于IM长连接技术,即使在断网或复杂网络切换时也依然能找回客户会话,不丢客户订单。第七、实现了质检系统透明管理:移动客服自带实时监控系统,可实时监控当前所有会话,管理员在线质检,在线查看会话信息,还提供了历史会话查询、质检考核。通过实时与历史查看,可以统计出客服代表的接入量、在线时间及应答等待时间。





环信CTO Johnson向大家介绍客服产品

总之,通过部署环信移动客服,较于传统客服产品可以节省成本约60%,在移动端省电省流量高达80%,同时留住70%会话客户,订单量和客单价均可以获得不同幅度提升。 查看全部
7月28日,环信B轮融资及移动客服新品发布会在北京JW万豪酒店举行。发布会上,环信CEO刘俊彦宣布,环信成功获得B轮融资,同时环信移动客服3.0产品也正式上线,而环信将以“连接人与商业”为愿景,开启万亿级企业云服务市场。

5.png


据悉,环信移动客服产品已经有国美在线、58到家、楚楚街等大批龙头企业签约,累计签约客服座席已经达4万个,而按艾媒咨询的报告显示,环信已占据市场份额第一的宝座

发布会现场,据启动环信移动客服3.0产品上线的环信CTO马晓宇介绍,环信之所以受到市场如此欢迎,是因为环信移动客服是有别于传统客服的划时代产品。在环信CTO马晓宇看来,客服经历了三个时代——
  1. 传统 call center的时代: 互联网尚未普及,电话客服客户等待时间长,客户服务人员压力大,工作重复内容多;
  2. 到了PC网页客服时代,随着互联网的普及,网页客服的成本明显小于电话客服,客户服务人员工作量较小,客户满意度有所提高,但相应依然不能及时有效;
  3. 当今,随着智能手机用户的快速增长,客户要求能够随时在移动端获取咨询服务。移动端客服的重要性将不断上升。移动客服时代随之到来。


9.png

然而在环信基于IM长连接技术推出移动客服之前,业界并没有一款真正适合移动端和社交化时代的可靠的云端移动客服产品。此前,业界普遍存在的是两种移动客服产品
  1. 一类是工单客服,可以被视为移动客服1.0,基于工单方式和客服交互,技术实现简单,但无法做到实时交互,沟通效率低,用户体验差。
  2. 另一类是轮询技术客服,可以被视为移动客服2.0,基于HTTP轮询技术,通过不断向服务器发送查询请求来准实时的收取消息。不能做到实时收取消息,流量和电量消耗高,APP在后台时无法接收消息,容易丢失客户。

而环信推出的移动客服产品是业界唯一一款具有IM长连接技术的移动客服产品,这被视为更适合移动端的客服产品。

这一类型的移动客服可以定义为“交互型智能移动客服”,可以被视为移动客服3.0,以环信为代表的这一类新型移动客服是基于亿级IM长连接,系统稳定;智能机器人技术可处理大部分重复问题。相较环信移动客服的能力,传统的电话、工单、轮询客服在移动端和社交趋势下就显得捉襟见肘,有些OUT了。
 
  • 环信移动客服实现了跨平台多渠道接入:支持 App、微信公众账号、微博、网页等,均可以快速统一接入客户服务后台管理。


8.png

  • 其次,满足了开放性与自定义信息:这种新型的移动客服实现了代码开源、UI开源,还提供多套UI模版,便于与APP快速集成,平滑接入。同时第三方集成功能也很强大,可与第三方工单、知识库、CRM 系统等进行扩展集成。
  • 第三,富媒体消息交互体验:移动客服平台提供了基于IM技术的类似微信体验的友好富媒体消息交互,不仅可以实时收发文字、表情,还可以即时收发图片、位置、实时语音、还可自定义消息,大大方便了与客户的沟通交流。
  • 第四,精准客户画像功能:移动客服的IM沟通帮助企业辅助判断客户需求与诉求,通过自定义客户分类标签,客户再次访问时可获知客户的类型。并且还支持自定义会话小结,根据会话小结统计会话的分类,通过会话小结追踪客户诉求。通过轨迹分析功能,即通过发送客户访问页面的轨迹,判断客户意图,获取客户个性化细节,了解客户基础信息,分析客户行为,可以极大提高订单效率。
  • 第五,“智能机器人+智能知识库”:作为一套智能化的客服系统,让企业建立基于业务的智能知识库,智能辅助归结业务信息和应答客户信息,历史常见问题系统梳理,提高客服效率。“智能机器人+智能知识库”组合目前可自动回复80%常见问题,随着智能知识库的不断训练,这一比例能够提高到90%。
  • 第六、真正实现不丢订单:环信是中国乃至全球领先的即时通讯云服务提供商,上线1年来,已成为唯一一家经历了亿级长连接真实稳定运行的即时通讯云平台,中国主流的采用第三方即时通讯云服务的App几乎都是环信的客户,每日环信平台的消息量达到数亿条,有着即时通讯云领域亿级长连接的绝对垄断优势。环信基于IM长连接技术,帮助企业实现超线拉取排队会话,让等待时间过长或有订单需求的客户得到优先服务,提升客服效率,即使客户关闭会话,退出App,甚至关闭手机,基于IM长连接技术依然能找回客户会话,提升客服效率,不丢客户订单。同时,基于IM长连接技术,即使在断网或复杂网络切换时也依然能找回客户会话,不丢客户订单。
  • 第七、实现了质检系统透明管理:移动客服自带实时监控系统,可实时监控当前所有会话,管理员在线质检,在线查看会话信息,还提供了历史会话查询、质检考核。通过实时与历史查看,可以统计出客服代表的接入量、在线时间及应答等待时间。


6.png

环信CTO Johnson向大家介绍客服产品

总之,通过部署环信移动客服,较于传统客服产品可以节省成本约60%,在移动端省电省流量高达80%,同时留住70%会话客户,订单量和客单价均可以获得不同幅度提升。
0
评论

gcm推送 移动开发 Android

admin 发表了文章 • 6800 次浏览 • 2015-07-27 15:12 • 来自相关话题

一.gcm前期准备





 
Apple有apns推送,Google有gcm推送,iOS接收通知调用系统通知栏提示,Android接收通知启动应用调用通知栏提示。
相对于apns,gcm则多了一些限制,需要一些必备条件达到才可以使用。
1.在国内,首先就是Google被墙,无法连接到Google服务器,需要你走VPN或者其它方式可以连接到Google服务器。
2.在你的开发环境下,需要通过Android SDK Manager—>Extras下安装Google Play services,成功之后在你的SDK文件/sdk/extras/google/google_play_services/libproject下会看到google-play-services_lib类库,可以从里面直接复制jar包到你的项目libs下
3.Android客户端,要求安装了Google核心服务Google Play服务,Google Play 商店才能使用gcm





以上是Google官方文档描述:
大意就是gcm要求设备运行在Android系统2.2或更高版本并且安装了Google play商店应用,或者虚拟机运行在Android系统2.2版本的并且支持Google API,但是并不限制你的应用必须部署在Google play 商店。
然而,如果你想要使用gcm 新的API就需要设备运行在Android系统2.3或更高版本,或者使用虚拟机运行在Android系统2.3并且支持Google API
在一个现有连接Google服务的设备上,对于前置3.0的设备,就要求在Android设备上设置Google账号,4.0.4或者更高版本则不需要设置Google账号
注:gcm只是简单的推送一个通知到客户端,其消息内容应小于4Kb,Google服务器存储时间为4个星期。在客户端,gcm是通过客户端设备注册一个系统广播来唤醒应用并发出通知提示,所以这个时候客户端不需要一直运行来接收消息,gcm一次发送最多可发送100个用户
 
二.官网创建项目获取信息

去Google Developers Console(https://console.developers.google.com/project)创建项目,输入你的project name和project id,创建成功如下图:





在应用中我们会用到这个project number,再去Credentials下创建一个server key,得到的api key会在自己的服务器端用到,如图




顺便说一下,默认Cloud Messaging for Android是可用的,如果不能用,就需要去API & auth—> API下查看Cloud Messaging for Android是否disable

三.创建一个客户端app

首先要在AndroidManifest.xml文件配置gcm权限等信息<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />//当GCM需要谷歌账户(设备版本低于4.0.4时需要)
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission android:name="applicationPackage.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="applicationPackage.permission.C2D_MESSAGE" />
applicationPackage要改成自己的报名

android:minSdkVersion="8"不得低于8





根据官网文档介绍:

1.我们应该在配置文件注册一个系统广播<receiver
android:name="com.google.android.gms.gcm.GcmReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.example.gcm" />
</intent-filter>
</receiver>
2.注册监听通知服务(在app中创建一个服务类并继承GcmListenerService类)<pre name="code" class="html"><service
android:name="com.example.MyGcmListenerService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>

public class MyGcmListenerService extends GcmListenerService {

@Override
public void onMessageReceived(String from, Bundle data) {
String message = data.getString("message");
/**
* Production applications would usually process the message here.
* Eg: - Syncing with server.
* - Store message in local database.
* - Update UI.
*/

/**
* In some cases it may be useful to show a notification indicating to the user
* that a message was received.
*/
sendNotification(message);
}
// [END receive_message]

/**
* Create and show a simple notification containing the received GCM message.
*
* @param message GCM message received.
*/
private void sendNotification(String message) {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);

Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_stat_ic_notification)
.setContentTitle("this is a new new GCM Message")
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);

NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
}
 
3.注册监听token改变的服务(在app中创建一个服务类继承InstanceIDListenerService类,本服务存在于新的Google play服务版本上) android:name="com.example.MyInstanceIDListenerService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.gms.iid.InstanceID"/>
</intent-filter>
</service>

public class MyInstanceIDListenerService extends InstanceIDListenerService {

@Override
public void onTokenRefresh() {
// Fetch updated Instance ID token and notify our app's server of any changes (if applicable).
}
}
 
gcm通过注册的系统广播可以自行启动GcmListenerService类,所以不需要在app创建一个广播类

注册token

App发送 project number到GCM Server注册接收推送信息。 

GCM Server 向App返回token(token是GCM服务器自行生产的,能够保证某一终端设备上的某一个应用,很重要)。 
在设备上应该先判断是否安装了Google play 服务int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
GooglePlayServicesUtil.getErrorDialog(resultCode, this, PLAY_SERVICES_RESOLUTION_REQUEST).show();//会提示错误对话框,其他错误信息可参考官网API
} else {
Log.i(TAG, "This device is not supported.”);
}
 
 
Google play服务存在,那接下来就需要去注册token了,在上边创建项目得到的project number在这里就需要用它来注册token










 InstanceID instanceID = InstanceID.getInstance(this);
String token = instanceID.getToken(PROJECT_NUMBER,
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
 
对于旧版本还是要使用以下方式来注册token(用于Google play 服务7.5版本之前)GoogleCloudMessaging.getInstance(Context).register(PROJECT_NUMBER);
 
在自己的服务器端注册api key

App向我们自己服务器发送token(推送消息的时候要使用token,GCM服务器是使用token来确定某一终端设备上的某一个应用接收消息的,所以第三方服务器需要保存它,需要注意的是token很长,存数据库时需要注意字段长度) ,将我们在上边create new key 得到的apikey添加到自己的服务器端保存,我们的服务器向GCM Server发送消息,传递apikey和token ,GCM Server把消息推送给App 
最后注意一下,关于app卸载出现的问题,看一下官方的介绍






app会发生卸载过程并不能很快完成,卸载app需要花时间从GCM移除当前关联的token,这个过程就会出现发送消息是成功的,但是不能到达app客户端,在最后,token被移除了,服务器端发送的消息失败,得到一个NotRegistered错误,这个时候就应该在服务器端删除相对应的token 查看全部
一.gcm前期准备

20150727113000901_(1).jpg

 
Apple有apns推送,Google有gcm推送,iOS接收通知调用系统通知栏提示,Android接收通知启动应用调用通知栏提示。
相对于apns,gcm则多了一些限制,需要一些必备条件达到才可以使用。
1.在国内,首先就是Google被墙,无法连接到Google服务器,需要你走VPN或者其它方式可以连接到Google服务器。
2.在你的开发环境下,需要通过Android SDK Manager—>Extras下安装Google Play services,成功之后在你的SDK文件/sdk/extras/google/google_play_services/libproject下会看到google-play-services_lib类库,可以从里面直接复制jar包到你的项目libs下
3.Android客户端,要求安装了Google核心服务Google Play服务,Google Play 商店才能使用gcm

20150727113107623.jpg

以上是Google官方文档描述:
大意就是gcm要求设备运行在Android系统2.2或更高版本并且安装了Google play商店应用,或者虚拟机运行在Android系统2.2版本的并且支持Google API,但是并不限制你的应用必须部署在Google play 商店。
然而,如果你想要使用gcm 新的API就需要设备运行在Android系统2.3或更高版本,或者使用虚拟机运行在Android系统2.3并且支持Google API
在一个现有连接Google服务的设备上,对于前置3.0的设备,就要求在Android设备上设置Google账号,4.0.4或者更高版本则不需要设置Google账号
注:gcm只是简单的推送一个通知到客户端,其消息内容应小于4Kb,Google服务器存储时间为4个星期。在客户端,gcm是通过客户端设备注册一个系统广播来唤醒应用并发出通知提示,所以这个时候客户端不需要一直运行来接收消息,gcm一次发送最多可发送100个用户
 
二.官网创建项目获取信息

去Google Developers Console(https://console.developers.google.com/project)创建项目,输入你的project name和project id,创建成功如下图:

6.jpg

在应用中我们会用到这个project number,再去Credentials下创建一个server key,得到的api key会在自己的服务器端用到,如图
7.jpg

顺便说一下,默认Cloud Messaging for Android是可用的,如果不能用,就需要去API & auth—> API下查看Cloud Messaging for Android是否disable

三.创建一个客户端app

首先要在AndroidManifest.xml文件配置gcm权限等信息
<uses-permission android:name="android.permission.INTERNET" />  
<uses-permission android:name="android.permission.GET_ACCOUNTS" />//当GCM需要谷歌账户(设备版本低于4.0.4时需要)
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission android:name="applicationPackage.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="applicationPackage.permission.C2D_MESSAGE" />

applicationPackage要改成自己的报名

android:minSdkVersion="8"不得低于8

8.jpg

根据官网文档介绍:

1.我们应该在配置文件注册一个系统广播
<receiver  
android:name="com.google.android.gms.gcm.GcmReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.example.gcm" />
</intent-filter>
</receiver>

2.注册监听通知服务(在app中创建一个服务类并继承GcmListenerService类)
<pre name="code" class="html"><service  
android:name="com.example.MyGcmListenerService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>

public class MyGcmListenerService extends GcmListenerService {

@Override
public void onMessageReceived(String from, Bundle data) {
String message = data.getString("message");
/**
* Production applications would usually process the message here.
* Eg: - Syncing with server.
* - Store message in local database.
* - Update UI.
*/

/**
* In some cases it may be useful to show a notification indicating to the user
* that a message was received.
*/
sendNotification(message);
}
// [END receive_message]

/**
* Create and show a simple notification containing the received GCM message.
*
* @param message GCM message received.
*/
private void sendNotification(String message) {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);

Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_stat_ic_notification)
.setContentTitle("this is a new new GCM Message")
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);

NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
}

 
3.注册监听token改变的服务(在app中创建一个服务类继承InstanceIDListenerService类,本服务存在于新的Google play服务版本上)
 android:name="com.example.MyInstanceIDListenerService"  
android:exported="false">
<intent-filter>
<action android:name="com.google.android.gms.iid.InstanceID"/>
</intent-filter>
</service>

public class MyInstanceIDListenerService extends InstanceIDListenerService {

@Override
public void onTokenRefresh() {
// Fetch updated Instance ID token and notify our app's server of any changes (if applicable).
}
}

 
gcm通过注册的系统广播可以自行启动GcmListenerService类,所以不需要在app创建一个广播类

注册token

App发送 project number到GCM Server注册接收推送信息。 

GCM Server 向App返回token(token是GCM服务器自行生产的,能够保证某一终端设备上的某一个应用,很重要)。 

在设备上应该先判断是否安装了Google play 服务
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);  
if (resultCode != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
GooglePlayServicesUtil.getErrorDialog(resultCode, this, PLAY_SERVICES_RESOLUTION_REQUEST).show();//会提示错误对话框,其他错误信息可参考官网API
} else {
Log.i(TAG, "This device is not supported.”);
}

 
 
Google play服务存在,那接下来就需要去注册token了,在上边创建项目得到的project number在这里就需要用它来注册token

10.jpg


9.jpg

 
InstanceID instanceID = InstanceID.getInstance(this);  
String token = instanceID.getToken(PROJECT_NUMBER,
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);

 
对于旧版本还是要使用以下方式来注册token(用于Google play 服务7.5版本之前)
GoogleCloudMessaging.getInstance(Context).register(PROJECT_NUMBER);  

 
在自己的服务器端注册api key

App向我们自己服务器发送token(推送消息的时候要使用token,GCM服务器是使用token来确定某一终端设备上的某一个应用接收消息的,所以第三方服务器需要保存它,需要注意的是token很长,存数据库时需要注意字段长度) ,将我们在上边create new key 得到的apikey添加到自己的服务器端保存,我们的服务器向GCM Server发送消息,传递apikey和token ,GCM Server把消息推送给App 
最后注意一下,关于app卸载出现的问题,看一下官方的介绍

11.jpg


app会发生卸载过程并不能很快完成,卸载app需要花时间从GCM移除当前关联的token,这个过程就会出现发送消息是成功的,但是不能到达app客户端,在最后,token被移除了,服务器端发送的消息失败,得到一个NotRegistered错误,这个时候就应该在服务器端删除相对应的token
0
评论

开发实战:Android自定义标题栏 Android 移动开发

oscar1212 发表了文章 • 2240 次浏览 • 2015-07-24 15:48 • 来自相关话题

本文要讲自己定义一个标题栏,能加事件。然后可以移值到不同的手机上,基本上不用改什么,调用也很简单

在layout文件夹下,新建一个XML。名字叫做layout_title_bar.xml然后来看看布局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="45.0dip"
android:background="@drawable/bg_title_bar"
android:gravity="top" >

<ImageView
android:id="@+id/title_bar_menu_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="3.0dip"
android:layout_marginRight="3.0dip"
android:layout_marginTop="3.0dip"
android:gravity="center"
android:src="@drawable/ic_top_bar_category" />

<ImageView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_toRightOf="@id/title_bar_menu_btn"
android:background="@drawable/ic_top_divider" />

<TextView
android:id="@+id/title_bar_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:ellipsize="end"
android:gravity="center"
android:paddingLeft="75.0dip"
android:paddingRight="75.0dip"
android:singleLine="true"
android:text="Java学习宝典"
android:textColor="#ffffff"
android:textSize="22sp" />

</RelativeLayout> 看下效果:





接下要就是要用了,在要用到的地方:我这里是activity_main.xml文件中:

加上一句:  <include layout="@layout/layout_title_bar" />这样就行了,

然后我们要给标题栏上的按钮添加事件,这个更加简单了:

在MainActivity.java(对应activity_main.xml)中,onCreate函数中添加:事件可以自己改,我这里是让它控制左右滑动的功能。
ImageView menuImg = (ImageView) findViewById(R.id.title_bar_menu_btn);
menuImg.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View arg0) {
if (!menuIsShow)
showMenu();
else {
hideMenu();
}

}

}); 这样就可以了:

我们来看看效果






这就是效果了,很简单吧,想用直接把上面的布局复制过去就OK了!
 
作者:林炳文Evankaka 查看全部
本文要讲自己定义一个标题栏,能加事件。然后可以移值到不同的手机上,基本上不用改什么,调用也很简单

在layout文件夹下,新建一个XML。名字叫做layout_title_bar.xml然后来看看布局:
<?xml version="1.0" encoding="utf-8"?>  
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="45.0dip"
android:background="@drawable/bg_title_bar"
android:gravity="top" >

<ImageView
android:id="@+id/title_bar_menu_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="3.0dip"
android:layout_marginRight="3.0dip"
android:layout_marginTop="3.0dip"
android:gravity="center"
android:src="@drawable/ic_top_bar_category" />

<ImageView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_toRightOf="@id/title_bar_menu_btn"
android:background="@drawable/ic_top_divider" />

<TextView
android:id="@+id/title_bar_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:ellipsize="end"
android:gravity="center"
android:paddingLeft="75.0dip"
android:paddingRight="75.0dip"
android:singleLine="true"
android:text="Java学习宝典"
android:textColor="#ffffff"
android:textSize="22sp" />

</RelativeLayout>
看下效果:

20150220004910963.png

接下要就是要用了,在要用到的地方:我这里是activity_main.xml文件中:

加上一句:  <include layout="@layout/layout_title_bar" />这样就行了,

然后我们要给标题栏上的按钮添加事件,这个更加简单了:

在MainActivity.java(对应activity_main.xml)中,onCreate函数中添加:事件可以自己改,我这里是让它控制左右滑动的功能。
ImageView menuImg = (ImageView) findViewById(R.id.title_bar_menu_btn);  
menuImg.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View arg0) {
if (!menuIsShow)
showMenu();
else {
hideMenu();
}

}

});
这样就可以了:

我们来看看效果

20150220004942958.gif


这就是效果了,很简单吧,想用直接把上面的布局复制过去就OK了!
 
作者:林炳文Evankaka
0
评论

中国互联网大会感受:技术人员最好的创业时代 云计算 移动开发 环信

admin 发表了文章 • 1422 次浏览 • 2015-07-24 15:25 • 来自相关话题

“年年岁岁花相似,岁岁年年人不同”,用这句千古名句来形容中国互联网大会的发展历程可以说再贴切不过了。在经历了互联网的1.0时代(PC互联网)、2.0时代(移动互联网)后,互联网的发展正快速步入下一个迭代周期,你可以认为是3.0时代,也可以给这个时代打上一个互联网+的标签。总之,当下这个时代互联网已不再是某个或某些企业的专属,谈全民互联网甚至也不觉得夸张。 在日前举办的第十四届中国互联网大会上,笔者也选取了三个非常有代表性的企业进行采访报道,看看透过它们是否能觉察出一些互联网+的典型特征。这三家企业分别是传统互联网的代表百度、传统制造业的代表联想,以及新兴的科技型创业企业环信。要说本次中国互联网大会上三家企业的所讲所展,有一个共同点是它们都在做云相关的内容,当然不同就多了去了,这里也不细说了,毕竟是三家几乎不搭杠的企业。 

首先,我们来聊聊环信。 

作为一家刚刚成立不过2年多的创业型企业,可能很多人还不太熟悉,这里先做个介绍。环信即时通讯云成立于2013年4月,是一家提供移动即时通讯能力的云计算 PaaS (Platform as a Service, 平台即服务) 平台服务商。 

这么听起来可能还是有些难懂,我们举个例子来进一步说明一下,即时通讯相信大家并不陌生,电话、QQ、微信之类的都算是即时通讯工具,即时通讯云简单理解就是用于承载这些工具的平台。而基于该平台,环信有自己开发的即时通讯工具移动客服。





 
环信CEO刘俊彦
 
据环信CEO刘俊彦介绍,目前其即时通讯云平台上线已一年多时间,SDK(Software Development Kit,软件开发工具包)覆盖用户近1个亿,有3万余个APP集成了该平台的即时通讯能力,终端用户覆盖超3个亿。而另一款拳头产品移动客服上线仅3个月,已签约数百家企业,包括国美在线、58到家在内的众多龙头企业都已是环信的用户。 

关于即时通讯云前文已有相应的解释,这里不再赘述,而是介绍下何谓移动客服。顾名思义,移动客服就是主要面向移动终端的客服,更准确地讲就是针对各种APP打造的客服工具。相信大家都打过400、800之类的客服电话,估计也用过PC端的网页客服,但随着移动互联网的兴起,这些方式在应对移动端客户的需求时已变得捉襟见肘。 

为什么呢?
 
一是移动端的量大,一个APP同时在线的人数可能在数十上百万;二是一旦APP打开,与客服之间的连接就是一直长期保持的关系。而在PC端,网页一旦关闭,与客服之间的对话就已经中断。无疑,移动客服后台数据中心所承载的压力和成本是要远高于传统客服方式的。刘俊彦表示,这也是移动客服市场的主要门槛之一。 

显然,作为国内较早进入该行业的企业,环信无疑已经占领了先机,前文已经提到了环信目前的用户情况,可以说非常不错,而更关键的是环信基本已经实现了收支平衡,要知道这在创业一两年的企业中可是为数不多的。 

放眼未来,环信也有着明确的规划。当前,其B轮融资已经到位,至于具体数额会于下周公布,但这些钱用在什么地方,他们早就想清楚了。刘俊彦表示,公司下一步的拓展方向主要是两个方面,一是由现在更多面向服务电商、O2O、互联网金融、互联网教育、医疗、旅游行业的移动客服向覆盖传统客服和移动客服的全领域扩张,二则是向物联网领域发展。 

具体来说,一是为了向用户提供客服的整体解决方案,而这么做的规划其实也是客户需求促使。据刘俊彦介绍,现在就有客户问他是不是能提供一整套完整的解决方案,而不需要移动客服找你们,网页客服找另一家,电话客服再找一家。二则是面向未来广阔的物联网市场,用不了几年,冰箱、洗衣机坏了的时候你已经无需再查找厂商的客服电话,而可能通过电器上的一个按钮就能实现报修,想一想是不是很美好。 

但话说回来,作为一个具有广阔市场前景的行业,环信所不可避免的要面临竞争,而且随着市场的不断扩大,竞争也会愈发剧烈。不过在笔者将这个问题抛给刘俊彦时,他倒是相当坦然。要说技术出身的人总是那么的质朴,可能是被问的多了回答的也多了,他很平淡地说,“市场这么大(美国大概是100亿美金,中国市场比这个还要大),我们能拿下个位数的份额,已经是足够大的体量了。现在更重要的是有更多的人进来,把这个行业先做大,做好用户服务。”

在写有关环信内容的最后,加一点刘俊彦的个人履历,17年研发,先后任职IONA、RedHat,专注于高并发消息中间件,实时消息系统,异构分布式企业系统集成,应用服务器。联想到最近一两年兴起的一批批创业公司,包括很多都在本次互联网大会上亮了相,笔者只想说,这是技术人员最好的创业时代。  查看全部
“年年岁岁花相似,岁岁年年人不同”,用这句千古名句来形容中国互联网大会的发展历程可以说再贴切不过了。在经历了互联网的1.0时代(PC互联网)、2.0时代(移动互联网)后,互联网的发展正快速步入下一个迭代周期,你可以认为是3.0时代,也可以给这个时代打上一个互联网+的标签。总之,当下这个时代互联网已不再是某个或某些企业的专属,谈全民互联网甚至也不觉得夸张。 在日前举办的第十四届中国互联网大会上,笔者也选取了三个非常有代表性的企业进行采访报道,看看透过它们是否能觉察出一些互联网+的典型特征。这三家企业分别是传统互联网的代表百度、传统制造业的代表联想,以及新兴的科技型创业企业环信。要说本次中国互联网大会上三家企业的所讲所展,有一个共同点是它们都在做云相关的内容,当然不同就多了去了,这里也不细说了,毕竟是三家几乎不搭杠的企业。 

首先,我们来聊聊环信。 

作为一家刚刚成立不过2年多的创业型企业,可能很多人还不太熟悉,这里先做个介绍。环信即时通讯云成立于2013年4月,是一家提供移动即时通讯能力的云计算 PaaS (Platform as a Service, 平台即服务) 平台服务商。 

这么听起来可能还是有些难懂,我们举个例子来进一步说明一下,即时通讯相信大家并不陌生,电话、QQ、微信之类的都算是即时通讯工具,即时通讯云简单理解就是用于承载这些工具的平台。而基于该平台,环信有自己开发的即时通讯工具移动客服。

lij5o8EpD9NFA_600.jpg

 
环信CEO刘俊彦
 
据环信CEO刘俊彦介绍,目前其即时通讯云平台上线已一年多时间,SDK(Software Development Kit,软件开发工具包)覆盖用户近1个亿,有3万余个APP集成了该平台的即时通讯能力,终端用户覆盖超3个亿。而另一款拳头产品移动客服上线仅3个月,已签约数百家企业,包括国美在线、58到家在内的众多龙头企业都已是环信的用户。 

关于即时通讯云前文已有相应的解释,这里不再赘述,而是介绍下何谓移动客服顾名思义,移动客服就是主要面向移动终端的客服,更准确地讲就是针对各种APP打造的客服工具。相信大家都打过400、800之类的客服电话,估计也用过PC端的网页客服,但随着移动互联网的兴起,这些方式在应对移动端客户的需求时已变得捉襟见肘。 

为什么呢?
 
  • 一是移动端的量大,一个APP同时在线的人数可能在数十上百万;
  • 二是一旦APP打开,与客服之间的连接就是一直长期保持的关系。而在PC端,网页一旦关闭,与客服之间的对话就已经中断。无疑,移动客服后台数据中心所承载的压力和成本是要远高于传统客服方式的。刘俊彦表示,这也是移动客服市场的主要门槛之一。 


显然,作为国内较早进入该行业的企业,环信无疑已经占领了先机,前文已经提到了环信目前的用户情况,可以说非常不错,而更关键的是环信基本已经实现了收支平衡,要知道这在创业一两年的企业中可是为数不多的。 

放眼未来,环信也有着明确的规划。当前,其B轮融资已经到位,至于具体数额会于下周公布,但这些钱用在什么地方,他们早就想清楚了。刘俊彦表示,公司下一步的拓展方向主要是两个方面,一是由现在更多面向服务电商、O2O、互联网金融、互联网教育、医疗、旅游行业的移动客服向覆盖传统客服和移动客服的全领域扩张,二则是向物联网领域发展。 

具体来说,一是为了向用户提供客服的整体解决方案,而这么做的规划其实也是客户需求促使。据刘俊彦介绍,现在就有客户问他是不是能提供一整套完整的解决方案,而不需要移动客服找你们,网页客服找另一家,电话客服再找一家。二则是面向未来广阔的物联网市场,用不了几年,冰箱、洗衣机坏了的时候你已经无需再查找厂商的客服电话,而可能通过电器上的一个按钮就能实现报修,想一想是不是很美好。 

但话说回来,作为一个具有广阔市场前景的行业,环信所不可避免的要面临竞争,而且随着市场的不断扩大,竞争也会愈发剧烈。不过在笔者将这个问题抛给刘俊彦时,他倒是相当坦然。要说技术出身的人总是那么的质朴,可能是被问的多了回答的也多了,他很平淡地说,“市场这么大(美国大概是100亿美金,中国市场比这个还要大),我们能拿下个位数的份额,已经是足够大的体量了。现在更重要的是有更多的人进来,把这个行业先做大,做好用户服务。”

在写有关环信内容的最后,加一点刘俊彦的个人履历,17年研发,先后任职IONA、RedHat,专注于高并发消息中间件,实时消息系统,异构分布式企业系统集成,应用服务器。联想到最近一两年兴起的一批批创业公司,包括很多都在本次互联网大会上亮了相,笔者只想说,这是技术人员最好的创业时代。 
0
回复

我想问2.3.6安卓用字体管家换字体能成功吗? 环信_Android Android 移动开发

回复

正宗猫奴° 发起了问题 • 1 人关注 • 1610 次浏览 • 2015-07-24 15:04 • 来自相关话题

0
评论

iOS开发生涯的初恋:详解Objective-C多项改进 iOS 移动开发

oscar1212 发表了文章 • 1662 次浏览 • 2015-07-24 11:42 • 来自相关话题

对于许多iOS开发者而言,Objective-C就是开发生涯中的初恋。如今,Swift正在以迅雷不及掩耳之势碾压Objective-C的份额,但Objective-C多项性能改进依然让开发者非常激动,本文作者对OC的提升进行了详解。
 
The Setup

下面的代码你们一定再熟悉不过了,我们来重温一下吧:
@property (strong, nonatomic) NSArray *someViews; 这绝对符合Objective-C完美主义开发者的标准。对它表示的属性,不同人有不同观点。但是,其中仍然存在着一些难以察觉的缺陷。

是否可能返回nil?

除非有现成的文件,或开发者全程都在一旁,否则光凭看是无法获取信息的。

除了UIView之外还有什么?

还是那句话——不确定。也许答案是reflection? 或许问题可以改成:除了UIView,有可能出现UIView子类吗?

看样子会出现诸多转换(casting)

因为是一队列……东西,知道那东西是什么之后,经过cast后才能利用。

会弱化Swift代码和可读性

很遗憾,Swift支持泛型(generics)就意味着(Objective-C )只会以optional的AnyObject集合的形式出现。如此一来,开发者要使用该属性就必须在Swift和Objective-C之间进行转换。

Nullability Annotations

单单一个属性就引发了这么多担忧,还挺让人不安的。如果代码本身引发很多质疑,出现error的可能性就大大增加,更别提在广为熟知的Objective-C和语言新秀Swift之间相互调用(interoperability)了。现在有了nullability annotations——我最爱的Objective-C新功能之一,问题就简单多了,编程也会省下很多麻烦。

intent.

现在谈到API,(intent.)可能会,也可能不会返回nil。简而言之,终于不用花费数小时来排除漏洞了。以下有三个选项:
nullable — Think UIViewnonnull — Think UIViewnull_unspecified — Think UIView!

再回到实例属性。假设在运行时迭代这个属性来创建某个用户界面,在相应的位置应该有UIButton和UIView。

但是,天哪!——不论怎么样它们也不应该是nil啊。现在出现如下的信息:
@property (strong, nonatomic, nonnull) NSArray *someViews; intent.大大提升了Objective-C,而且这个属性也不会在Swift里满满都是optional了。

开发者看看代码就知道有没有nil pointer了,太棒了!

计算机的静态检验和Swift的可用性都得到了提升,最重要的是实现了API的intent通讯。

泛型

……Objective-C开发者们举国欢庆。呜呼,泛型的恩泽终于笼罩大地,这无疑是那些开发者勇士们的功劳。

如果把Cocoa Touch比作孩子们的睡前故事,那么Objective-C就好比是主演,故事书肯定是以上面那段话结尾的。泛型的缺席一直以来是Objective-C开发者心头之痛,而诞生32年之后,Objective-C终于也支持泛型了。2015 WWDC上Swift 2成为了镁光灯下的宠儿,而Objective-C这一巨大的跨越却被忽视了,实在委屈。支持泛型将带来诸多改变,而且都是积极的改变。

现在可以定义属性,下指令给编译器来显示所有UIView:
@property (strong, nonatomic, nonnull) NSArray<UIView *> *someViews; 向属性强加UIView之外的东西时,编译器会报错。而且如今不用做大量头痛的转换(cast)了。

Objective-C支持泛型对Swift而言也是好消息。上次更新时,我们让Swift知道对象不应该是optional的,现在Swift还知道它们是UIViews,如此一来含混不清的AnyObject声明就不需要了。如今的Objective-C可以像C#、C++、Swift等语言一样通过<>括号来表示类型了。虽然通常是对协议表示一致性(conformance),但编译器知道何时、何地以及如何运用它们,且运用是经过推理的。

再进一步,可以用参数来表示扩展(extensions)、类别(categories)和类(classes),好处不仅仅体现在集合(collections)上。泛型的强大体现在整个Objective-C之中,集合仅仅是结果而已。举个例子,看看NSDictionary,开发者肯定会偷着乐吧:
@interface NSDictionary<KeyType, ObjectType> (Lookup)
- (nullable ObjectType)objectForKey:(KeyType)aKey;
@end 刚开始知道类型擦除(type erasure)是为了这个的时候,我有点儿不满意,但考虑到老旧的Objective-C程序堆积在一起的问题,也就释怀了。

类型擦除(type erasure)不但能实现二进制兼容,而且不改变Objective-C的执行时间。所以亲爱的开发者们,C#的泛型的确胜过其他语言,皱皱眉头,发几句牢骚就算了,日子还得继续呢。

KindOf Types

啊,这是最后一部分重要内容。再次调用之前定义的属性,就会显示UIView。判断里面包含着views和buttons是再正常不过的事。

这种情况下,添加如下代码会发生什么呢?
[self.someViews[0] addTarget:self action:selector(aMethod:) forControlEvents:UIControlEventTouchUpInside]; 啊,编译器警告。

这就对啦,因为即便可以在这个属性里插入一个button,就算可以假设是个UIView,button也不一定没有经过转换。

新的KindOf特性能够轻松解决这种始料未及的情况。我们再回到实例属性上:
@property (strong, nonatomic, nonnull) NSArray<__kindof UIView *> *someViews; 实际上我们已经告诉编译器:属性及其集合会出现一些UIView。这样在类型协议里显示更多我们之前看不到的信息。其本质向下转型(downcasting)。

这意味着上述代码编译没什么问题,因为编译器知道集合里肯定会出现一个button。

现在那些担忧就都解释得清了。

虽然不喜欢Swift的人可能会刻意夸大Objective-C的优点,但如今两种语言实现了互相调用,这是Objective-C所有提升的最大价值所在,我们应该心存感激。

毋庸置疑,Objective-C的确比以往更加强大。

总结

对我来说,Objective-C是开发生涯中的初恋,相比其他语言,它是那么与众不同——直到今天都是如此,它的好、它的坏都让我欲罢不能。虽然如今Swift正以迅雷不及掩耳之势征服着我的心,我还是希望Objective-C陪伴在身边。

Objective-C的提升能够帮助开发者写出更好的代码,这是好事。而且这些优势已经在Foundation中随处可见了。
 
来源:csdn 查看全部
对于许多iOS开发者而言,Objective-C就是开发生涯中的初恋。如今,Swift正在以迅雷不及掩耳之势碾压Objective-C的份额,但Objective-C多项性能改进依然让开发者非常激动,本文作者对OC的提升进行了详解。
 
The Setup

下面的代码你们一定再熟悉不过了,我们来重温一下吧:
@property (strong, nonatomic) NSArray *someViews;  
这绝对符合Objective-C完美主义开发者的标准。对它表示的属性,不同人有不同观点。但是,其中仍然存在着一些难以察觉的缺陷。

是否可能返回nil?

除非有现成的文件,或开发者全程都在一旁,否则光凭看是无法获取信息的。

除了UIView之外还有什么?

还是那句话——不确定。也许答案是reflection? 或许问题可以改成:除了UIView,有可能出现UIView子类吗?

看样子会出现诸多转换(casting)

因为是一队列……东西,知道那东西是什么之后,经过cast后才能利用。

会弱化Swift代码和可读性

很遗憾,Swift支持泛型(generics)就意味着(Objective-C )只会以optional的AnyObject集合的形式出现。如此一来,开发者要使用该属性就必须在Swift和Objective-C之间进行转换。

Nullability Annotations

单单一个属性就引发了这么多担忧,还挺让人不安的。如果代码本身引发很多质疑,出现error的可能性就大大增加,更别提在广为熟知的Objective-C和语言新秀Swift之间相互调用(interoperability)了。现在有了nullability annotations——我最爱的Objective-C新功能之一,问题就简单多了,编程也会省下很多麻烦。

intent.

现在谈到API,(intent.)可能会,也可能不会返回nil。简而言之,终于不用花费数小时来排除漏洞了。以下有三个选项:
  • nullable — Think UIView
  • nonnull — Think UIView
  • null_unspecified — Think UIView!


再回到实例属性。假设在运行时迭代这个属性来创建某个用户界面,在相应的位置应该有UIButton和UIView。

但是,天哪!——不论怎么样它们也不应该是nil啊。现在出现如下的信息:
@property (strong, nonatomic, nonnull) NSArray *someViews; 
intent.大大提升了Objective-C,而且这个属性也不会在Swift里满满都是optional了。

开发者看看代码就知道有没有nil pointer了,太棒了!

计算机的静态检验和Swift的可用性都得到了提升,最重要的是实现了API的intent通讯。

泛型

……Objective-C开发者们举国欢庆。呜呼,泛型的恩泽终于笼罩大地,这无疑是那些开发者勇士们的功劳。

如果把Cocoa Touch比作孩子们的睡前故事,那么Objective-C就好比是主演,故事书肯定是以上面那段话结尾的。泛型的缺席一直以来是Objective-C开发者心头之痛,而诞生32年之后,Objective-C终于也支持泛型了。2015 WWDC上Swift 2成为了镁光灯下的宠儿,而Objective-C这一巨大的跨越却被忽视了,实在委屈。支持泛型将带来诸多改变,而且都是积极的改变。

现在可以定义属性,下指令给编译器来显示所有UIView:
@property (strong, nonatomic, nonnull) NSArray<UIView *> *someViews;  
向属性强加UIView之外的东西时,编译器会报错。而且如今不用做大量头痛的转换(cast)了。

Objective-C支持泛型对Swift而言也是好消息。上次更新时,我们让Swift知道对象不应该是optional的,现在Swift还知道它们是UIViews,如此一来含混不清的AnyObject声明就不需要了。如今的Objective-C可以像C#、C++、Swift等语言一样通过<>括号来表示类型了。虽然通常是对协议表示一致性(conformance),但编译器知道何时、何地以及如何运用它们,且运用是经过推理的。

再进一步,可以用参数来表示扩展(extensions)、类别(categories)和类(classes),好处不仅仅体现在集合(collections)上。泛型的强大体现在整个Objective-C之中,集合仅仅是结果而已。举个例子,看看NSDictionary,开发者肯定会偷着乐吧:
@interface NSDictionary<KeyType, ObjectType> (Lookup)  
- (nullable ObjectType)objectForKey:(KeyType)aKey;
@end
刚开始知道类型擦除(type erasure)是为了这个的时候,我有点儿不满意,但考虑到老旧的Objective-C程序堆积在一起的问题,也就释怀了。

类型擦除(type erasure)不但能实现二进制兼容,而且不改变Objective-C的执行时间。所以亲爱的开发者们,C#的泛型的确胜过其他语言,皱皱眉头,发几句牢骚就算了,日子还得继续呢。

KindOf Types

啊,这是最后一部分重要内容。再次调用之前定义的属性,就会显示UIView。判断里面包含着views和buttons是再正常不过的事。

这种情况下,添加如下代码会发生什么呢?
[self.someViews[0] addTarget:self action:selector(aMethod:) forControlEvents:UIControlEventTouchUpInside];  
啊,编译器警告。

这就对啦,因为即便可以在这个属性里插入一个button,就算可以假设是个UIView,button也不一定没有经过转换。

新的KindOf特性能够轻松解决这种始料未及的情况。我们再回到实例属性上:
@property (strong, nonatomic, nonnull) NSArray<__kindof UIView *> *someViews;  
实际上我们已经告诉编译器:属性及其集合会出现一些UIView。这样在类型协议里显示更多我们之前看不到的信息。其本质向下转型(downcasting)。

这意味着上述代码编译没什么问题,因为编译器知道集合里肯定会出现一个button。

现在那些担忧就都解释得清了。

虽然不喜欢Swift的人可能会刻意夸大Objective-C的优点,但如今两种语言实现了互相调用,这是Objective-C所有提升的最大价值所在,我们应该心存感激。

毋庸置疑,Objective-C的确比以往更加强大。

总结

对我来说,Objective-C是开发生涯中的初恋,相比其他语言,它是那么与众不同——直到今天都是如此,它的好、它的坏都让我欲罢不能。虽然如今Swift正以迅雷不及掩耳之势征服着我的心,我还是希望Objective-C陪伴在身边。

Objective-C的提升能够帮助开发者写出更好的代码,这是好事。而且这些优势已经在Foundation中随处可见了。
 
来源:csdn
0
评论

值得推荐:理解 JavaScript 的原型链和继承 开发者 移动开发

oscar1212 发表了文章 • 1247 次浏览 • 2015-07-16 15:58 • 来自相关话题

instanceof 运算符可以用来判断某个构造函数的prototype属性是否存在另外一个要检测对象的原型链上1
 
什么意思呢?

来个题Function instanceof Object;用高中数学的话就是把x,y代入公式得:

instanceof 运算符可以用来判断Object的 prototype属性 是否存在Function的 原型链 上。
等等,斜体字的这俩到底是什么鬼意思?

prototype属性是原型链吗?

JS是基于原型链面向对象语言,也就是说所有对象都是以对象为模板创建实例的。如果是其他oo语言的背景比如Java或Ruby,都习惯于创建一个class模板,class创建object实例。比如ruby:
class A
def initialize name @name = name end
def to_s
@name
end
endputs A.new('hehe') # => hehe这里的类A就是所有 A.new 创建出来的实例的模板而已。而对于原型链语言JS来说,同意的事情要这样做
function A(name){ this.name = name
}
A.prototype.toString = function(){ return this.name
}var a = new A('hehe')
console.log('object name is:' + new A ('hehe')) // => object name is: hehe
这里的怪怪的函数其实就是constructor,相当于ruby例子里的initialize而prototype上的方法toString也就是类似class模板上的方法。
为什么要把方法绑到prototype上?直接 A.toString…= 不行吗?
在解释prototype之前,先解释一下 new A 到底发生了什么2:
1: // var a = new A('hehe') =>2: var a = new Object();3: a.__proto__ = A.prototype; (proto)4: A.call(a, 'hehe');其中 A.call 的意思是先把A的this设置为a,然后执行A的body也就是this.name=name

但是 __proto__ 又是什么

__proto__ 才是原型链

__proto__ 是内部 [ [Prototype ]] (说了半天原型链这就是牛逼闪闪的 原型链, 指向对象或者null)的getter和setter方法(已加入ES6规范3,但是还是建议只使用Object.getPrototypeOf())

JS对象能使用它原型链对象的所有方法,比如所有的对象的原型链(的原型链的原型链的原型链…)都最终会指向Object(或null)。因此,所有的对象都能使用Object.prototype上的方法,比如我之前覆盖掉的 toString 本身就是Object.prototype上的方法,如果没有覆盖,它是可以拿到所有Object上的方法的:
a.toString === A.prototype.toString // truea.toLocalString === Object.prototype.toLocalString // truea.__proto__ === A.prototype // true所以,现在是否可以理解这句话了呢
instanceof 运算符可以用来判断Object的 prototype属性 是否存在Function的 原型链 上。

所以instanceof其实就是
Function.__proto__ === Object.prototype// false擦,假设失败了呢,让我们来看看为什么不对,Function.__proto__到底指哪去了
Function.__proto__ === Function.prototype//true原来指向自己的prototype了呢,那就意味着…
Function instanceof Function//trueyes,然而 Function instanceof Object似乎也能解释了
Function.__proto__ === Function.prototypeFunction.__proto__.__proto__ === Object.prototype所以如果我们让
Function.__proto__.__proto__ = nullFunction instanceof Object//false这回知道为什么不要用 __proto__ 了吧,一不小心重写了会导致所有继承自它的对象都受影响。
为了养成良好的习惯,实际项目最好使用 getPrototypeOf 取原型链,这里只是为了方便我采用__proto__
下面来看第二个题
Object instanceof Function
难道可以互相链吗?这意味着
Object.__proto__ === Function.prototype// true// 但是Firefox取不到Object.__proto__, 看来做了保护,必须要用// Object.getPrototypeOf(Object) === Function.prototype要晕了, 忍不住要画个图





多简单呢,一共就分别有两类:

原型链指向Function.prototype的函数们

原型链指向Object.propotype的对象们

而原型链顶端的Object.prototype就再没有原型链了,所以是空

现在再回头看题目是不是so easy了。

也没什么卵用得 contructor

如果你好奇的在FireFox Console中看一下 a 除了刚才那些玩意,还有一个奇怪的东西





话说 A 里面这个constructor是个什么鬼,我们来玩它一下
a.constructor === A.prototype.constructor
A.prototype.constructor === A
A.prototype.constructor = nulla.constructor // => nulla instanceof A // true这只是函数都有的一个玩意而已, 由于js的函数可以作为构造器,也就是可以 new ,所以所有的 函数的prototype.constructor都指向自己,因此所有的 new 出来的对象也都有一个reference能找到自己的构造器。

然而除了这个功能也并没有什么卵用嘛。

真的是这样吗?
.

..



….

…..

……

…….
恩,真的!

Bonus 继承

下面这个是babel 从es6 class
class A{
constructor(name) { this.name= name
}
toString() { return this.name
}
}class B extends A {
toString(){ return this.name + 'b'
}
}编译出来的ES5继承
function _inherits(subClass, superClass) {
// 密}var A = (function () { function A(name) { this.name = name;
}

A.prototype.toString = function toString() { return this.name;
}; return A;
})();var B = (function (_A) { function B() { if (_A != null) {
_A.apply(this, arguments);
}
}

_inherits(B, _A);

B.prototype.toString = function toString() { return this.name + 'b';
}; return B;
})(A);其他地方都不用看了,inherits 函数用到了之前学到的所有玩意,要求实现要满足下列所有的cases,就当是课后练习了:
var a= new A('A');var b= new B('B');
a.constructor === A &&
b.constructor === B &&
a instanceof A &&
b instanceof A &&
b instanceof B
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/instanceof这里只是意思,但是如果真的改变 __proto__ 是非常低效的https://developer.mozilla.org/ ... protohttp://www.ecma-international.org/ecma-262/6.0/#sec-additional-properties-of-the-object.prototype-object

Author: Jichao Ouyang 查看全部
instanceof 运算符可以用来判断某个构造函数的prototype属性是否存在另外一个要检测对象的原型链上1
 
什么意思呢?

来个题Function instanceof Object;用高中数学的话就是把x,y代入公式得:

instanceof 运算符可以用来判断Object的 prototype属性 是否存在Function的 原型链 上。
等等,斜体字的这俩到底是什么鬼意思?

prototype属性是原型链吗?

JS是基于原型链面向对象语言,也就是说所有对象都是以对象为模板创建实例的。如果是其他oo语言的背景比如Java或Ruby,都习惯于创建一个class模板,class创建object实例。比如ruby:
  class A
def initialize name @name = name end
def to_s
@name
end
endputs A.new('hehe') # => hehe
这里的类A就是所有 A.new 创建出来的实例的模板而已。而对于原型链语言JS来说,同意的事情要这样做
function A(name){  this.name = name
}
A.prototype.toString = function(){ return this.name
}var a = new A('hehe')
console.log('object name is:' + new A ('hehe')) // => object name is: hehe

  • 这里的怪怪的函数其实就是constructor,相当于ruby例子里的initialize
  • 而prototype上的方法toString也就是类似class模板上的方法。

为什么要把方法绑到prototype上?直接 A.toString…= 不行吗?
在解释prototype之前,先解释一下 new A 到底发生了什么2:
1: // var a = new A('hehe') =>2: var a = new Object();3: a.__proto__ = A.prototype; (proto)4: A.call(a, 'hehe');
其中 A.call 的意思是先把A的this设置为a,然后执行A的body也就是this.name=name

但是 __proto__ 又是什么

__proto__ 才是原型链

__proto__ 是内部 [ [Prototype ]] (说了半天原型链这就是牛逼闪闪的 原型链, 指向对象或者null)的getter和setter方法(已加入ES6规范3,但是还是建议只使用Object.getPrototypeOf())

JS对象能使用它原型链对象的所有方法,比如所有的对象的原型链(的原型链的原型链的原型链…)都最终会指向Object(或null)。因此,所有的对象都能使用Object.prototype上的方法,比如我之前覆盖掉的 toString 本身就是Object.prototype上的方法,如果没有覆盖,它是可以拿到所有Object上的方法的:
a.toString === A.prototype.toString // truea.toLocalString === Object.prototype.toLocalString // truea.__proto__ === A.prototype // true
所以,现在是否可以理解这句话了呢
instanceof 运算符可以用来判断Object的 prototype属性 是否存在Function的 原型链 上。

所以instanceof其实就是
Function.__proto__ === Object.prototype// false
擦,假设失败了呢,让我们来看看为什么不对,Function.__proto__到底指哪去了
Function.__proto__ === Function.prototype//true
原来指向自己的prototype了呢,那就意味着…
Function instanceof Function//true
yes,然而 Function instanceof Object似乎也能解释了
Function.__proto__ === Function.prototypeFunction.__proto__.__proto__ === Object.prototype
所以如果我们让
Function.__proto__.__proto__ = nullFunction instanceof Object//false
这回知道为什么不要用 __proto__ 了吧,一不小心重写了会导致所有继承自它的对象都受影响。
为了养成良好的习惯,实际项目最好使用 getPrototypeOf 取原型链,这里只是为了方便我采用__proto__
下面来看第二个题
Object instanceof Function
难道可以互相链吗?这意味着
Object.__proto__ === Function.prototype// true// 但是Firefox取不到Object.__proto__, 看来做了保护,必须要用// Object.getPrototypeOf(Object) === Function.prototype
要晕了, 忍不住要画个图

1.png

多简单呢,一共就分别有两类:

原型链指向Function.prototype的函数们

原型链指向Object.propotype的对象们

而原型链顶端的Object.prototype就再没有原型链了,所以是空

现在再回头看题目是不是so easy了。

也没什么卵用得 contructor

如果你好奇的在FireFox Console中看一下 a 除了刚才那些玩意,还有一个奇怪的东西

2.png

话说 A 里面这个constructor是个什么鬼,我们来玩它一下
a.constructor === A.prototype.constructor
A.prototype.constructor === A
A.prototype.constructor = nulla.constructor // => nulla instanceof A // true
这只是函数都有的一个玩意而已, 由于js的函数可以作为构造器,也就是可以 new ,所以所有的 函数的prototype.constructor都指向自己,因此所有的 new 出来的对象也都有一个reference能找到自己的构造器。

然而除了这个功能也并没有什么卵用嘛。

真的是这样吗?
.

..



….

…..

……

…….
恩,真的!

Bonus 继承

下面这个是babel 从es6 class
class A{
constructor(name) { this.name= name
}
toString() { return this.name
}
}class B extends A {
toString(){ return this.name + 'b'
}
}
编译出来的ES5继承
function _inherits(subClass, superClass) { 
// 密}var A = (function () { function A(name) { this.name = name;
}

A.prototype.toString = function toString() { return this.name;
}; return A;
})();var B = (function (_A) { function B() { if (_A != null) {
_A.apply(this, arguments);
}
}

_inherits(B, _A);

B.prototype.toString = function toString() { return this.name + 'b';
}; return B;
})(A);
其他地方都不用看了,inherits 函数用到了之前学到的所有玩意,要求实现要满足下列所有的cases,就当是课后练习了:
var a= new A('A');var b= new B('B');
a.constructor === A &&
b.constructor === B &&
a instanceof A &&
b instanceof A &&
b instanceof B

  • https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/instanceof
  • 这里只是意思,但是如果真的改变 __proto__ 是非常低效的https://developer.mozilla.org/ ... proto
  • http://www.ecma-international.org/ecma-262/6.0/#sec-additional-properties-of-the-object.prototype-object


Author: Jichao Ouyang
0
评论

不算“真正的语言”?详说Swift 2.0中的错误处理 移动开发 swift

oscar1212 发表了文章 • 1595 次浏览 • 2015-07-15 17:25 • 来自相关话题

苹果公司在今年的全球开发者大会(Worldwide Developers Conference, WWDC)上宣布推出Swift2.0,该语言的首席架构师Chris Lattner表示,Swift 2.0主要在语言基本语法、安全性和格式美观度这三方面进行了改进。除了这些新的功能特性,还有对语法的优化、修饰及美化,最后是Swift 1.x中最具影响力的错误处理机制。
 
历史一瞬:不起眼的开端

我们都知道,Swift语言作为Objective-C当前替代语言被推出,是OS X和iOS应用程序开发的“通用语”。在最初的版本中,Objective-C没有原生的异常处理机制。后来通过添加NSException类,还有 NS_DURING, NS_HANDLER和 NS_ENDHANDLER宏才有了异常处理。这种方案现在被称为“经典的异常处理”,还有这些宏都是基于setjmp()和longjmp()这两个C语言函数的。

异常捕获(exception-catching)看起来如下所示,在NS_DURING和NS_HANDLER宏之间抛出的任何异常都将会导致在NS_HANDLER和NS_ENDHANDLER宏之间执行相应的代码。
NS_DURING
2. // Call a dangerous method or function that raises an exception:
3. [obj someRiskyMethod];
4.NS_HANDLER
5. NSLog(@"Oh no!");
6. [anotherObj makeItRight];
7.NS_ENDHANDLER
下面是立刻能触发抛出异常的方法(现在仍然可用):

[cpp] view plaincopy
1.- (void)someRiskyMethod
2.{
3. [NSException raise:@"Kablam"
4. format:@"This method is not implemented yet. Do not call!"];
5.}
可以想象,这种手工处理异常的方式戏弄的是早期Cocoa框架程序开发人员。但是这些程序员还不至于到这份儿上,因为他们很少使用这种方式。无论在Cocoa还是Cocoa Touch框架下,异常通常都被归为灾难性的,不可恢复的错误,比如程序员造成的错误。上面的-someRiskyMethod就是很好的例子,由于实现部分没有准备好而引发了异常。在Cocoa和Cocoa Touch框架中,可恢复的错误由稍后讨论的NSError类来处理。

原生的异常处理

我想由于Objective-C中的经典异常处理机制对应的手工处理方式让人感觉闹心,于是苹果公司在Mac OS X 10.3(2003年10月)中发布了原生的异常处理机制,彼时还没有iOS系统。这本质上是将C++的异常处理嫁接到了Objective-C。异常处理的结构目前看起来是这样的:
@try {
2. [obj someRiskyMethod];
3.}
4.@catch (SomeClass *exception) {
5. // Handle the error.
6. // Can use the exception object to gather information.
7.}
8.@catch (SomeOtherClass *exception) {
9. // ...
10.}
11.@catch (id allTheRest) {
12. // ...
13.}
14.@finally {
15. // Code that is executed whether an exception is thrown or not.
16. // Use for cleanup.
17.}
原生的异常处理使你有机会为每个异常类型指定不同@catch部分。无论@try结果如何,@finally都要执行其对应的代码。

尽管原生的异常处理如所预期的那样抛出一个NSException异常,但是最明确的方法还是“@throw <expression>;”语句。通常你抛出的是NSException实例,但说不定什么对象会被抛出。

NSError

尽管Objective-C原生与经典的异常处理有许多优点,但Cocoa和Cocoa Touch框架应用程序开发人员仍然很少使用异常,而是限制程序出现程序员所导致的不可恢复的错误。使用NSError类处理可恢复的错误,这种方法早于使用异常处理。Swift 1.x也继承了NSError的样式。

在Swift 1.x中,Cocoa和Cocoa Touch的方法和函数可能不会返回一个布尔类型的false或者nil来表示一个失败(failure)的对象。另外,NSErrorPointer对象会被当作一个参数返回特定的失败信息。下面是个典型的例子:

cpp] view plaincopy
1.// A local variable to store an error object if one comes back:
2.var error: NSError?
3.// success is a Bool:
4.let success = someString.writeToURL(someURL,
5. atomically: true,
6. encoding: NSUTF8StringEncoding,
7. error: &error)
8.if !success {
9. // Log information about the error:
10. println("Error writing to URL: \(error!)")
11.}
程序员所导致的错误可以用Swift标准库(Swift Standard Library)函数fatalError("Error message”)来标记,将其在控制台记录为错误消息并无条件中止执行。还可以使用assert(), assertionFailure(), precondition()和preconditionFailure()这些函数。

Swift第一次发布时,一些非苹果平台开发人员已经准备好了火把和干草叉。他们声称Swift不能算是“真正的语言”,因为它缺乏异常处理。但是,Cocoa和Cocoa Touch社区对此不予理睬,我们知道NSError和NSException那个时候就存在了。就我个人而言,我相信苹果公司仍然在思考实现错误和异常处理的正确方式。我还认为直到问题解决了,苹果公司才会公开Swift源码。这一切问题在Swift 2.0中全被扫清了。 
 
Swift 2.0中的错误处理

在Swift 2.0中,如果想要抛出错误,那么抛出的对象必须符合ErrorType协议。可能正如你所愿,NSError就符合该协议。枚举在这里用来给错误进行分类。
enum AwfulError: ErrorType {
2. case Bad
3. case Worse
4. case Terrible
5.}
然后如果一个可能抛出一个或多个错误的函数或方法会被throws关键字标记:
func doDangerousStuff() throws -> SomeObject {
2. // If something bad happens throw the error:
3. throw AwfulError.Bad
4.
5. // If something worse happens, throw another error:
6. throw AwfulError.Worse
7.
8. // If something terrible happens, you know what to do:
9. throw AwfulError.Terrible
10.
11. // If you made it here, you can return:
12. return SomeObject()
13.}
为了捕获错误,新型的do-catch语句出现了:
do {
2. let theResult = try obj.doDangerousStuff()
3.}
4.catch AwfulError.Bad {
5. // Deal with badness.
6.}
7.catch AwfulError.Worse {
8. // Deal with worseness.
9.}
10.catch AwfulError.Terrible {
11. // Deal with terribleness.
12.}
13.catch ErrorType {
14. // Unexpected error!
15.}
这个do-catch语句和switch语句有一些相似之处,被捕获的错误详尽无遗,因此你可以使用这种样式来捕获抛出的错误。还要注意关键字try的使用。它是为了明确地标示抛出的代码行,因此当阅读代码的时候,你能够立刻找到错误在哪里。

关键字try的变体是“try!”。这个关键字大概也适用于那些程序员导致的错误。如果使用“try!”标记一个被调用的抛出对象中的方法,你等于告诉编译器这个错误永远不会发生,并且你也不需要捕获它。如果该语句本身产生了错误(error),应用程序会停止执行,那么你就要开始调试了。
let theResult = try! obj.doDangerousStuff() 与Cocoa和Cocoa Touch框架间的交互

现在的问题是,你如何在Swift 2.0中处理爷爷级的NSError API呢?苹果公司已经在Swift 2.0中为统一代码行为作了大量工作,并且已经为未来写入Swift的框架准备方法。Cocoa和Cocoa Touch中可以产生NSError实例的方法和函数有苹果公司的签名( signature),可以自动转换为Swift新的错误处理方式。

例如,这个NSString的构造器( initializer)在Swift 1.x中就有以下签名:
convenience init?(contentsOfFile path: String,
2. encoding enc: UInt,
3. error error: NSErrorPointer)
注意:在Swift 2.0中,构造器不再被标记为failable,它并不需要NSErrorPointer来做参数,而是使用抛出异常的方式显式地指示潜在的失败。

下面的例子使用了这种新的签名:
do {
2. let str = try NSString(contentsOfFile: "Foo.bar",
3. encoding: NSUTF8StringEncoding)
4.}
5.catch let error as NSError {
6. print(error.localizedDescription)
7.}
注意错误是如何被捕获的,并且如何被转换成了一个NSError实例,这样你就可以获取与其相似API的信息了。事实上,任何ErrorType类型的实例都可以转换成NSError类型。

最后说说@finally

细心的读者可能已经注意到,Swift 2.0引入了一个新的do-catch语句,而不是do-catch-finally。不管是否捕捉到错误的情况下,你如何指定必须运行的代码呢?为此,现在可以使用defer语句,用来推迟代码块的执行直到当前的作用域结束。
// Some scope:
2.{
3. // Get some resource.
4.
5. defer {
6. // Release resource.
7. }
8.
9. // Do things with the resource.
10. // Possibly return early if an error occurs.
11.
12.} // Deferred code is executed at the end of the scope.
Swift 2.0将Cocoa和Cocoa Touch的错误处理机制凝聚为具有现代风格的用法,这是一项伟大的工作,也会使许多程序员倍感亲切。统一行为是不错的定位,会使Swift语言和其所继承的框架逐步发展。
 
文章来源:Big Nerd Ranch 查看全部
苹果公司在今年的全球开发者大会(Worldwide Developers Conference, WWDC)上宣布推出Swift2.0,该语言的首席架构师Chris Lattner表示,Swift 2.0主要在语言基本语法、安全性和格式美观度这三方面进行了改进。除了这些新的功能特性,还有对语法的优化、修饰及美化,最后是Swift 1.x中最具影响力的错误处理机制。
 
历史一瞬:不起眼的开端

我们都知道,Swift语言作为Objective-C当前替代语言被推出,是OS X和iOS应用程序开发的“通用语”。在最初的版本中,Objective-C没有原生的异常处理机制。后来通过添加NSException类,还有 NS_DURING, NS_HANDLER和 NS_ENDHANDLER宏才有了异常处理。这种方案现在被称为“经典的异常处理”,还有这些宏都是基于setjmp()和longjmp()这两个C语言函数的。

异常捕获(exception-catching)看起来如下所示,在NS_DURING和NS_HANDLER宏之间抛出的任何异常都将会导致在NS_HANDLER和NS_ENDHANDLER宏之间执行相应的代码。
NS_DURING  
2. // Call a dangerous method or function that raises an exception:
3. [obj someRiskyMethod];
4.NS_HANDLER
5. NSLog(@"Oh no!");
6. [anotherObj makeItRight];
7.NS_ENDHANDLER
下面是立刻能触发抛出异常的方法(现在仍然可用):

[cpp] view plaincopy
1.- (void)someRiskyMethod
2.{
3. [NSException raise:@"Kablam"
4. format:@"This method is not implemented yet. Do not call!"];
5.}
可以想象,这种手工处理异常的方式戏弄的是早期Cocoa框架程序开发人员。但是这些程序员还不至于到这份儿上,因为他们很少使用这种方式。无论在Cocoa还是Cocoa Touch框架下,异常通常都被归为灾难性的,不可恢复的错误,比如程序员造成的错误。上面的-someRiskyMethod就是很好的例子,由于实现部分没有准备好而引发了异常。在Cocoa和Cocoa Touch框架中,可恢复的错误由稍后讨论的NSError类来处理。

原生的异常处理

我想由于Objective-C中的经典异常处理机制对应的手工处理方式让人感觉闹心,于是苹果公司在Mac OS X 10.3(2003年10月)中发布了原生的异常处理机制,彼时还没有iOS系统。这本质上是将C++的异常处理嫁接到了Objective-C。异常处理的结构目前看起来是这样的:
@try {  
2. [obj someRiskyMethod];
3.}
4.@catch (SomeClass *exception) {
5. // Handle the error.
6. // Can use the exception object to gather information.
7.}
8.@catch (SomeOtherClass *exception) {
9. // ...
10.}
11.@catch (id allTheRest) {
12. // ...
13.}
14.@finally {
15. // Code that is executed whether an exception is thrown or not.
16. // Use for cleanup.
17.}
原生的异常处理使你有机会为每个异常类型指定不同@catch部分。无论@try结果如何,@finally都要执行其对应的代码。

尽管原生的异常处理如所预期的那样抛出一个NSException异常,但是最明确的方法还是“@throw <expression>;”语句。通常你抛出的是NSException实例,但说不定什么对象会被抛出。

NSError

尽管Objective-C原生与经典的异常处理有许多优点,但Cocoa和Cocoa Touch框架应用程序开发人员仍然很少使用异常,而是限制程序出现程序员所导致的不可恢复的错误。使用NSError类处理可恢复的错误,这种方法早于使用异常处理。Swift 1.x也继承了NSError的样式。

在Swift 1.x中,Cocoa和Cocoa Touch的方法和函数可能不会返回一个布尔类型的false或者nil来表示一个失败(failure)的对象。另外,NSErrorPointer对象会被当作一个参数返回特定的失败信息。下面是个典型的例子:

cpp] view plaincopy
1.// A local variable to store an error object if one comes back:
2.var error: NSError?
3.// success is a Bool:
4.let success = someString.writeToURL(someURL,
5. atomically: true,
6. encoding: NSUTF8StringEncoding,
7. error: &error)
8.if !success {
9. // Log information about the error:
10. println("Error writing to URL: \(error!)")
11.}
程序员所导致的错误可以用Swift标准库(Swift Standard Library)函数fatalError("Error message”)来标记,将其在控制台记录为错误消息并无条件中止执行。还可以使用assert(), assertionFailure(), precondition()和preconditionFailure()这些函数。

Swift第一次发布时,一些非苹果平台开发人员已经准备好了火把和干草叉。他们声称Swift不能算是“真正的语言”,因为它缺乏异常处理。但是,Cocoa和Cocoa Touch社区对此不予理睬,我们知道NSError和NSException那个时候就存在了。就我个人而言,我相信苹果公司仍然在思考实现错误和异常处理的正确方式。我还认为直到问题解决了,苹果公司才会公开Swift源码。这一切问题在Swift 2.0中全被扫清了。 
 
Swift 2.0中的错误处理

在Swift 2.0中,如果想要抛出错误,那么抛出的对象必须符合ErrorType协议。可能正如你所愿,NSError就符合该协议。枚举在这里用来给错误进行分类。
enum AwfulError: ErrorType {  
2. case Bad
3. case Worse
4. case Terrible
5.}
然后如果一个可能抛出一个或多个错误的函数或方法会被throws关键字标记:
func doDangerousStuff() throws -> SomeObject {  
2. // If something bad happens throw the error:
3. throw AwfulError.Bad
4.
5. // If something worse happens, throw another error:
6. throw AwfulError.Worse
7.
8. // If something terrible happens, you know what to do:
9. throw AwfulError.Terrible
10.
11. // If you made it here, you can return:
12. return SomeObject()
13.}
为了捕获错误,新型的do-catch语句出现了:
do {  
2. let theResult = try obj.doDangerousStuff()
3.}
4.catch AwfulError.Bad {
5. // Deal with badness.
6.}
7.catch AwfulError.Worse {
8. // Deal with worseness.
9.}
10.catch AwfulError.Terrible {
11. // Deal with terribleness.
12.}
13.catch ErrorType {
14. // Unexpected error!
15.}
这个do-catch语句和switch语句有一些相似之处,被捕获的错误详尽无遗,因此你可以使用这种样式来捕获抛出的错误。还要注意关键字try的使用。它是为了明确地标示抛出的代码行,因此当阅读代码的时候,你能够立刻找到错误在哪里。

关键字try的变体是“try!”。这个关键字大概也适用于那些程序员导致的错误。如果使用“try!”标记一个被调用的抛出对象中的方法,你等于告诉编译器这个错误永远不会发生,并且你也不需要捕获它。如果该语句本身产生了错误(error),应用程序会停止执行,那么你就要开始调试了。
let theResult = try! obj.doDangerousStuff()  
与Cocoa和Cocoa Touch框架间的交互

现在的问题是,你如何在Swift 2.0中处理爷爷级的NSError API呢?苹果公司已经在Swift 2.0中为统一代码行为作了大量工作,并且已经为未来写入Swift的框架准备方法。Cocoa和Cocoa Touch中可以产生NSError实例的方法和函数有苹果公司的签名( signature),可以自动转换为Swift新的错误处理方式。

例如,这个NSString的构造器( initializer)在Swift 1.x中就有以下签名:
convenience init?(contentsOfFile path: String,  
2. encoding enc: UInt,
3. error error: NSErrorPointer)
注意:在Swift 2.0中,构造器不再被标记为failable,它并不需要NSErrorPointer来做参数,而是使用抛出异常的方式显式地指示潜在的失败。

下面的例子使用了这种新的签名:
do {  
2. let str = try NSString(contentsOfFile: "Foo.bar",
3. encoding: NSUTF8StringEncoding)
4.}
5.catch let error as NSError {
6. print(error.localizedDescription)
7.}
注意错误是如何被捕获的,并且如何被转换成了一个NSError实例,这样你就可以获取与其相似API的信息了。事实上,任何ErrorType类型的实例都可以转换成NSError类型。

最后说说@finally

细心的读者可能已经注意到,Swift 2.0引入了一个新的do-catch语句,而不是do-catch-finally。不管是否捕捉到错误的情况下,你如何指定必须运行的代码呢?为此,现在可以使用defer语句,用来推迟代码块的执行直到当前的作用域结束。
// Some scope:  
2.{
3. // Get some resource.
4.
5. defer {
6. // Release resource.
7. }
8.
9. // Do things with the resource.
10. // Possibly return early if an error occurs.
11.
12.} // Deferred code is executed at the end of the scope.
Swift 2.0将Cocoa和Cocoa Touch的错误处理机制凝聚为具有现代风格的用法,这是一项伟大的工作,也会使许多程序员倍感亲切。统一行为是不错的定位,会使Swift语言和其所继承的框架逐步发展。
 
文章来源:Big Nerd Ranch
0
评论

全球扫货指南集成环信移动客服:订单量客单价双丰收 环信移动客服 环信 移动开发

admin 发表了文章 • 1472 次浏览 • 2015-07-14 16:27 • 来自相关话题

移动互联网时代,同时迎来了全民创业的时代,虽然这两者不能划上等号,但不能否认,移动互联网的普及,给全民创业提供了更多的创新灵感,也赋予了电商更多活力。笔者了解的一些电商,已完全摒弃PC端接入口,而只从移动端进行接入。





在传统大型平台电商的窗口已经被逐渐关闭的时候,新入场的玩家必须借助移动端和社交实现弯道超车,移动电子商务公司“全球扫货指南”便是中国移动互联网发展的其中一家受益企业,其市场总监左小禛便认为:电子商务的未来是移动电商,而移动电商必须重视移动客服。

移动电商的三个关键点

的确,百度无线数据报告显示,移动互联网创业者开发经验不足1年的人数比例为38.3%,个人开发者比例明显上升,同时11—20人团队开发比例下降,移动开发者生态从量变向质变迁移。此外,移动互联网创业者对商业模式的探索和创新尚无特定模式可以借鉴。上述状况下,移动电商创业者如何实现弯道超车?笔者认为,以下三个关键点需要重点把握:

1、转变思维,认清客户在哪?

移动互联网时代用户数的迅猛增长,已是必然趋势。用户数的急速增长,意味着巨大的机会,同时也意味着巨大的挑战,终端的小型化、多样化,接入方式的多样化都意味着我们处在全新的互联网生态环境中。

Gartner预测,到2017年年底,超过70%的交易将来自于移动端。2014年阿里双十一的现场监控显示,总成交额571亿其中移动端贡献了243亿,移动端交易量比例将有超过PC端的趋势。同时,京东2014年第四季度财报显示移动端的订单量占比接近40%。

因此,移动互联网时代,电商行业应转变思维,认清客户来源趋势,应在移动端的各个接口做好整体布局,无论是营销、服务还是流程,应进行相应梳理。

2、移动互联网的营销,社交为王!

但在移动互联时代,营销渠道越来越多。过去的营销是通过电视、报纸等渠道跟消费者沟通,但移动互联网时代则是分享的时代,免费思维已成为主流,为了让用户喜欢,愿意分享,消费者和商家会直接面对面进行免费试用与体验,通过各种活动进行赠予、使用,增强体验。这也使移动互联网时代的电商营销成本非常巨大。

移动互联网时代的营销除了普通的宣传、引导、试用、免费等传统方式外,更多的具有社交化属性,用户体验变得如此重要,即时通讯所具有的实时性、互动社交性让移动电商更具活力。甚至很多商家都搭建了基于兴趣社交的板块辅助自身电商平台,通过社区导购来降低用户的购买决策成本,在非标品等方面与传统大电商平台竞争获取优势实现弯道超车。

3、移动互联网的客户服务,体验为王!

营销的成功,只能带来一定的流量,但真正的交易与再次销售,则一定是产品本身具有的价值及客户服务所带给客户的体验。我们经常说,客户在哪,客户服务就要跟到哪。客户在移动端,移动端的客户服务如果不到位,不但订单丢失,客户丢失,甚至公司也可能被那些更重视移动端的用户服务体验的公司,更能迅速把握时代大趋势的公司所颠覆。一项研究报告指出,如果做不好客服,辛辛苦苦通过各种渠道引流到自己App、网站、平台、账号的客户,95%都会流失掉。

因此,电商已从PC端转战到了移动端,移动端有其特定的消费属性,无论是营销与服务,应从移动端的消费属性来研究。

移动电商的客服趋势

如果说电商的移动性趋势已得到行业认可,各个大、中型电子商务公司正在奋力奔跑在移动端,正在全力争夺消费者手机上不多的APP安装上。但笔者需要提醒大家的是:太多企业过于重视营销,而对客户服务有所忽视。

客户服务的重要性已不需要赘述,笔者认为移动电商客服有几个趋势将带动电商企业的发展:

1、 多渠道融合,尤其以移动端为主的客服请求将占主导

客户服务请求来源包括传统呼叫中心的语音、基于网页的实时在线聊天系统、工单系统、微博、微信等等。客户来源的多样性,让多渠道融合客服成为必须。另一方面,正如上文所述,如今的消费者正在远离PC和电话,消费者都去了移动端,所以客户服务将以移动端客服请求为主导。

2、 即时通讯(IM)将是最适合移动设备的客服服务形式

微信已成为我们最重要的日常沟通形式,界面简单易操作,不需要任何培训,人人都会使用,最重要的是,这是最适合移动设备的沟通方式。互联网女皇发布的《2015互联网趋势报告》也认为: IM不仅是世界上标准化程度最高的互联网产品,而且是世界上下载和使用量最大的互联网产品,也是用户交流体验最好的产品。异步又实时、个性化又主流、表达能力很强但又迅速等等。

传统400电话虽然也方便迅速,但笔者也经常因为400电话的无尽等待而挂机。虽然对12306这样的订票刚需企业影响不大,但如是电商企业,那客户流失率就太高了。因此,即时通讯式的客服形式非常适合移动设备,一个发送就能即时接送信息,按一个按钮就得到服务,可以秒级接通,并且可以得到7X24小时随时随地的解答。不用去填写工单,也不用在APP中遇到问题的时还要跳出APP外通过电话,邮件,微信,QQ等方式才能后被解决。

3、智能客服技术将得到大量应用

上文提到了即时通讯式的客服形式非常适合移动设备,移动互联网时代,客户手机24 小时随身携带的属性决定了传统5 X8小时的服务形式早已满足不了客户需求。客户需要实现一个发送就能即时接送信息,可以秒级接通,并且可以得到7X24小时随时随地的解答。我们可以想象的是,这个7X24小时随时随地的服务并不是企业派了足够多的人工座席在为客户提供服务,而是智能客服技术的一项应用。

智能客服技术是实时聊天的一种技术应用,因为即时通讯沟通方式最大的优势是可以一对多,即一个客服坐席可以同时和多个人聊天,使用自动菜单导航,语义分析,机器人智能应答,智能知识库等技术的大面积应用,“智能机器人+知识库”可以帮助回答80%的常见问题,可大量减少传统座席人员数。

移动电商客服的三大难点透析

通过笔者对移动电商客服的几个趋势的梳理,我们看到,移动电商的消费群体的特定性,让移动客服与传统客服具有很多的不一致性,移动客服如需要做精做透,以下流程是难点:
 1、 集中的质检系统

传统语音客服因为可以通过录音、检索等方式进行客户服务质量检测,移动客服的即时通讯性、多渠道接入等属性,使客服的质量把控具有一定的难度。

2、 交易行业的大数据积累与分析

大量的移动端客服数据与传统来自于呼叫中心、Web端、微博、微信的客服数据,如何进行统一接入、积累与分析,进行数据挖掘实现商业转化,这是较大的难点也是最重要的商机,客户趋动才是需求的起点,是创新的动力。

3、 即时客服需要即时的信息管理

移动互联网时代,服务的即时性也对管理的即时性提出了很高的要求。移动电子商务公司全球扫货指南市场总监左小禛便深有体会:“移动电商经常会定期或者不定期举行一些活动,活动举办期间,服务请求较平常可能会有十倍甚至更多倍的增长,这样的环境下,如何去调配座席人员?如果知道何种渠道来源的增长比例?服务过程中出现了哪些问题?哪些是共性问题等等。移动环境下,即时客服要求有即时的信息管理。我们采用了环信移动客服,解决了我们客服过程中的很多难题。“

全球扫货指南的移动客服初体验

全球扫货指南是全球首家时尚买手制购物平台。平台上有各类买手推荐的奢侈单品,产品的价格搜索引擎可以帮助用户一键比价,比完之后觉得划算就可以找靠谱买手下单购买。全球扫货指南作为交易平台,实行第三方担保机制,若买卖双方发生纠纷,提供先行赔付。在CEO肖宇眼里,随着这几年电商的蓬勃发展,用户线上消费习惯正在快速被培养。目前客单价千元以上的电商玩家并不多,另一方面用户的消费升级不断加速,奢侈品购买呈年轻化,因此在手机上消费的客单价越来越高,将会给轻奢市场带来巨大的机会。
 
据左小禛介绍,全球扫货指南接入了这种智能移动客服产品后,可以实现快速注册、根据体验指南一两分钟内即可对接商家完成会话体验,同时实现了跨平台多渠道接入:支持 App、微信公众账号、微博、网页等,均可以快速统一接入客户服务后台管理。

其次,满足了开放性与自定义信息:这种新型的移动客服实现了代码开源、UI开源,还提供多套UI模版,这样便于与全球扫货指南自身的APP快速集成,平滑接入。同时第三方集成功能也很强大,可与第三方工单、知识库、CRM 系统等进行扩展集成。

第三,富媒体消息交互体验:移动客服平台提供了基于IM技术的类似微信体验的友好富媒体消息交互,不仅可以实时收发文字、表情,还可以即时收发图片、位置、实时语音、还可自定义消息,大大方便了与客户的沟通交流。

第四,精准客户画像功能:移动客服的IM沟通帮助全球扫货指南辅助判断客户需求与诉求,通过自定义客户分类标签,客户再次访问时可获知客户的类型。并且还支持自定义会话小结,根据会话小结统计会话的分类,通过会话小结追踪客户诉求。通过轨迹分析功能,即通过发送客户访问页面的轨迹,判断客户意图,获取客户个性化细节,了解客户基础信息,分析客户行为,可以极大提高订单效率。

第五,“智能机器人+智能知识库”:作为一套智能化的客服系统,全球扫货指南建立了基于业务的智能知识库,智能辅助归结业务信息和应答客户信息,历史常见问题系统梳理,提高客服效率。“智能机器人+智能知识库”组合目前可自动回复80%常见问题,随着智能知识库的不断训练,这一比例能够提高到90%。

第六、真正实现不丢订单:环信基于IM长连接技术,帮助全球扫货指南实现超线拉取排队会话,让等待时间过长或有订单需求的客户得到优先服务,提升客服效率,即使客户关闭会话,退出App,甚至关闭手机,基于IM长连接技术依然能找回客户会话,提升客服效率,不丢客户订单。同时,基于IM长连接技术,即使在断网或复杂网络切换时也依然能找回客户会话,不丢客户订单。

第七、实现了质检系统透明管理:移动客服自带实时监控系统,可实时监控当前所有会话,管理员在线质检,在线查看会话信息,还提供了历史会话查询、质检考核。通过实时与历史查看,可以统计出客服代表的接入量、在线时间及应答等待时间。

通过销售部和技术部返回的数据报告显示,左小禛判断,通过部署这种新型智能移动云客服,较于传统客服产品节省成本约60%,省电省流量高达80%,同时留住了70%会话客户,订单量和客单价均获得了不同幅度提升。目前全球扫货指南覆盖全球100个顶级奢侈品品牌,超过10万个热门单品。根据贝恩咨询的数据,中国人去年一年消费奢侈品3800亿元,其中70%在海外消费,仅代购市场就超过750亿元,奢侈品的海淘电商无疑是块很诱人的蛋糕。

移动客服的魅力,从上述数据的发布可看出,已超出了大家的想象!原因在于:传统客服体系下,客服只是成本中心,辅助部门;而在移动互联网时候下,客服俨然已成为核心流程之一,竞争力关键要素之一。

一位客服领域大佬曾这样总结这个时代:“伴随着客户互动的革命,从呼叫中心演变到的客户中心作为不断扩展的客户交互平台概念一直经历着深刻的变革。运营日益规模化,精准化、多通路化、智能化和普适化。作为集语音和非语音渠道为一体,人工与智能服务共协同,物理与数字的通路大融合,随着以客户理念,人文为中心时代的来临,客户服务中心正从企业价值链的一测走向价值传递的中央,与惊艳的产品研发一起发挥着客户体验创造的核心角色。”

移动客服,你已不能再等待! 查看全部
移动互联网时代,同时迎来了全民创业的时代,虽然这两者不能划上等号,但不能否认,移动互联网的普及,给全民创业提供了更多的创新灵感,也赋予了电商更多活力。笔者了解的一些电商,已完全摒弃PC端接入口,而只从移动端进行接入。

1.jpg

在传统大型平台电商的窗口已经被逐渐关闭的时候,新入场的玩家必须借助移动端和社交实现弯道超车,移动电子商务公司“全球扫货指南”便是中国移动互联网发展的其中一家受益企业,其市场总监左小禛便认为:电子商务的未来是移动电商,而移动电商必须重视移动客服。

移动电商的三个关键点

的确,百度无线数据报告显示,移动互联网创业者开发经验不足1年的人数比例为38.3%,个人开发者比例明显上升,同时11—20人团队开发比例下降,移动开发者生态从量变向质变迁移。此外,移动互联网创业者对商业模式的探索和创新尚无特定模式可以借鉴。上述状况下,移动电商创业者如何实现弯道超车?笔者认为,以下三个关键点需要重点把握:

1、转变思维,认清客户在哪?

移动互联网时代用户数的迅猛增长,已是必然趋势。用户数的急速增长,意味着巨大的机会,同时也意味着巨大的挑战,终端的小型化、多样化,接入方式的多样化都意味着我们处在全新的互联网生态环境中。

Gartner预测,到2017年年底,超过70%的交易将来自于移动端。2014年阿里双十一的现场监控显示,总成交额571亿其中移动端贡献了243亿,移动端交易量比例将有超过PC端的趋势。同时,京东2014年第四季度财报显示移动端的订单量占比接近40%。

因此,移动互联网时代,电商行业应转变思维,认清客户来源趋势,应在移动端的各个接口做好整体布局,无论是营销、服务还是流程,应进行相应梳理。

2、移动互联网的营销,社交为王!

但在移动互联时代,营销渠道越来越多。过去的营销是通过电视、报纸等渠道跟消费者沟通,但移动互联网时代则是分享的时代,免费思维已成为主流,为了让用户喜欢,愿意分享,消费者和商家会直接面对面进行免费试用与体验,通过各种活动进行赠予、使用,增强体验。这也使移动互联网时代的电商营销成本非常巨大。

移动互联网时代的营销除了普通的宣传、引导、试用、免费等传统方式外,更多的具有社交化属性,用户体验变得如此重要,即时通讯所具有的实时性、互动社交性让移动电商更具活力。甚至很多商家都搭建了基于兴趣社交的板块辅助自身电商平台,通过社区导购来降低用户的购买决策成本,在非标品等方面与传统大电商平台竞争获取优势实现弯道超车。

3、移动互联网的客户服务,体验为王!

营销的成功,只能带来一定的流量,但真正的交易与再次销售,则一定是产品本身具有的价值及客户服务所带给客户的体验。我们经常说,客户在哪,客户服务就要跟到哪。客户在移动端,移动端的客户服务如果不到位,不但订单丢失,客户丢失,甚至公司也可能被那些更重视移动端的用户服务体验的公司,更能迅速把握时代大趋势的公司所颠覆。一项研究报告指出,如果做不好客服,辛辛苦苦通过各种渠道引流到自己App、网站、平台、账号的客户,95%都会流失掉。

因此,电商已从PC端转战到了移动端,移动端有其特定的消费属性,无论是营销与服务,应从移动端的消费属性来研究。

移动电商的客服趋势

如果说电商的移动性趋势已得到行业认可,各个大、中型电子商务公司正在奋力奔跑在移动端,正在全力争夺消费者手机上不多的APP安装上。但笔者需要提醒大家的是:太多企业过于重视营销,而对客户服务有所忽视。

客户服务的重要性已不需要赘述,笔者认为移动电商客服有几个趋势将带动电商企业的发展:

1、 多渠道融合,尤其以移动端为主的客服请求将占主导

客户服务请求来源包括传统呼叫中心的语音、基于网页的实时在线聊天系统、工单系统、微博、微信等等。客户来源的多样性,让多渠道融合客服成为必须。另一方面,正如上文所述,如今的消费者正在远离PC和电话,消费者都去了移动端,所以客户服务将以移动端客服请求为主导。

2、 即时通讯(IM)将是最适合移动设备的客服服务形式

微信已成为我们最重要的日常沟通形式,界面简单易操作,不需要任何培训,人人都会使用,最重要的是,这是最适合移动设备的沟通方式。互联网女皇发布的《2015互联网趋势报告》也认为: IM不仅是世界上标准化程度最高的互联网产品,而且是世界上下载和使用量最大的互联网产品,也是用户交流体验最好的产品。异步又实时、个性化又主流、表达能力很强但又迅速等等。

传统400电话虽然也方便迅速,但笔者也经常因为400电话的无尽等待而挂机。虽然对12306这样的订票刚需企业影响不大,但如是电商企业,那客户流失率就太高了。因此,即时通讯式的客服形式非常适合移动设备,一个发送就能即时接送信息,按一个按钮就得到服务,可以秒级接通,并且可以得到7X24小时随时随地的解答。不用去填写工单,也不用在APP中遇到问题的时还要跳出APP外通过电话,邮件,微信,QQ等方式才能后被解决。

3、智能客服技术将得到大量应用

上文提到了即时通讯式的客服形式非常适合移动设备,移动互联网时代,客户手机24 小时随身携带的属性决定了传统5 X8小时的服务形式早已满足不了客户需求。客户需要实现一个发送就能即时接送信息,可以秒级接通,并且可以得到7X24小时随时随地的解答。我们可以想象的是,这个7X24小时随时随地的服务并不是企业派了足够多的人工座席在为客户提供服务,而是智能客服技术的一项应用。

智能客服技术是实时聊天的一种技术应用,因为即时通讯沟通方式最大的优势是可以一对多,即一个客服坐席可以同时和多个人聊天,使用自动菜单导航,语义分析,机器人智能应答,智能知识库等技术的大面积应用,“智能机器人+知识库”可以帮助回答80%的常见问题,可大量减少传统座席人员数。

移动电商客服的三大难点透析

通过笔者对移动电商客服的几个趋势的梳理,我们看到,移动电商的消费群体的特定性,让移动客服与传统客服具有很多的不一致性,移动客服如需要做精做透,以下流程是难点:
 1、 集中的质检系统

传统语音客服因为可以通过录音、检索等方式进行客户服务质量检测,移动客服的即时通讯性、多渠道接入等属性,使客服的质量把控具有一定的难度。

2、 交易行业的大数据积累与分析

大量的移动端客服数据与传统来自于呼叫中心、Web端、微博、微信的客服数据,如何进行统一接入、积累与分析,进行数据挖掘实现商业转化,这是较大的难点也是最重要的商机,客户趋动才是需求的起点,是创新的动力。

3、 即时客服需要即时的信息管理

移动互联网时代,服务的即时性也对管理的即时性提出了很高的要求。移动电子商务公司全球扫货指南市场总监左小禛便深有体会:“移动电商经常会定期或者不定期举行一些活动,活动举办期间,服务请求较平常可能会有十倍甚至更多倍的增长,这样的环境下,如何去调配座席人员?如果知道何种渠道来源的增长比例?服务过程中出现了哪些问题?哪些是共性问题等等。移动环境下,即时客服要求有即时的信息管理。我们采用了环信移动客服,解决了我们客服过程中的很多难题。“

全球扫货指南的移动客服初体验

全球扫货指南是全球首家时尚买手制购物平台。平台上有各类买手推荐的奢侈单品,产品的价格搜索引擎可以帮助用户一键比价,比完之后觉得划算就可以找靠谱买手下单购买。全球扫货指南作为交易平台,实行第三方担保机制,若买卖双方发生纠纷,提供先行赔付。在CEO肖宇眼里,随着这几年电商的蓬勃发展,用户线上消费习惯正在快速被培养。目前客单价千元以上的电商玩家并不多,另一方面用户的消费升级不断加速,奢侈品购买呈年轻化,因此在手机上消费的客单价越来越高,将会给轻奢市场带来巨大的机会。
 
据左小禛介绍,全球扫货指南接入了这种智能移动客服产品后,可以实现快速注册、根据体验指南一两分钟内即可对接商家完成会话体验,同时实现了跨平台多渠道接入:支持 App、微信公众账号、微博、网页等,均可以快速统一接入客户服务后台管理。

其次,满足了开放性与自定义信息:这种新型的移动客服实现了代码开源、UI开源,还提供多套UI模版,这样便于与全球扫货指南自身的APP快速集成,平滑接入。同时第三方集成功能也很强大,可与第三方工单、知识库、CRM 系统等进行扩展集成。

第三,富媒体消息交互体验:移动客服平台提供了基于IM技术的类似微信体验的友好富媒体消息交互,不仅可以实时收发文字、表情,还可以即时收发图片、位置、实时语音、还可自定义消息,大大方便了与客户的沟通交流。

第四,精准客户画像功能:移动客服的IM沟通帮助全球扫货指南辅助判断客户需求与诉求,通过自定义客户分类标签,客户再次访问时可获知客户的类型。并且还支持自定义会话小结,根据会话小结统计会话的分类,通过会话小结追踪客户诉求。通过轨迹分析功能,即通过发送客户访问页面的轨迹,判断客户意图,获取客户个性化细节,了解客户基础信息,分析客户行为,可以极大提高订单效率。

第五,“智能机器人+智能知识库”:作为一套智能化的客服系统,全球扫货指南建立了基于业务的智能知识库,智能辅助归结业务信息和应答客户信息,历史常见问题系统梳理,提高客服效率。“智能机器人+智能知识库”组合目前可自动回复80%常见问题,随着智能知识库的不断训练,这一比例能够提高到90%。

第六、真正实现不丢订单:环信基于IM长连接技术,帮助全球扫货指南实现超线拉取排队会话,让等待时间过长或有订单需求的客户得到优先服务,提升客服效率,即使客户关闭会话,退出App,甚至关闭手机,基于IM长连接技术依然能找回客户会话,提升客服效率,不丢客户订单。同时,基于IM长连接技术,即使在断网或复杂网络切换时也依然能找回客户会话,不丢客户订单。

第七、实现了质检系统透明管理:移动客服自带实时监控系统,可实时监控当前所有会话,管理员在线质检,在线查看会话信息,还提供了历史会话查询、质检考核。通过实时与历史查看,可以统计出客服代表的接入量、在线时间及应答等待时间。

通过销售部和技术部返回的数据报告显示,左小禛判断,通过部署这种新型智能移动云客服,较于传统客服产品节省成本约60%,省电省流量高达80%,同时留住了70%会话客户,订单量和客单价均获得了不同幅度提升。目前全球扫货指南覆盖全球100个顶级奢侈品品牌,超过10万个热门单品。根据贝恩咨询的数据,中国人去年一年消费奢侈品3800亿元,其中70%在海外消费,仅代购市场就超过750亿元,奢侈品的海淘电商无疑是块很诱人的蛋糕。

移动客服的魅力,从上述数据的发布可看出,已超出了大家的想象!原因在于:传统客服体系下,客服只是成本中心,辅助部门;而在移动互联网时候下,客服俨然已成为核心流程之一,竞争力关键要素之一。

一位客服领域大佬曾这样总结这个时代:“伴随着客户互动的革命,从呼叫中心演变到的客户中心作为不断扩展的客户交互平台概念一直经历着深刻的变革。运营日益规模化,精准化、多通路化、智能化和普适化。作为集语音和非语音渠道为一体,人工与智能服务共协同,物理与数字的通路大融合,随着以客户理念,人文为中心时代的来临,客户服务中心正从企业价值链的一测走向价值传递的中央,与惊艳的产品研发一起发挥着客户体验创造的核心角色。”

移动客服,你已不能再等待!
0
评论

环信CEO:环信移动客服技术全解析 移动开发 环信

admin 发表了文章 • 2791 次浏览 • 2015-07-14 16:20 • 来自相关话题

摘要:《近匠》第92期,在专注于为开发者提供移动端即时通讯解决方案的同时,环信也开始了在连接人与商业、物与物版块的IM生态布局。环信CEO刘俊彦深剖环信移动客服的核心技术,以及对开源与未来无所不在的客服场景畅想。上线一年多的时间,环信的团队已经扩大到一百多人,在专注于为开发者提供移动端即时通讯解决方案的同时,环信开始了在连接人与商业、物与物版块的IM生态布局。并于近期推出专为移动端打造的客服平台,与环信IM SDK共享核心代码。本期《近匠》专访环信CEO 刘俊彦,听他讲述打造环信移动客服的核心技术与挑战,以及环信对开源与未来无所不在的客服场景畅想。





图:环信CEO 刘俊彦

CSDN:最初决定打造这样一个移动客服平台有着哪些初衷和考虑?

刘俊彦:首先从现实说起,从去年上线之后,就不断地有海淘、生活O2O等领域的开发者表示,使用环信IM SDK来做手机App的内置客服通道还是很好用的,但希望环信同时还能够提供一个具备客服工作台、工单分配、KPI考核等功能的客服平台。其实我的第一反应是拒绝的,因为这好像与即时通讯本身并没有太大关系,但随着这方面用户需求的增长,我们便开始思考这个问题。

其次,与战略方面也有所契合,我们所希望的是能够通过环信将所有人、物都连接起来,但之前却只拘泥于连接人与人的社交,在环信的版图中缺少着连接人与商业、人和客户的版块。因此,我们决定开发移动客服系统,让用户和商家可以直接在应用中聊起来,打造出一个完整的IM生态蓝图。

CSDN:在环信的产品线中,移动客服平台有着什么样的定位?

刘俊彦:移动客服平台是一个在IM基础上的行业应用,在IM已经覆盖几亿用户之后,我们就在思考下一步做什么?如果一款产品或某项功能能够真真切切地帮助到我们的IM用户,体验更爽,更有粘性,我们都会进行尝试。其实我们做了很多类似的工作,比如最近上线的关键字检测功能,就是为用户提供IM之上的最后一公里的额外的服务。移动客服同样如此,移动客服的核心还是IM,但我们同时还提供全套的完整的客服工作后台,有客户服务支持需求的用户不需要任何开发就可以直接使用,因此,我们将移动客服定位为IM在客户服务行业的垂直应用。

CSDN:云客服模式其实早有应用,相比其他服务提供商,环信移动客服平台有着哪些特色及技术优势?

刘俊彦:当下的客服软件市场分为两部分,一是传统电话呼叫中心的客服,他们的沟通方式以语音沟通为主,第二类是非语音类的客服,一般归纳为新媒体客服。新媒体客服包含微信公众号、微博、网页、App等渠道来源。对网页端的客服渠道来说,其对客服服务器的并发技术要求并不高,因为通常是使用基于轮询的短连接技术。比如每天有十万人找客服咨询聊天,每人聊五分钟,那么平均到每秒钟也就最多2-3个人同时在聊天,服务器只需要支持每秒钟2到3个请求的并发,对服务器压力很小。但手机App客服就不一样了。从技术上来讲,好用的手机App客服技术要求手机与客服服务器之间保持着7x24的长连接。任何时候,只要用户不卸载你的App,客服就永远可以主动的去找到消费者,向他主动发送消息。举个例子,我们有的用户用这个技术做外呼营销。他先在自己的CRM系统里对他的用户挖掘打上标签,比如找到所有的2-4岁小孩的妈妈用户群体。然后向这类妈妈群体群发消息。发出去的促销消息在消费者的App端看来是一条推送过来的聊天消息,首先这个消息不会被错过。然后点击这个推送后就会进入到客服的一对一聊天页面。这样的促销消息发送方式因为是和真人客服之间一对一的双向交互,所以效果比那种单向的广告推送好很多,转化率非常高。类似这样的外呼营销方式,让客服部门从以前的成本中心变成了现在的营收中心。而这些营销方式,如果没有手机APP和客服服务器之间的IM长连接,是不可能做到的。

当然,IM长连接技术对服务器的技术能力以及成本压力也增大许多,因为哪怕一个用户从来没找过客服聊天,我们也要为这个用户在他的手机和服务器端之间维护一个长连接,这个长连接会7X24小时的运行着。通常有100万的月活,就意味着要维护100万的长连接。但这却是环信的优势所在。环信移动客服平台与其他客服提供商最大的区别就是在移动端的IM长连接技术。在这点上,环信基本是垄断地位。

CSDN:可否详解环信移动客服平台的智能应答系统在面对海量请求时,如何做到真正智能地屏蔽与提炼?

刘俊彦:全球有100亿设备24小时连在网上,他们随时随地都能通过移动设备内置的客服通道找到客服,所以移动端的客服要应对的请求可能是海量的。对客服部门来说,利用原本的人工客服团队再加上新型的智能机器人客服系统,可以让问题解决效率呈指数性增长。传统的聊天机器人技术是基于搜索的问答匹配,而环信的智能客服是最新的基于深度机器学习的技术,不仅可以根据上下文进行推理,还能对人工座席和客户的交流进行实时学习和训练,极大降低知识库的维护成本。

目前,智能聊天机器人技术最实际的应用场景是基于文字交互的客服系统,包括短信、微信公众号、App内置客服、网页在线客服等,不仅降低了原本一年四季24小时在线的客服中心成本,更让拥有极致用户体验的新一代客服中心成为可能。

但是,相比之下,人工服务永远是最智能、最好的服务,在产品设计上,应实现人工与智能服务的无缝切换,当智能客服回答比较勉为其难的时候,就直接切换到人工服务,这样才能为客户提供更好的体验。所以客服系统中的聊天机器人技术最重要的是做好人工座席和机器人座席之间的无缝高效的切换,而不用刻意追求智能机器人技术的智能程度。客服系统中的智能聊天机器人只需解决特定领域的知识问题,无需像微软小冰那样陪用户聊人生聊理想。

CSDN:在移动客服平台开发的过程中,遇到过哪些难点与挑战?如何解决的?

刘俊彦:对移动客服来说,有两个技术难点。首当其冲便是在手机上为客户提供服务,IM技术是最适合用来在手机上连接客户和商家的。IM长连接技术能保障客服随时随地主动联系到客户、断网或复杂网络切换时不丢客户,并对电量流量进行优化。同时,也必须让客服人员、商家使用起来非常爽,即客服工作台好不好用、能不能提高客服效率、是否能进行全方位的KPI考核等。

对客服而言,即时通讯可谓是重中之重,在纯社交领域,消息丢失或晚到可能不是太大问题,但客服不一样,如果一条消息丢失或延迟,可能就意味着会发生丢单、客户流失情况,商业损失会非常大。所以对于选购移动客服的商家来说,他们希望移动端的IM技术和支撑客服工作人员的客服后台技术能够由一个厂商来统一提供。而不是说需要客服后台用这家,即时通讯买那家,这样在使用移动客服产品过程中遇到任何问题,都可以通过一个厂商一次性地及时解决。

CSDN:在移动网络环境下,弱网络、丢消息、丢订单等问题天然存在,环信采取了哪些技术手段来解决这一难题?通过哪些机制确保做到真正的不丢消息、不丢客户订单,还能省电省流量?

刘俊彦:这是环信过去一年多一直在做的事情,其实大多数IM厂商也能保证做到,但这的确还存在一些技术难点。首先,如何保证不丢消息?就必须通过一个好的协议来实现,必须保证协议本身是完全可靠,一定不会丢消息的,而在电量、流量的节约方面则包含协议、实现等诸多层面的优化。当然,无论是电量、流量的节约还是保证消息及时到达,除了最根本的协议、架构等,还包括许多细节方面的长时间打磨,才能不断地进步。
举个例子,环信在去年针对用户需求进行了许多优化,其中有一点便是针对来自三四线城市使用2G网络的用户,在弱网络环境下发送图片速度非常慢的问题,进行了切片上传的优化,将一个50K大小的图片切成10片,开10个线程,同时上传,极大地提高了传送的成功率。

CSDN:将UI模板开源让开发者100%自定制是环信一直以来的做法,之前也上线了“更极客 更开源”的IM Geek开发者社区,并将SDK开源,请问环信在开源方面有着哪些具体的计划和措施?

刘俊彦:环信的创始成员都是做开源出身,现在有些人对开源软件存在误解,而我们从不认为开源软件就意味着不好、不安全、低质量,这点从Linux就可以显而易见。我曾在Redhat担任高级开发工程师的工作,现在,许多公司都在使用Linux,也没有人会给予Linux不安全、不好用等差评。我们所希望的,不是自己重新去发明轮子,而是站在前人的肩膀上,取其精华去其糟粕,来进行自己的开发,比如最初在设计环信的通讯协议时,我们就借鉴了一部分XMPP的核心模块精华。

但XMPP协议并非为移动端设计,XMPP出现时还没有移动设备。在PC时代,用户不需要考虑电量、流量等问题,并且也不存在弱网络导致消息丢失的问题。这也就表明,我们必须将其中不好的部分推倒,进行重新设计或重写,开发出适用于移动端的IM协议。当然,XMPP也拥有很多优点,它存在十年,有许多插件,并充分考虑到协议的扩展,它是经过许多人不断摸索制定出来的协议,拥有着非常高的价值。

在使用开源软件的同时,我们也会反哺回馈开源社区,环信公司内的技术团队现在至少有十多个人都是一些知名的开源软件的committer,一直都在为开源软件贡献力量。现在有些公司可能会担心用开源软件出了问题后不可控制,这说明他们并没有用真正开源人的精神去使用开源软件,对于存在瑕疵的地方,就应该去改写代码,让它变得更好,而不是直接弃之如敝履。在开发过程中,如果使用到存在问题的开源软件,我们要做的事情就是去进行修改完善,然后将代码提交回去,让整个开源社区都能收益,这是环信对每个工程师的要求。

无论是将UI模板100%开源还是上线IM Geek开发者社区,我们的真正目的就是为开源社区做贡献,而不只是环信的产品。其实在当下的国内外开源社区方面,IM和移动社交还是空白的存在。现在,很多人都在做朋友圈、附近的人、聊天、匿名聊天或群组等功能,但归纳起来大概只有二三十种模块,剩下的工作便是各种模块的组合及编组。所以我们的想法就是开发者不用自己再去劳心劳力地重新开发一些基础和常见模块,而是通过社区的力量将这些模块都开发并开源出来,甚至包括基于这些模块的完整的应用,统统开源。这样不仅能节省创业团队大量的时间精力,也能降低开发成本,将资金投入到更好的用户体验、设计及运营上。

要经营好开源社区就必须以身作则,环信自身也在不断地贡献开源模块。当然,开源社区光靠一时的热情是远远不够的,未来,环信会为乐于开源的committer提供经济上的资助,只要开源软件做得好,并将其回馈给社区,提供开放下载。我们非常欢迎有开源情怀的开发者投身到开源事业中。

CSDN:环信移动客服在安全及保护用户隐私数据等方面有着哪些具体措施?

刘俊彦:隐私一直是很多公司一直在意的问题,会担心商业数据、用户信息会不会被窃取?环信移动客服对这方面是非常注意的,不会以任何形式碰触用户的聊天记录,用户可以100%随时导出或删除。而在系统保障方面,环信到目前已经趟过了许多雷点,并且内部还有一个每月演习的硬性规定,以此来保障即使发生系统挂掉的情况,核心功能依然可用。此外,环信正在着手“异地多活”,以此来提供更可靠、安全的服务。

CSDN:移动客服系统如何收费?

刘俊彦:IM已成红海,而移动客服则是商业化的企业级服务,需要为企业出现丢单等情况负责。环信移动客服系统的收费标准分为免费和收费用户数量级,2个座席以内可免费使用,超过2个座席的公司,需按每年每座席1500元进行收费。





图:环信移动客服收费标准

CSDN:现在大部分客服请求均来自于移动端,环信对于未来的移动客户服务还有着哪些畅想?

刘俊彦:当下,客户服务软件行业正在经历一场变革,用户获得服务的渠道和行为在发生巨变。随着环信移动客服这样的产品的普及,用户的服务体验将有极大的提升,而依托于技术进步,商家为此投入的人力成本却呈下降趋势。环信已经实现了人与人、人与商业的连接,但其生态布局依然缺少一块,就是人与物、物与物的连接。物联网正在临近,客户服务更将呈现完全不同的场景。我们需要做什么?首先就是物与物之间实现通讯功能的实时数据交换,其次,人如何控制设备?第三,在物与物之上,人和人之间需要沟通。

比如,一个物联网冰箱发生故障后,用户肯定不会再打400电话了。用户只需直接点击冰箱内嵌的客服按钮,即可一键接通,不仅可以和客服视频聊天得到帮助,还可以将冰箱的相关参数发送给客服,快速解决问题。同时,未来的客服一定是内嵌型的,将无处不在,无论是App、智能家居还是车联网,一个按钮所有问题都能搞定。目前,环信已经在着手物联网IM产品研发。 查看全部
摘要:《近匠》第92期,在专注于为开发者提供移动端即时通讯解决方案的同时,环信也开始了在连接人与商业、物与物版块的IM生态布局。环信CEO刘俊彦深剖环信移动客服的核心技术,以及对开源与未来无所不在的客服场景畅想。上线一年多的时间,环信的团队已经扩大到一百多人,在专注于为开发者提供移动端即时通讯解决方案的同时,环信开始了在连接人与商业、物与物版块的IM生态布局。并于近期推出专为移动端打造的客服平台,与环信IM SDK共享核心代码。本期《近匠》专访环信CEO 刘俊彦,听他讲述打造环信移动客服的核心技术与挑战,以及环信对开源与未来无所不在的客服场景畅想。

1.jpg

图:环信CEO 刘俊彦

CSDN:最初决定打造这样一个移动客服平台有着哪些初衷和考虑?

刘俊彦:首先从现实说起,从去年上线之后,就不断地有海淘、生活O2O等领域的开发者表示,使用环信IM SDK来做手机App的内置客服通道还是很好用的,但希望环信同时还能够提供一个具备客服工作台、工单分配、KPI考核等功能的客服平台。其实我的第一反应是拒绝的,因为这好像与即时通讯本身并没有太大关系,但随着这方面用户需求的增长,我们便开始思考这个问题。

其次,与战略方面也有所契合,我们所希望的是能够通过环信将所有人、物都连接起来,但之前却只拘泥于连接人与人的社交,在环信的版图中缺少着连接人与商业、人和客户的版块。因此,我们决定开发移动客服系统,让用户和商家可以直接在应用中聊起来,打造出一个完整的IM生态蓝图。

CSDN:在环信的产品线中,移动客服平台有着什么样的定位?

刘俊彦:移动客服平台是一个在IM基础上的行业应用,在IM已经覆盖几亿用户之后,我们就在思考下一步做什么?如果一款产品或某项功能能够真真切切地帮助到我们的IM用户,体验更爽,更有粘性,我们都会进行尝试。其实我们做了很多类似的工作,比如最近上线的关键字检测功能,就是为用户提供IM之上的最后一公里的额外的服务。移动客服同样如此,移动客服的核心还是IM,但我们同时还提供全套的完整的客服工作后台,有客户服务支持需求的用户不需要任何开发就可以直接使用,因此,我们将移动客服定位为IM在客户服务行业的垂直应用。

CSDN:云客服模式其实早有应用,相比其他服务提供商,环信移动客服平台有着哪些特色及技术优势?

刘俊彦:当下的客服软件市场分为两部分,一是传统电话呼叫中心的客服,他们的沟通方式以语音沟通为主,第二类是非语音类的客服,一般归纳为新媒体客服。新媒体客服包含微信公众号、微博、网页、App等渠道来源。对网页端的客服渠道来说,其对客服服务器的并发技术要求并不高,因为通常是使用基于轮询的短连接技术。比如每天有十万人找客服咨询聊天,每人聊五分钟,那么平均到每秒钟也就最多2-3个人同时在聊天,服务器只需要支持每秒钟2到3个请求的并发,对服务器压力很小。但手机App客服就不一样了。从技术上来讲,好用的手机App客服技术要求手机与客服服务器之间保持着7x24的长连接。任何时候,只要用户不卸载你的App,客服就永远可以主动的去找到消费者,向他主动发送消息。举个例子,我们有的用户用这个技术做外呼营销。他先在自己的CRM系统里对他的用户挖掘打上标签,比如找到所有的2-4岁小孩的妈妈用户群体。然后向这类妈妈群体群发消息。发出去的促销消息在消费者的App端看来是一条推送过来的聊天消息,首先这个消息不会被错过。然后点击这个推送后就会进入到客服的一对一聊天页面。这样的促销消息发送方式因为是和真人客服之间一对一的双向交互,所以效果比那种单向的广告推送好很多,转化率非常高。类似这样的外呼营销方式,让客服部门从以前的成本中心变成了现在的营收中心。而这些营销方式,如果没有手机APP和客服服务器之间的IM长连接,是不可能做到的。

当然,IM长连接技术对服务器的技术能力以及成本压力也增大许多,因为哪怕一个用户从来没找过客服聊天,我们也要为这个用户在他的手机和服务器端之间维护一个长连接,这个长连接会7X24小时的运行着。通常有100万的月活,就意味着要维护100万的长连接。但这却是环信的优势所在。环信移动客服平台与其他客服提供商最大的区别就是在移动端的IM长连接技术。在这点上,环信基本是垄断地位。

CSDN:可否详解环信移动客服平台的智能应答系统在面对海量请求时,如何做到真正智能地屏蔽与提炼?

刘俊彦:全球有100亿设备24小时连在网上,他们随时随地都能通过移动设备内置的客服通道找到客服,所以移动端的客服要应对的请求可能是海量的。对客服部门来说,利用原本的人工客服团队再加上新型的智能机器人客服系统,可以让问题解决效率呈指数性增长。传统的聊天机器人技术是基于搜索的问答匹配,而环信的智能客服是最新的基于深度机器学习的技术,不仅可以根据上下文进行推理,还能对人工座席和客户的交流进行实时学习和训练,极大降低知识库的维护成本。

目前,智能聊天机器人技术最实际的应用场景是基于文字交互的客服系统,包括短信、微信公众号、App内置客服、网页在线客服等,不仅降低了原本一年四季24小时在线的客服中心成本,更让拥有极致用户体验的新一代客服中心成为可能。

但是,相比之下,人工服务永远是最智能、最好的服务,在产品设计上,应实现人工与智能服务的无缝切换,当智能客服回答比较勉为其难的时候,就直接切换到人工服务,这样才能为客户提供更好的体验。所以客服系统中的聊天机器人技术最重要的是做好人工座席和机器人座席之间的无缝高效的切换,而不用刻意追求智能机器人技术的智能程度。客服系统中的智能聊天机器人只需解决特定领域的知识问题,无需像微软小冰那样陪用户聊人生聊理想。

CSDN:在移动客服平台开发的过程中,遇到过哪些难点与挑战?如何解决的?

刘俊彦:对移动客服来说,有两个技术难点。首当其冲便是在手机上为客户提供服务,IM技术是最适合用来在手机上连接客户和商家的。IM长连接技术能保障客服随时随地主动联系到客户、断网或复杂网络切换时不丢客户,并对电量流量进行优化。同时,也必须让客服人员、商家使用起来非常爽,即客服工作台好不好用、能不能提高客服效率、是否能进行全方位的KPI考核等。

对客服而言,即时通讯可谓是重中之重,在纯社交领域,消息丢失或晚到可能不是太大问题,但客服不一样,如果一条消息丢失或延迟,可能就意味着会发生丢单、客户流失情况,商业损失会非常大。所以对于选购移动客服的商家来说,他们希望移动端的IM技术和支撑客服工作人员的客服后台技术能够由一个厂商来统一提供。而不是说需要客服后台用这家,即时通讯买那家,这样在使用移动客服产品过程中遇到任何问题,都可以通过一个厂商一次性地及时解决。

CSDN:在移动网络环境下,弱网络、丢消息、丢订单等问题天然存在,环信采取了哪些技术手段来解决这一难题?通过哪些机制确保做到真正的不丢消息、不丢客户订单,还能省电省流量?

刘俊彦:这是环信过去一年多一直在做的事情,其实大多数IM厂商也能保证做到,但这的确还存在一些技术难点。首先,如何保证不丢消息?就必须通过一个好的协议来实现,必须保证协议本身是完全可靠,一定不会丢消息的,而在电量、流量的节约方面则包含协议、实现等诸多层面的优化。当然,无论是电量、流量的节约还是保证消息及时到达,除了最根本的协议、架构等,还包括许多细节方面的长时间打磨,才能不断地进步。
举个例子,环信在去年针对用户需求进行了许多优化,其中有一点便是针对来自三四线城市使用2G网络的用户,在弱网络环境下发送图片速度非常慢的问题,进行了切片上传的优化,将一个50K大小的图片切成10片,开10个线程,同时上传,极大地提高了传送的成功率。

CSDN:将UI模板开源让开发者100%自定制是环信一直以来的做法,之前也上线了“更极客 更开源”的IM Geek开发者社区,并将SDK开源,请问环信在开源方面有着哪些具体的计划和措施?

刘俊彦:环信的创始成员都是做开源出身,现在有些人对开源软件存在误解,而我们从不认为开源软件就意味着不好、不安全、低质量,这点从Linux就可以显而易见。我曾在Redhat担任高级开发工程师的工作,现在,许多公司都在使用Linux,也没有人会给予Linux不安全、不好用等差评。我们所希望的,不是自己重新去发明轮子,而是站在前人的肩膀上,取其精华去其糟粕,来进行自己的开发,比如最初在设计环信的通讯协议时,我们就借鉴了一部分XMPP的核心模块精华。

但XMPP协议并非为移动端设计,XMPP出现时还没有移动设备。在PC时代,用户不需要考虑电量、流量等问题,并且也不存在弱网络导致消息丢失的问题。这也就表明,我们必须将其中不好的部分推倒,进行重新设计或重写,开发出适用于移动端的IM协议。当然,XMPP也拥有很多优点,它存在十年,有许多插件,并充分考虑到协议的扩展,它是经过许多人不断摸索制定出来的协议,拥有着非常高的价值。

在使用开源软件的同时,我们也会反哺回馈开源社区,环信公司内的技术团队现在至少有十多个人都是一些知名的开源软件的committer,一直都在为开源软件贡献力量。现在有些公司可能会担心用开源软件出了问题后不可控制,这说明他们并没有用真正开源人的精神去使用开源软件,对于存在瑕疵的地方,就应该去改写代码,让它变得更好,而不是直接弃之如敝履。在开发过程中,如果使用到存在问题的开源软件,我们要做的事情就是去进行修改完善,然后将代码提交回去,让整个开源社区都能收益,这是环信对每个工程师的要求。

无论是将UI模板100%开源还是上线IM Geek开发者社区,我们的真正目的就是为开源社区做贡献,而不只是环信的产品。其实在当下的国内外开源社区方面,IM和移动社交还是空白的存在。现在,很多人都在做朋友圈、附近的人、聊天、匿名聊天或群组等功能,但归纳起来大概只有二三十种模块,剩下的工作便是各种模块的组合及编组。所以我们的想法就是开发者不用自己再去劳心劳力地重新开发一些基础和常见模块,而是通过社区的力量将这些模块都开发并开源出来,甚至包括基于这些模块的完整的应用,统统开源。这样不仅能节省创业团队大量的时间精力,也能降低开发成本,将资金投入到更好的用户体验、设计及运营上。

要经营好开源社区就必须以身作则,环信自身也在不断地贡献开源模块。当然,开源社区光靠一时的热情是远远不够的,未来,环信会为乐于开源的committer提供经济上的资助,只要开源软件做得好,并将其回馈给社区,提供开放下载。我们非常欢迎有开源情怀的开发者投身到开源事业中。

CSDN:环信移动客服在安全及保护用户隐私数据等方面有着哪些具体措施?

刘俊彦:隐私一直是很多公司一直在意的问题,会担心商业数据、用户信息会不会被窃取?环信移动客服对这方面是非常注意的,不会以任何形式碰触用户的聊天记录,用户可以100%随时导出或删除。而在系统保障方面,环信到目前已经趟过了许多雷点,并且内部还有一个每月演习的硬性规定,以此来保障即使发生系统挂掉的情况,核心功能依然可用。此外,环信正在着手“异地多活”,以此来提供更可靠、安全的服务。

CSDN:移动客服系统如何收费?

刘俊彦:IM已成红海,而移动客服则是商业化的企业级服务,需要为企业出现丢单等情况负责。环信移动客服系统的收费标准分为免费和收费用户数量级,2个座席以内可免费使用,超过2个座席的公司,需按每年每座席1500元进行收费。

2.jpg

图:环信移动客服收费标准

CSDN:现在大部分客服请求均来自于移动端,环信对于未来的移动客户服务还有着哪些畅想?

刘俊彦:当下,客户服务软件行业正在经历一场变革,用户获得服务的渠道和行为在发生巨变。随着环信移动客服这样的产品的普及,用户的服务体验将有极大的提升,而依托于技术进步,商家为此投入的人力成本却呈下降趋势。环信已经实现了人与人、人与商业的连接,但其生态布局依然缺少一块,就是人与物、物与物的连接。物联网正在临近,客户服务更将呈现完全不同的场景。我们需要做什么?首先就是物与物之间实现通讯功能的实时数据交换,其次,人如何控制设备?第三,在物与物之上,人和人之间需要沟通。

比如,一个物联网冰箱发生故障后,用户肯定不会再打400电话了。用户只需直接点击冰箱内嵌的客服按钮,即可一键接通,不仅可以和客服视频聊天得到帮助,还可以将冰箱的相关参数发送给客服,快速解决问题。同时,未来的客服一定是内嵌型的,将无处不在,无论是App、智能家居还是车联网,一个按钮所有问题都能搞定。目前,环信已经在着手物联网IM产品研发。
0
评论

App崩溃分析:如何监控http请求并做出优化? 移动开发

oscar1212 发表了文章 • 2193 次浏览 • 2015-07-14 16:09 • 来自相关话题

移动互联网时代,移动App与服务器之间的交互越来越频繁,数据量也越来越大,伴随而来的各种网络连接问题也在影响着各App的留存率。如何保证http请求的质量成为开发者们需要解决的一大问题。本文着重讲述http请求遇到的问题以及该如何监控和优化。

http请求遇到的问题

在App开发过程中,通常是用无线网络去做测试,这样网络的连通率、速度以及响应时间都是处在一个相对理想的情况下,但是在App发布后,用户使用场景往往是2G、3G,以及一些网络水平初级的地区,网速和连通率都在一个不稳定甚至极低的水平,这时,一系列的问题随之而来,其中我们主要讨论两点:
响应时间:由于网络速度的下降, 响应时间开始变长,同一个url的访问时间可能会成倍增长,增加用户的等待时间;错误率:由于网络质量的下降,丢包错包概率成倍增长,由于请求的错误也会导致服务器端处理错误率的提高,可能会造成返回数据为空或者错误,致使用户增加使用成本。

如何去优化?

应用向服务器发送http请求,一般都是调用的系统接口或者第三方接口(比如OKHttp):    




这个时候,我们可以在应用调用接口时,加一个收集模块来采集http信息,如图:





Collection module可以用不同的实现方式:iOS利用Runtime通过代码注入的方式去获取相关信息;Android通过自定义URLStreamHandler去获取http信息,之后通过一些统计工具可以直观地去分析和优化应用的网络模块。

如何利用网络监控去做优化?

那么,究竟该如何利用好网络监控来进行应用优化?开发者可以从http响应时间、http错误率、请求量(rpm)和Data I/O四个维度监控http请求,并监测每个url的运营商、终端设备、错误码。同时,地理定位功能可以提供每个地区网络状况的平均值,方便开发者去分析和优化。
http响应时间

通过响应时间的长短,可以判断哪个url去优化,如果响应时间长,是不是后台查询过慢?还是因为运营商基站建的少网络信号差?
http错误率

通过错误率,可以知道访问某个url时最多的错误码是多少,根据错误码去确定是请求错误还是服务器错误,从而缩小问题的查找范围。
请求量(rpm)

通过查看url的请求量,可以去推断用户的喜好,从而做一些定制化的服务,也可以通过这个指标去确定App端发请求频率是否正常。
Data I/O

通过Data I/O,可以知道某个url的请求数据大小是否正常,是否流量过大可以进行压缩从而节省用户的费用。





当然,每个指标不是独立的,而是应该综合来判断。举一个例子,做一个在线图库的应用,用户反映一直刷不出图,那就可以这样推断一下:看http响应时间,如果正常,有可能是App收到数据后显示有问题,如果过长,那么可能是服务器端问题;再看错误率,如果很高,那么有可能是服务器返回结果有问题,如果不高,那么有可能是因为网络信号差导致的。

这个时候,再看一下请求量和Data I/O,如果请求量很小,但是Data I/O很高,那么是否可以优化http请求策略?如果改成每次请求一屏的数据,根据用户的翻页情况发送多次请求,而不是一次去请求几页数据,那么这样数据总量没变,但是用户看到的效果却是每翻一页,只要很少的时间就可以显示出图片,这样就可以提升用户体验。

简单论述了网络问题对于移动App产生的影响,以及如何去监控http请求并做出优化。当然,实现监控的方式有很多,也可以有很多技术上的玩法,但无论技术实现得有多好,如何优化App?提升用户体验和留存率,才是开发者最该关心的问题。
  查看全部
移动互联网时代,移动App与服务器之间的交互越来越频繁,数据量也越来越大,伴随而来的各种网络连接问题也在影响着各App的留存率。如何保证http请求的质量成为开发者们需要解决的一大问题。本文着重讲述http请求遇到的问题以及该如何监控和优化。

http请求遇到的问题

在App开发过程中,通常是用无线网络去做测试,这样网络的连通率、速度以及响应时间都是处在一个相对理想的情况下,但是在App发布后,用户使用场景往往是2G、3G,以及一些网络水平初级的地区,网速和连通率都在一个不稳定甚至极低的水平,这时,一系列的问题随之而来,其中我们主要讨论两点:
  • 响应时间:由于网络速度的下降, 响应时间开始变长,同一个url的访问时间可能会成倍增长,增加用户的等待时间;
  • 错误率:由于网络质量的下降,丢包错包概率成倍增长,由于请求的错误也会导致服务器端处理错误率的提高,可能会造成返回数据为空或者错误,致使用户增加使用成本。


如何去优化?

应用向服务器发送http请求,一般都是调用的系统接口或者第三方接口(比如OKHttp):    
1.jpg

这个时候,我们可以在应用调用接口时,加一个收集模块来采集http信息,如图:

2.jpg

Collection module可以用不同的实现方式:iOS利用Runtime通过代码注入的方式去获取相关信息;Android通过自定义URLStreamHandler去获取http信息,之后通过一些统计工具可以直观地去分析和优化应用的网络模块。

如何利用网络监控去做优化?

那么,究竟该如何利用好网络监控来进行应用优化?开发者可以从http响应时间、http错误率、请求量(rpm)和Data I/O四个维度监控http请求,并监测每个url的运营商、终端设备、错误码。同时,地理定位功能可以提供每个地区网络状况的平均值,方便开发者去分析和优化。
  • http响应时间


通过响应时间的长短,可以判断哪个url去优化,如果响应时间长,是不是后台查询过慢?还是因为运营商基站建的少网络信号差?
  • http错误率


通过错误率,可以知道访问某个url时最多的错误码是多少,根据错误码去确定是请求错误还是服务器错误,从而缩小问题的查找范围。
  • 请求量(rpm)


通过查看url的请求量,可以去推断用户的喜好,从而做一些定制化的服务,也可以通过这个指标去确定App端发请求频率是否正常。
  • Data I/O


通过Data I/O,可以知道某个url的请求数据大小是否正常,是否流量过大可以进行压缩从而节省用户的费用。

3.jpg

当然,每个指标不是独立的,而是应该综合来判断。举一个例子,做一个在线图库的应用,用户反映一直刷不出图,那就可以这样推断一下:看http响应时间,如果正常,有可能是App收到数据后显示有问题,如果过长,那么可能是服务器端问题;再看错误率,如果很高,那么有可能是服务器返回结果有问题,如果不高,那么有可能是因为网络信号差导致的。

这个时候,再看一下请求量和Data I/O,如果请求量很小,但是Data I/O很高,那么是否可以优化http请求策略?如果改成每次请求一屏的数据,根据用户的翻页情况发送多次请求,而不是一次去请求几页数据,那么这样数据总量没变,但是用户看到的效果却是每翻一页,只要很少的时间就可以显示出图片,这样就可以提升用户体验。

简单论述了网络问题对于移动App产生的影响,以及如何去监控http请求并做出优化。当然,实现监控的方式有很多,也可以有很多技术上的玩法,但无论技术实现得有多好,如何优化App?提升用户体验和留存率,才是开发者最该关心的问题。
 
0
评论

一个社交App是如何构建高伸缩性的交互式系统 移动开发

oscar1212 发表了文章 • 3122 次浏览 • 2015-07-13 12:15 • 来自相关话题

一个社交App需实现的功能

用户关注的常规社交功能、活动、地理位置、探索功能、新鲜事、视频照片分享等等,需要提供的功能不胜枚举,所以从技术角度来说,开发者需要解决的问题也是异常复杂的。

当一款社交App发布之初,用户访问量比较小,使用一台服务器就能够支撑全部的访问压力和数据存储需求,但是互联网应用具有病毒式的传播特点。一款App很可能会面临一夜爆红的现象,访问量和数据量在短时间内呈现爆发式增长,这时候会面临的局面是每天上亿PV、数百万新增用户和活跃用户、流量飙升至每秒数百兆。这些对于一个只部署了简单后端架构的应用来讲是无法支撑的,会直接导致服务器响应缓慢甚至超时,以及在高峰期时服务呈现瘫痪状态,使得后端的服务完全无法使用,用户体验急剧下降。本文将会通过一个真实的案例来分享一个社交应用如何构建一个具备高伸缩性的后端系统。

社交App最初部署的后端架构解析

社交App在最初的时候,后端架构相对比较简单,最初是部署在基础网络之上。最前面放置一台绑定了公网IP的nginx服务器作负载均衡,后面放置3台应用服务器来负责处理所有业务上的请求,最后面搭建一台MySQL Database数据库。





 
构建私有网络

随着产品的不断迭代、用户数的持续增长、数据量的积累,App就需要改进自己的后端架构,即开始构建私有网络。用户可以使用私有网络构建自己的网络拓扑——创建路由器和私有网络,将后续加入的用于运行内部服务的主机放置在私用网络中,可以有效地和云平台其他用户主机,在网络上实现100%二层隔离。主机对外开放的仅仅只有80端口,这样系统安全性上多了一层保障。






在上面的架构图中,最前面的是防火墙,后面接负载均衡器,然后接路由器和私有网络,很多互联网应用都存在读多写少的情况,这个比例有时可以达到8:2,所以我们首先通过引入缓存分摊数据库读压力。其次,引入负载均衡器,替换最初架构中的nginx proxy,负责均衡器在这里其主要用于分发请求到后端多台应用服务器,,当其中一台应用服务器挂掉,负载均衡器可以进行自动隔离。

业务分区与扩展

App随着并发访问量和数据量不断增大,首先想到横向扩容Web服务。水平扩容业务服务器的前提是要保证每台服务器都是无状态的,将session信息下放到缓存或数据库中存储,保证请求被负载到任何一台服务器可以正常处理。






从上图中看到,在前一步「构建私有网络」之后,增加了一个新的私有网络来扩展网络层,这里可以利用自有映像功能,将原有的应用服务器制作成模板,后续就可以基于这个模板快速启动新的主机。另外可以利用Auto-scaling(自动横向扩展)功能,根据后端服务器的负载请求,动态调整服务器的数量。

一个社交应用的后端会提供很多服务请求接口,比如添加好友、刷新新鲜事、浏览页面等,可以通过日志分析每一个接口的耗时,将耗时长但非重要业务的请求分到单独的Web服务器上进行处理,从而给主Web服务器留出更多资源去处理关键业务的请求。

面向服务的架构

随着产品功能的不断迭代,业务代码会越来越复杂,出现故障的可能性也在加大,当一个局部功能出现问题时,都会影响整个服务的可用性。此时可以构建面向服务的架构,将一个完整且庞大的服务拆分为一个个的子服务,服务之间通过接口交互。如下图所示:






社交App的服务被拆分成了四个子服务——新鲜事(News Feed)、用户资料(Profile)、广告(Ads)和探索(Explore),不同的服务之间通过消息通信框架(例如ZeroMQ)来进行交互。把一个大服务拆分为几个小的子服务的好处不言而喻,主要是:
故障隔离:子服务出现故障不会影响全局,比如广告业务出现问题并不会让整个App不能使用,依然可以查看新鲜事等;独立扩展:每一个被拆分出的子服务有着不同的访问压力,比如新鲜事的调用相比一些二级页面的用户资料要高很多,所以前者会被分配更多的Web 服务器;独立部署:一个大服务的配置因功能过多会异常复杂,一旦被拆分就可根据不同的特性需求定制配置项,从而提高可管理性;团队协作开发:开发者都有着自己精通的方向,从而提高开发效率;抽象出数据访问:在后续进行数据层面(数据库、缓存)扩展时,可通过修改子服务的Data Service,实现对下层数据的透明。

数据库Replication

业务增长也会给数据库带来诸多问题,当最初架构中单台数据库(数据库同时提供读和写)不足已支撑起App访问压力时,首先需要做数据副本Replication。市面上常见的MySQL、MongoDB等数据库都提供Replication功能,以MySQL为例,从高层来看,Replication可分成三步:
Master将改变记录到二进制日志(binary log)中(这些记录叫做二进制日志事件,binary log events);Slave将Master的binary log events拷贝到它的中继日志(relay log);Slave重做中继日志中的事件,将改变反映它自己的数据。

具体实现该过程的第一部分就是Master记录二进制日志。在每个事务更新数据完成之前,Master在二进制日志记录这些改变。MySQL将事务串行的写入二进制日志,即使事务中的语句都是交叉执行的。在事件写入二进制日志完成后,Master通知存储引擎提交事务。

下一步就是Slave将Master的binary log拷贝到它自己的中继日志。首先,Slave开始一个工作线程——I/O线程。I/O线程在Master上打开一个普通的连接,然后开始binlog dump process。Binlog dump process从Master的二进制日志中读取事件,如果已经跟上Master,它会睡眠并等待Master产生新的事件。I/O线程将这些事件写入中继日志。

SQL slave thread处理该过程的最后一步。SQL线程从中继日志读取事件,更新Slave的数据,使其与Master中的数据一致。只要该线程与I/O线程保持一致,中继日志通常会位于OS的缓存中,所以中继日志的开销很小。

此外,在Master中也有一个工作线程:和其它MySQL的连接一样,Slave在Master中打开一个连接也会使得Master开始一个线程。复制过程有一个很重要的限制——复制在Slave上是串行化的,也就是说Master上的并行更新操作不能在Slave上并行操作。

对于云计算使用者来说,只需要知道数据库的IP和端口即可进行使用。具体实现见下图:





第一步要做的是扩充Slave,将单机Master变成Master+3台Slave的架构,而在其中的Slave上搭建一个内网的负载均衡器(Load Balancer),对于最上层的Data Service来说,只要配置一个MySQL Master节点和一个LB节点即可,今后因业务变化进行增减Slave对上层来说完全是透明的。

此做法可以带来两个好处,第一是提高可用性,若是一台Master出现错误,则可以提升某一台的Slave作为Master继续提供服务,从而保证数据可用性;第二个是分摊读压力,对于一个社交App来说,读写分离是在数据层优化第一步要做的事情,利用上面的架构可以很轻易地做到将读的请求分担到MySQL Slave上进行查询,而写留给Master。但是读写分离时会有数据库一致性的问题,即在数据写至Master之后同步到Slave有一个延迟的时间,对于社交应用来说,这是可以接受的,只要保证数据的最终一致性即可。

在上图的最下面有一个Snapshot,即定期对数据进行冷备份,这不同于单纯对MySQL Master进行复制的Slave,因为线上bug或误操作会删除Master上的数据,这时会立即同步到slave上造成数据丢失这时冷备份Snapshot就会起到数据保护作用。

运行过程中肯定需要监控,用户可以利用Linux上的工具进行统计分析top / iotop / df / free / netstat等工具去监控系统里的各个服务和组件是否正常运行,以及通过日志的信息(http access log / application log / database slow log )分析各个服务的性能瓶颈。

数据分区与扩容

下一步业务的调整要进行数据库的分区和扩容。第一,构建缓存集群,在开始的架构中引用了Memcached缓存,是单机数据库缓存。当数据量增长,,需要把数据分散到多台缓存服务器上,常用的是HashRing算法,好处在于不管是添加结点还是删除结点时,只会使得少部分数据失效。还可以引用NoSQL数据库,这里用到了Redis把社交数据里对于关系要求不强但对查询效率要求很高的数据从MySQL里拿到Redis里存。Redis尤其适合存储列表类数据,比如好友关系列表、排行榜数据等。





除此以外可以考虑做数据分区对于MySQL第一步是垂直拆分,把原来单独的数据库按照功能模块分别拆分成:好友新鲜事、用户资料、广告数据以及探索数据。对于Redis也同样,将原来的单台Redis按照功能模块拆成四个,分别为:排行榜数据、好友、广告数据、探索数据。

接下来会遇到的瓶颈是单表过大的问题,这时候我们需要做水平拆分——把一个表拆分成多个表,需要选取一个分区Key,比如对用户表做拆分时,通常选取User ID。分区key的选择主要是看所有的查询语句频繁使用哪个查询字段,就选择那个字段作为分区key这样能保证大部分的查询可以落在单个数据表上,少量没有带分区Key的查询语句,可能要遍历一遍所有切分后的数据表。

构建完整的测试环境

构建完整测试服务器时需要创建新的路由器和私有网络、独立的网络环境和带宽资源、内网GRE隧道打通路由器、VPN拨入网络和SSH密钥管理。





这个过程你可以创建一个包含所有系统服务的all-in-one的环境,将其制作成自有映像。如果后续你的团队来新的人,需要独立的完整开发环境,只需基于自有镜像快速创建主机即可;还可以利用User Data定制化功能,在主机启动执行一段你上传的脚本,来初始化环境。你可以将这两个功能结合起来用,把所有你所需要用的服务全部安装部署完毕后做成映像,并用User Data脚本从代码库里更新代码。因为代码的变动相对于环境的更新更加频繁,不可能每次代码的更新都要构建一个新的自有镜像。通过这种方式构建起一个完整的测试服务器,让每个工程师都可以有自己独立的测试服务器。

在App发布上线时需要连到线上环境怎么办?这两个网络本身完全100%隔离,可利用GRE隧道的功能,把两个路由器打通,实现测试环境网络和线上生产环境网络的完全连通。

多机房部署与混合组网

为了让后端架构更可靠和业务更稳定,就需要实施多机房部署和混合组网。具体原因有以下三点:
异地容灾:在复杂的网络环境下,机房可能会出现网络状况,导致一些比较关键性的业务的可用性降低,备份机房后可保证服务不会出现明显的长时间中断;负载分摊:单独一个机房可能不足以支撑全部的请求,这时可以把一部分的请求压力分担到另一个机房;加速区域访问:在国内网络环境下,南方和北方相互之间网络访问时有较高的延迟。通过做多机房部署实现加速区域用户的访问。






如上所示,有三个机房,中间是QingCloud北京1区机房,负责主营业务。左边是亚太1区机房,主要服务亚太和海外的客户。这两个机房都使用了QingCloud私有网络部署,利用路由器,通过GRE隧道或者IPsec加密隧道的方式进行互通。如果对数据传输过程的安全性要求较高,可以用IPsec的方式把两个机房相互打通,这时的访问只能通过内网IP进行访问。右边是办公室机房,工程师在这个环境下进行开发。

在实现混合组网时,只要机房路由器或者网宽设备支持标准的GRE隧道协议、IP隧道协议,就可以将传统物理世界的机房与路由器连通,并最终打通公有云环境。多机房部署通常见的方案有这些:
异地冷备份

把主机房全套业务在异地重新构建一遍,且不需要提供线上服务,只有在主机房出现故障的时候才切换到备用机房,部署相对要简单一些。但有两方面缺点,一是成本比较高,需要双倍的费用且只是用来做冷备份,平时完全用不上;另外,当主机房突然挂掉时,备用机房再起动起来提供服务,数据需要预热,这是非常缓慢的过程,可能会出现服务响应慢,甚至不能正常提供服务。
异地多活

从易到难有三阶段:第一,反向代理,用户请求到第二个机房,但不做任何处理被转向第一个机房这样会对两地的延时有一定的要求。第二,在第二个机房部署应用服务器和缓存,大部分的数据请求可以从缓存中读取,不用进行跨机房请求,但当缓存失效时,依然落到第一个机房的数据库去查询。所以,这个方式不太彻底;第三,全套服务的部署,包括HTTP服务器、业务服务器、缓存和数据库的 slave。此方式使得进入第二个机房的请求,只需要在机房内就可以完成请求处理,速度更快,但会遇到数据一致性和缓存一致性的问题,针对这点也会有一些解决方法。除了数据同步过程中的不一致问题,还需要面对缓存。

好的系统架构不是设计出来的,而是进化而来的

构建稳定可靠的业务系统需要注意以下这些:
分析用户行为,理解你的业务,如社交、电商、视频;

不同的业务有不同的行业属性和特点,对于社交来讲,比较典型的特点是数据量庞大、数据查询维度多,比如查询6月11日-7月15日在xx咖啡厅我所有好友里拍过照片的人,查询条件包括好友维度、照片维度、地点维度、隐私状态维度等,这时就需要合理的做数据层面的扩展。
电商的特点是定期举办大促销活动,届时会需要大量的计算资源、应用服务器来扛流量峰值,此时可利用云计算平台的弹性实现快速扩展业务,而在自己业务压力、促销来临时调用API接口,及AutoScaling扩展后端计算资源。视频业务有非常明显的流量高峰期和低峰期,流量高峰期通常是白天或者大家晚上下班回家那段时间,晚上2点到早上6点是流量非常低的时候,可利用云计算弹性优势,来调用API方式调整业务带宽资源,从而达到节省成本目的。合理规划系统,预估系统容量,如 10w / 100w / 1000w PV(DAU):不同的系统容量有可能对应不同架构的部署方式,找到最适合自己的那一个;系统是可横向扩展的 scalable;不遗余力地解决单点问题;为出错而设计design for failure:App的后端架构在开发支出就要为可能出现的各种问题进行准备,比如异地备份等;设计面向服务的架构,拆分子系统,API交互,异步处理;构建无处不在的缓存:页面缓存、接口缓存、对象缓存、数据库缓存;避免过度设计,好的系统架构不是设计出来的,而是进化而来的。
 来源:csdn 查看全部
一个社交App需实现的功能

用户关注的常规社交功能、活动、地理位置、探索功能、新鲜事、视频照片分享等等,需要提供的功能不胜枚举,所以从技术角度来说,开发者需要解决的问题也是异常复杂的。

当一款社交App发布之初,用户访问量比较小,使用一台服务器就能够支撑全部的访问压力和数据存储需求,但是互联网应用具有病毒式的传播特点。一款App很可能会面临一夜爆红的现象,访问量和数据量在短时间内呈现爆发式增长,这时候会面临的局面是每天上亿PV、数百万新增用户和活跃用户、流量飙升至每秒数百兆。这些对于一个只部署了简单后端架构的应用来讲是无法支撑的,会直接导致服务器响应缓慢甚至超时,以及在高峰期时服务呈现瘫痪状态,使得后端的服务完全无法使用,用户体验急剧下降。本文将会通过一个真实的案例来分享一个社交应用如何构建一个具备高伸缩性的后端系统。

社交App最初部署的后端架构解析

社交App在最初的时候,后端架构相对比较简单,最初是部署在基础网络之上。最前面放置一台绑定了公网IP的nginx服务器作负载均衡,后面放置3台应用服务器来负责处理所有业务上的请求,最后面搭建一台MySQL Database数据库。

1.jpg

 
构建私有网络

随着产品的不断迭代、用户数的持续增长、数据量的积累,App就需要改进自己的后端架构,即开始构建私有网络。用户可以使用私有网络构建自己的网络拓扑——创建路由器和私有网络,将后续加入的用于运行内部服务的主机放置在私用网络中,可以有效地和云平台其他用户主机,在网络上实现100%二层隔离。主机对外开放的仅仅只有80端口,这样系统安全性上多了一层保障。

2.jpg


在上面的架构图中,最前面的是防火墙,后面接负载均衡器,然后接路由器和私有网络,很多互联网应用都存在读多写少的情况,这个比例有时可以达到8:2,所以我们首先通过引入缓存分摊数据库读压力。其次,引入负载均衡器,替换最初架构中的nginx proxy,负责均衡器在这里其主要用于分发请求到后端多台应用服务器,,当其中一台应用服务器挂掉,负载均衡器可以进行自动隔离。

业务分区与扩展

App随着并发访问量和数据量不断增大,首先想到横向扩容Web服务。水平扩容业务服务器的前提是要保证每台服务器都是无状态的,将session信息下放到缓存或数据库中存储,保证请求被负载到任何一台服务器可以正常处理。

3.jpg


从上图中看到,在前一步「构建私有网络」之后,增加了一个新的私有网络来扩展网络层,这里可以利用自有映像功能,将原有的应用服务器制作成模板,后续就可以基于这个模板快速启动新的主机。另外可以利用Auto-scaling(自动横向扩展)功能,根据后端服务器的负载请求,动态调整服务器的数量。

一个社交应用的后端会提供很多服务请求接口,比如添加好友、刷新新鲜事、浏览页面等,可以通过日志分析每一个接口的耗时,将耗时长但非重要业务的请求分到单独的Web服务器上进行处理,从而给主Web服务器留出更多资源去处理关键业务的请求。

面向服务的架构

随着产品功能的不断迭代,业务代码会越来越复杂,出现故障的可能性也在加大,当一个局部功能出现问题时,都会影响整个服务的可用性。此时可以构建面向服务的架构,将一个完整且庞大的服务拆分为一个个的子服务,服务之间通过接口交互。如下图所示:

4.jpg


社交App的服务被拆分成了四个子服务——新鲜事(News Feed)、用户资料(Profile)、广告(Ads)和探索(Explore),不同的服务之间通过消息通信框架(例如ZeroMQ)来进行交互。把一个大服务拆分为几个小的子服务的好处不言而喻,主要是:
  • 故障隔离:子服务出现故障不会影响全局,比如广告业务出现问题并不会让整个App不能使用,依然可以查看新鲜事等;
  • 独立扩展:每一个被拆分出的子服务有着不同的访问压力,比如新鲜事的调用相比一些二级页面的用户资料要高很多,所以前者会被分配更多的Web 服务器;
  • 独立部署:一个大服务的配置因功能过多会异常复杂,一旦被拆分就可根据不同的特性需求定制配置项,从而提高可管理性;
  • 团队协作开发:开发者都有着自己精通的方向,从而提高开发效率;
  • 抽象出数据访问:在后续进行数据层面(数据库、缓存)扩展时,可通过修改子服务的Data Service,实现对下层数据的透明。


数据库Replication

业务增长也会给数据库带来诸多问题,当最初架构中单台数据库(数据库同时提供读和写)不足已支撑起App访问压力时,首先需要做数据副本Replication。市面上常见的MySQL、MongoDB等数据库都提供Replication功能,以MySQL为例,从高层来看,Replication可分成三步:
  • Master将改变记录到二进制日志(binary log)中(这些记录叫做二进制日志事件,binary log events);
  • Slave将Master的binary log events拷贝到它的中继日志(relay log);
  • Slave重做中继日志中的事件,将改变反映它自己的数据。


具体实现该过程的第一部分就是Master记录二进制日志。在每个事务更新数据完成之前,Master在二进制日志记录这些改变。MySQL将事务串行的写入二进制日志,即使事务中的语句都是交叉执行的。在事件写入二进制日志完成后,Master通知存储引擎提交事务。

下一步就是Slave将Master的binary log拷贝到它自己的中继日志。首先,Slave开始一个工作线程——I/O线程。I/O线程在Master上打开一个普通的连接,然后开始binlog dump process。Binlog dump process从Master的二进制日志中读取事件,如果已经跟上Master,它会睡眠并等待Master产生新的事件。I/O线程将这些事件写入中继日志。

SQL slave thread处理该过程的最后一步。SQL线程从中继日志读取事件,更新Slave的数据,使其与Master中的数据一致。只要该线程与I/O线程保持一致,中继日志通常会位于OS的缓存中,所以中继日志的开销很小。

此外,在Master中也有一个工作线程:和其它MySQL的连接一样,Slave在Master中打开一个连接也会使得Master开始一个线程。复制过程有一个很重要的限制——复制在Slave上是串行化的,也就是说Master上的并行更新操作不能在Slave上并行操作。

对于云计算使用者来说,只需要知道数据库的IP和端口即可进行使用。具体实现见下图:

5.jpg

第一步要做的是扩充Slave,将单机Master变成Master+3台Slave的架构,而在其中的Slave上搭建一个内网的负载均衡器(Load Balancer),对于最上层的Data Service来说,只要配置一个MySQL Master节点和一个LB节点即可,今后因业务变化进行增减Slave对上层来说完全是透明的。

此做法可以带来两个好处,第一是提高可用性,若是一台Master出现错误,则可以提升某一台的Slave作为Master继续提供服务,从而保证数据可用性;第二个是分摊读压力,对于一个社交App来说,读写分离是在数据层优化第一步要做的事情,利用上面的架构可以很轻易地做到将读的请求分担到MySQL Slave上进行查询,而写留给Master。但是读写分离时会有数据库一致性的问题,即在数据写至Master之后同步到Slave有一个延迟的时间,对于社交应用来说,这是可以接受的,只要保证数据的最终一致性即可。

在上图的最下面有一个Snapshot,即定期对数据进行冷备份,这不同于单纯对MySQL Master进行复制的Slave,因为线上bug或误操作会删除Master上的数据,这时会立即同步到slave上造成数据丢失这时冷备份Snapshot就会起到数据保护作用。

运行过程中肯定需要监控,用户可以利用Linux上的工具进行统计分析top / iotop / df / free / netstat等工具去监控系统里的各个服务和组件是否正常运行,以及通过日志的信息(http access log / application log / database slow log )分析各个服务的性能瓶颈。

数据分区与扩容

下一步业务的调整要进行数据库的分区和扩容。第一,构建缓存集群,在开始的架构中引用了Memcached缓存,是单机数据库缓存。当数据量增长,,需要把数据分散到多台缓存服务器上,常用的是HashRing算法,好处在于不管是添加结点还是删除结点时,只会使得少部分数据失效。还可以引用NoSQL数据库,这里用到了Redis把社交数据里对于关系要求不强但对查询效率要求很高的数据从MySQL里拿到Redis里存。Redis尤其适合存储列表类数据,比如好友关系列表、排行榜数据等。

6.jpg

除此以外可以考虑做数据分区对于MySQL第一步是垂直拆分,把原来单独的数据库按照功能模块分别拆分成:好友新鲜事、用户资料、广告数据以及探索数据。对于Redis也同样,将原来的单台Redis按照功能模块拆成四个,分别为:排行榜数据、好友、广告数据、探索数据。

接下来会遇到的瓶颈是单表过大的问题,这时候我们需要做水平拆分——把一个表拆分成多个表,需要选取一个分区Key,比如对用户表做拆分时,通常选取User ID。分区key的选择主要是看所有的查询语句频繁使用哪个查询字段,就选择那个字段作为分区key这样能保证大部分的查询可以落在单个数据表上,少量没有带分区Key的查询语句,可能要遍历一遍所有切分后的数据表。

构建完整的测试环境

构建完整测试服务器时需要创建新的路由器和私有网络、独立的网络环境和带宽资源、内网GRE隧道打通路由器、VPN拨入网络和SSH密钥管理。

8.jpg

这个过程你可以创建一个包含所有系统服务的all-in-one的环境,将其制作成自有映像。如果后续你的团队来新的人,需要独立的完整开发环境,只需基于自有镜像快速创建主机即可;还可以利用User Data定制化功能,在主机启动执行一段你上传的脚本,来初始化环境。你可以将这两个功能结合起来用,把所有你所需要用的服务全部安装部署完毕后做成映像,并用User Data脚本从代码库里更新代码。因为代码的变动相对于环境的更新更加频繁,不可能每次代码的更新都要构建一个新的自有镜像。通过这种方式构建起一个完整的测试服务器,让每个工程师都可以有自己独立的测试服务器。

在App发布上线时需要连到线上环境怎么办?这两个网络本身完全100%隔离,可利用GRE隧道的功能,把两个路由器打通,实现测试环境网络和线上生产环境网络的完全连通。

多机房部署与混合组网

为了让后端架构更可靠和业务更稳定,就需要实施多机房部署和混合组网。具体原因有以下三点:
  • 异地容灾:在复杂的网络环境下,机房可能会出现网络状况,导致一些比较关键性的业务的可用性降低,备份机房后可保证服务不会出现明显的长时间中断;
  • 负载分摊:单独一个机房可能不足以支撑全部的请求,这时可以把一部分的请求压力分担到另一个机房;
  • 加速区域访问:在国内网络环境下,南方和北方相互之间网络访问时有较高的延迟。通过做多机房部署实现加速区域用户的访问。


9.jpg


如上所示,有三个机房,中间是QingCloud北京1区机房,负责主营业务。左边是亚太1区机房,主要服务亚太和海外的客户。这两个机房都使用了QingCloud私有网络部署,利用路由器,通过GRE隧道或者IPsec加密隧道的方式进行互通。如果对数据传输过程的安全性要求较高,可以用IPsec的方式把两个机房相互打通,这时的访问只能通过内网IP进行访问。右边是办公室机房,工程师在这个环境下进行开发。

在实现混合组网时,只要机房路由器或者网宽设备支持标准的GRE隧道协议、IP隧道协议,就可以将传统物理世界的机房与路由器连通,并最终打通公有云环境。多机房部署通常见的方案有这些:
  • 异地冷备份


把主机房全套业务在异地重新构建一遍,且不需要提供线上服务,只有在主机房出现故障的时候才切换到备用机房,部署相对要简单一些。但有两方面缺点,一是成本比较高,需要双倍的费用且只是用来做冷备份,平时完全用不上;另外,当主机房突然挂掉时,备用机房再起动起来提供服务,数据需要预热,这是非常缓慢的过程,可能会出现服务响应慢,甚至不能正常提供服务。
  • 异地多活


从易到难有三阶段:第一,反向代理,用户请求到第二个机房,但不做任何处理被转向第一个机房这样会对两地的延时有一定的要求。第二,在第二个机房部署应用服务器和缓存,大部分的数据请求可以从缓存中读取,不用进行跨机房请求,但当缓存失效时,依然落到第一个机房的数据库去查询。所以,这个方式不太彻底;第三,全套服务的部署,包括HTTP服务器、业务服务器、缓存和数据库的 slave。此方式使得进入第二个机房的请求,只需要在机房内就可以完成请求处理,速度更快,但会遇到数据一致性和缓存一致性的问题,针对这点也会有一些解决方法。除了数据同步过程中的不一致问题,还需要面对缓存。

好的系统架构不是设计出来的,而是进化而来的

构建稳定可靠的业务系统需要注意以下这些:
  • 分析用户行为,理解你的业务,如社交、电商、视频;


不同的业务有不同的行业属性和特点,对于社交来讲,比较典型的特点是数据量庞大、数据查询维度多,比如查询6月11日-7月15日在xx咖啡厅我所有好友里拍过照片的人,查询条件包括好友维度、照片维度、地点维度、隐私状态维度等,这时就需要合理的做数据层面的扩展。
  • 电商的特点是定期举办大促销活动,届时会需要大量的计算资源、应用服务器来扛流量峰值,此时可利用云计算平台的弹性实现快速扩展业务,而在自己业务压力、促销来临时调用API接口,及AutoScaling扩展后端计算资源。视频业务有非常明显的流量高峰期和低峰期,流量高峰期通常是白天或者大家晚上下班回家那段时间,晚上2点到早上6点是流量非常低的时候,可利用云计算弹性优势,来调用API方式调整业务带宽资源,从而达到节省成本目的。
  • 合理规划系统,预估系统容量,如 10w / 100w / 1000w PV(DAU):不同的系统容量有可能对应不同架构的部署方式,找到最适合自己的那一个;
  • 系统是可横向扩展的 scalable;
  • 不遗余力地解决单点问题;
  • 为出错而设计design for failure:App的后端架构在开发支出就要为可能出现的各种问题进行准备,比如异地备份等;
  • 设计面向服务的架构,拆分子系统,API交互,异步处理;
  • 构建无处不在的缓存:页面缓存、接口缓存、对象缓存、数据库缓存;
  • 避免过度设计,好的系统架构不是设计出来的,而是进化而来的。

 来源:csdn
0
评论

Android M Developer Preview 2 发布 Android 移动开发

oscar 发表了文章 • 1188 次浏览 • 2015-07-10 14:49 • 来自相关话题

Google 更新 Android M 开发者预览版,相比 Lollipop 主要是安全和电池寿命方面的改进。此版本包括更多的授权设置改进,比如指纹验证,外部存储处理的授权方式改进。

Google 强烈建议大家升级到最新版本,最新版本包括最新的平台 APIs:更新了 Bluetooth Stylus APIs,为 Media API 添加了新的调用,一些类的重构等等。

此外还有一系列的 bug 修复。Google 温馨提示: Messenger 应用还不能很好的在 64 位模拟器上运行,还有些 YouTube 视频分享方面的问题,联系人同步方面的问题,Android M 在 Nexus Player 上的问题等等。
 
原文地址:http://www.oschina.net/news/64 ... pdate 查看全部
Google 更新 Android M 开发者预览版,相比 Lollipop 主要是安全和电池寿命方面的改进。此版本包括更多的授权设置改进,比如指纹验证,外部存储处理的授权方式改进。

Google 强烈建议大家升级到最新版本,最新版本包括最新的平台 APIs:更新了 Bluetooth Stylus APIs,为 Media API 添加了新的调用,一些类的重构等等。

此外还有一系列的 bug 修复。Google 温馨提示: Messenger 应用还不能很好的在 64 位模拟器上运行,还有些 YouTube 视频分享方面的问题,联系人同步方面的问题,Android M 在 Nexus Player 上的问题等等。
 
原文地址:http://www.oschina.net/news/64 ... pdate
0
评论

Go语言对Android原生应用开发的支持情况 Android Go 移动开发

oscar 发表了文章 • 1446 次浏览 • 2015-07-08 16:43 • 来自相关话题

Google工程师和独立开发人员提出了几份不同的提案,旨在让Go语言支持开发原生的Android应用。这项工作无法让Go语言编写的应用使用Android NDK的全部接口,但有可能使用其中的一个子集。
David Crawshaw是Google的工程师,他写了一份提案,旨在让Go语言部分支持编写Android应用。根据他的说法,“用Go语言来实现整个Android平台非常困难。Android平台是用Java写的,并拥有庞大的API层。”
但是,Crawshaw说,一部分Android应用——比如游戏——使用了精简得多的C语言API编写代码,这些API由Android NDK提供。这样,使用Go语言来开发和NDK一样的功能,提供对Android的支持是有可能实现的。
Crawshaw建议在Go 1.4的开发周期中,Go语言的代码库引入一个叫GOOS=android的选项,这个选项可以提供以下功能:
为Android NDK中导出的OpenGL、OpenSL和OpenMAX接口,提供Go语言的绑定(binding)。从Java语言到Go语言的绑定生成器(binding generator)。如果我们有一个Go语言编写的软件包,那么这个生成器可以帮助Java代码调用它,所以游戏菜单界面就可以直接使用标准的SDK来编写了。集成到Android Studio的编译系统中。
不止Crawshaw一个人提出了把Go语言和Android结合起来的想法。Elias Naur建议扩展Go语言的工具链来支持创建动态库。这样我们就可以在Android应用中使用Go语言编写的库,它们被Android应用加载和运行,并打包在apk中发行。要把这个想法变为现实,有一个重要的前提条件:加入对交叉编译的支持,而Go 1.3已经实现了它。交叉编译是必需的,因为NDK本身并不能在Android上运行,只有使用NDK编译和(或)链接的可执行程序和动态库才能在Android设备上运行。
上面这个提案基于已有的开源项目goandroid,作者就是Elias Naur。Goandroid修改了Go语言的工具链和运行时库,使之能编写动态库,在原生的Android应用中运行,而Google官方并不支持这个功能。
最后,还有一个叫Mandala的项目,它是一个更全面的框架,它的目标是使Go语言能编写Android原生应用。Mandala利用了Goandroid的工具链,它的作者Andrea Fazzi说,感谢Goandroid,“你可以在桌面环境中开发、测试和运行你的应用,然后再把它部署到Android设备上。它鼓励大家以Go语言独特的方式来编写Android应用:使用通道(channels)来实现通讯,而不是回调函数(callbacks)”
在功能方面,Mandala项目跟Crawshaw的提案很接近,它的目标也主要是为游戏提供解决方案:“我们不应该把Mandala框架看作是一个上层的游戏引擎,而是应该在它基础之上构建游戏引擎,或者把已有的游戏引擎移植到它上面。” Fazzi 提醒道,Google并不支持用Go语言来开发原生的Android应用,但他也表达了他的期望“当前这些工作可以起到某种激励作用,促使Go语言开发团队从官方层面支持Android。”
来源:infoq
参考原文链接:The State of Go Language for Android Native Development 查看全部
Google工程师和独立开发人员提出了几份不同的提案,旨在让Go语言支持开发原生的Android应用。这项工作无法让Go语言编写的应用使用Android NDK的全部接口,但有可能使用其中的一个子集。
David Crawshaw是Google的工程师,他写了一份提案,旨在让Go语言部分支持编写Android应用。根据他的说法,“用Go语言来实现整个Android平台非常困难。Android平台是用Java写的,并拥有庞大的API层。”
但是,Crawshaw说,一部分Android应用——比如游戏——使用了精简得多的C语言API编写代码,这些API由Android NDK提供。这样,使用Go语言来开发和NDK一样的功能,提供对Android的支持是有可能实现的。
Crawshaw建议在Go 1.4的开发周期中,Go语言的代码库引入一个叫GOOS=android的选项,这个选项可以提供以下功能:
  • 为Android NDK中导出的OpenGL、OpenSL和OpenMAX接口,提供Go语言的绑定(binding)。
  • 从Java语言到Go语言的绑定生成器(binding generator)。如果我们有一个Go语言编写的软件包,那么这个生成器可以帮助Java代码调用它,所以游戏菜单界面就可以直接使用标准的SDK来编写了。
  • 集成到Android Studio的编译系统中。

不止Crawshaw一个人提出了把Go语言和Android结合起来的想法。Elias Naur建议扩展Go语言的工具链来支持创建动态库。这样我们就可以在Android应用中使用Go语言编写的库,它们被Android应用加载和运行,并打包在apk中发行。要把这个想法变为现实,有一个重要的前提条件:加入对交叉编译的支持,而Go 1.3已经实现了它。交叉编译是必需的,因为NDK本身并不能在Android上运行,只有使用NDK编译和(或)链接的可执行程序和动态库才能在Android设备上运行。
上面这个提案基于已有的开源项目goandroid,作者就是Elias Naur。Goandroid修改了Go语言的工具链和运行时库,使之能编写动态库,在原生的Android应用中运行,而Google官方并不支持这个功能。
最后,还有一个叫Mandala的项目,它是一个更全面的框架,它的目标是使Go语言能编写Android原生应用。Mandala利用了Goandroid的工具链,它的作者Andrea Fazzi说,感谢Goandroid,“你可以在桌面环境中开发、测试和运行你的应用,然后再把它部署到Android设备上。它鼓励大家以Go语言独特的方式来编写Android应用:使用通道(channels)来实现通讯,而不是回调函数(callbacks)”
在功能方面,Mandala项目跟Crawshaw的提案很接近,它的目标也主要是为游戏提供解决方案:“我们不应该把Mandala框架看作是一个上层的游戏引擎,而是应该在它基础之上构建游戏引擎,或者把已有的游戏引擎移植到它上面。” Fazzi 提醒道,Google并不支持用Go语言来开发原生的Android应用,但他也表达了他的期望“当前这些工作可以起到某种激励作用,促使Go语言开发团队从官方层面支持Android。”
来源:infoq
参考原文链接:The State of Go Language for Android Native Development
0
评论

干货:Nginx/LVS/HAProxy 负载均衡软件的优缺点详解 移动开发

oscar 发表了文章 • 3588 次浏览 • 2015-07-08 10:56 • 来自相关话题

Nginx/LVS/HAProxy是目前使用最广泛的三种负载均衡软件,一般对负载均衡的使用是随着网站规模的提升根据不同的阶段来使用不同的技术,具体的应用需求还得具体分析。
如果是中小型的Web应用,比如日PV小于1000万,用Nginx就完全可以了;如果机器不少,可以用DNS轮询,LVS所耗费的机器还是比较多的;大型网站或重要的服务,且服务器比较多时,可以考虑用LVS。
目前关于网站架构一般比较合理流行的架构方案:Web前端采用Nginx/HAProxy+Keepalived作负载均衡器;后端采用MySQL数据库一主多从和读写分离,采用LVS+Keepalived的架构。当然要根据项目具体需求制定方案,下面说说各自的特点和适用场合。
Nginx
Nginx的优点:
工作在网络的7层之上,可以针对http应用做一些分流的策略,比如针对域名、目录结构,它的正则规则比HAProxy更为强大和灵活,这也是它目前广泛流行的主要原因之一,Nginx单凭这点可利用的场合就远多于LVS了。Nginx对网络稳定性的依赖非常小,理论上能ping通就就能进行负载功能,这个也是它的优势之一;相反LVS对网络稳定性依赖比较大,这点用过Nginx的人都深有体会;Nginx安装和配置比较简单,测试起来比较方便,它基本能把错误用日志打印出来。LVS的配置、测试就要花比较长的时间了,LVS对网络依赖比较大。可以承担高负载压力且稳定,在硬件不差的情况下一般能支撑几万次的并发量,负载度比LVS相对小些。Nginx可以通过端口检测到服务器内部的故障,比如根据服务器处理网页返回的状态码、超时等等,并且会把返回错误的请求重新提交到另一个节点,不过其中缺点就是不支持url来检测。比如用户正在上传一个文件,而处理该上传的节点刚好在上传过程中出现故障,Nginx会把上传切到另一台服务器重新处理,而LVS就直接断掉了,如果是上传一个很大的文件或者很重要的文件的话,用户可能会因此而不满。Nginx不仅仅是一款优秀的负载均衡器/反向代理软件,它同时也是功能强大的Web应用服务器。LNMP也是近几年非常流行的web架构,在高流量的环境中稳定性也很好。Nginx现在作为Web反向加速缓存越来越成熟了,速度比传统的Squid服务器更快,可以考虑用其作为反向代理加速器。Nginx可作为中层反向代理使用,这一层面Nginx基本上无对手,唯一可以对比Nginx的就只有lighttpd了,不过lighttpd目前还没有做到Nginx完全的功能,配置也不那么清晰易读,社区资料也远远没Nginx活跃。Nginx也可作为静态网页和图片服务器,这方面的性能也无对手。还有Nginx社区非常活跃,第三方模块也很多。
Nginx的缺点:
Nginx仅能支持http、https和Email协议,这样就在适用范围上面小些,这个是它的缺点。对后端服务器的健康检查,只支持通过端口来检测,不支持通过url来检测。不支持Session的直接保持,但能通过ip_hash来解决。
LVS
LVS是使用Linux内核集群实现的一个高性能、高可用的负载均衡服务器,它具有很好的可伸缩性(Scalability)、可靠性(Reliability)和可管理性(Manageability)。
LVS的优点:
抗负载能力强,工作在网络4层之上,仅作分发之用,没有流量的产生,这个特点也决定了它在负载均衡软件里的性能最强的,对内存和cpu资源消耗比较低。配置性比较低,这是一个缺点也是一个优点,因为没有可太多配置的东西,所以并不需要太多接触,大大减少了人为出错的几率。工作稳定,因为其本身抗负载能力很强,自身有完整的双机热备方案,如LVS+Keepalived,不过我们在项目实施中用得最多的还是LVS/DR+Keepalived。无流量,LVS只分发请求,而流量并不从它本身出去,这点保证了均衡器IO的性能不会收到大流量的影响。应用范围比较广,因为LVS工作在4层,所以它几乎可以对所有应用做负载均衡,包括http、数据库、在线聊天室等等。
LVS的缺点:
软件本身不支持正则表达式处理,不能做动静分离;而现在许多网站在这方面都有较强的需求,这个是Nginx/HAProxy+Keepalived的优势所在。如果是网站应用比较庞大的话,LVS/DR+Keepalived实施起来就比较复杂了,特别后面有Windows Server的机器的话,如果实施及配置还有维护过程就比较复杂了,相对而言,Nginx/HAProxy+Keepalived就简单多了。
HAProxy
HAProxy的特点:
HAProxy也是支持虚拟主机的。HAProxy的优点能够补充Nginx的一些缺点,比如支持Session的保持,Cookie的引导;同时支持通过获取指定的url来检测后端服务器的状态。HAProxy跟LVS类似,本身就只是一款负载均衡软件;单纯从效率上来讲HAProxy会比Nginx有更出色的负载均衡速度,在并发处理上也是优于Nginx的。HAProxy支持TCP协议的负载均衡转发,可以对MySQL读进行负载均衡,对后端的MySQL节点进行检测和负载均衡,大家可以用LVS+Keepalived对MySQL主从做负载均衡。5、HAProxy负载均衡策略非常多,HAProxy的负载均衡算法现在具体有如下8种:
roundrobin:表示简单的轮询,这个不多说,这个是负载均衡基本都具备的;
static-rr:表示根据权重,建议关注;
leastconn:表示最少连接者先处理,建议关注;
source:表示根据请求源IP,这个跟Nginx的IP_hash机制类似,我们用其作为解决session问题的一种方法,建议关注;
ri:表示根据请求的URI;
rl_param:表示根据请求的URl参数’balance url_param’ requires an URL parameter name;
hdr(name):表示根据HTTP请求头来锁定每一次HTTP请求;
rdp-cookie(name):表示根据据cookie(name)来锁定并哈希每一次TCP请求。
Nginx和LVS对比总结:
Nginx工作在网络的7层,所以它可以针对http应用本身来做分流策略,比如针对域名、目录结构等,相比之下LVS并不具备这样的功能,所以Nginx单凭这点可利用的场合就远多于LVS了;但Nginx有用的这些功能使其可调整度要高于LVS,所以经常要去触碰触碰,触碰多了,人为出问题的几率也就会大。
Nginx对网络稳定性的依赖较小,理论上只要ping得通,网页访问正常,Nginx就能连得通,这是Nginx的一大优势!Nginx同时还能区分内外网,如果是同时拥有内外网的节点,就相当于单机拥有了备份线路;LVS就比较依赖于网络环境,目前来看服务器在同一网段内并且LVS使用direct方式分流,效果较能得到保证。
另外注意,LVS需要向托管商至少申请多一个ip来做Visual IP,貌似是不能用本身的IP来做VIP的。要做好LVS管理员,确实得跟进学习很多有关网络通信方面的知识,就不再是一个HTTP那么简单了。
Nginx安装和配置比较简单,测试起来也很方便,因为它基本能把错误用日志打印出来。LVS的安装和配置、测试就要花比较长的时间了;LVS对网络依赖比较大,很多时候不能配置成功都是因为网络问题而不是配置问题,出了问题要解决也相应的会麻烦得多。
Nginx也同样能承受很高负载且稳定,但负载度和稳定度差LVS还有几个等级:Nginx处理所有流量所以受限于机器IO和配置;本身的bug也还是难以避免的。
Nginx可以检测到服务器内部的故障,比如根据服务器处理网页返回的状态码、超时等等,并且会把返回错误的请求重新提交到另一个节点。目前LVS中 ldirectd也能支持针对服务器内部的情况来监控,但LVS的原理使其不能重发请求。
比如用户正在上传一个文件,而处理该上传的节点刚好在上传过程中出现故障,Nginx会把上传切到另一台服务器重新处理,而LVS就直接断掉了,如果是上传一个很大的文件或者很重要的文件的话,用户可能会因此而恼火。
Nginx对请求的异步处理可以帮助节点服务器减轻负载,假如使用apache直接对外服务,那么出现很多的窄带链接时apache服务器将会占用大 量内存而不能释放,使用多一个Nginx做apache代理的话,这些窄带链接会被Nginx挡住,apache上就不会堆积过多的请求,这样就减少了相当多的资源占用。这点使用squid也有相同的作用,即使squid本身配置为不缓存,对apache还是有很大帮助的。
Nginx能支持http、https和email(email的功能比较少用),LVS所支持的应用在这点上会比Nginx更多。在使用上,一般最前端所采取的策略应是LVS,也就是DNS的指向应为LVS均衡器,LVS的优点令它非常适合做这个任务。
重要的ip地址,最好交由LVS托管,比如数据库的 ip、webservice服务器的ip等等,这些ip地址随着时间推移,使用面会越来越大,如果更换ip则故障会接踵而至。所以将这些重要ip交给 LVS托管是最为稳妥的,这样做的唯一缺点是需要的VIP数量会比较多。
Nginx可作为LVS节点机器使用,一是可以利用Nginx的功能,二是可以利用Nginx的性能。当然这一层面也可以直接使用squid,squid的功能方面就比Nginx弱不少了,性能上也有所逊色于Nginx。Nginx也可作为中层代理使用,这一层面Nginx基本上无对手,唯一可以撼动Nginx的就只有lighttpd了,不过lighttpd目前还没有能做到 Nginx完全的功能,配置也不那么清晰易读。
另外,中层代理的IP也是重要的,所以中层代理也拥有一个VIP和LVS是最完美的方案了。具体的应用还得具体分析,如果是比较小的网站(日PV小于1000万),用Nginx就完全可以了,如果机器也不少,可以用DNS轮询,LVS所耗费的机器还是比较多的;大型网站或者重要的服务,机器不发愁的时候,要多多考虑利用LVS。
现在对网络负载均衡的使用是随着网站规模的提升根据不同的阶段来使用不同的技术:
第一阶段:利用Nginx或HAProxy进行单点的负载均衡,这一阶段服务器规模刚脱离开单服务器、单数据库的模式,需要一定的负载均衡,但是仍然规模较小没有专业的维护团队来进行维护,也没有需要进行大规模的网站部署。这样利用Nginx或HAproxy就是第一选择,此时这些东西上手快, 配置容易,在七层之上利用HTTP协议就可以。这时是第一选择。第二阶段:随着网络服务进一步扩大,这时单点的Nginx已经不能满足,这时使用LVS或者商用Array就是首要选择,Nginx此时就作为LVS或者Array的节点来使用,具体LVS或Array的是选择是根据公司规模和预算来选择,Array的应用交付功能非常强大,本人在某项目中使用过,性价比也远高于F5,商用首选!但是一般来说这阶段相关人才跟不上业务的提升,所以购买商业负载均衡已经成为了必经之路。关人才的能力以及数量也随之提升,这时无论从开发适合自身产品的定制,以及降低成本来讲开源的LVS,已经成为首选,这时LVS会成为主流。第三阶段:这时网络服务已经成为主流产品,此时随着公司知名度也进一步扩展,相关人才的能力以及数量也随之提升,这时无论从开发适合自身产品的定制,以及降低成本来讲开源的LVS,已经成为首选,这时LVS会成为主流。最终形成比较理想的基本架构为:Array/LVS — Nginx/Haproxy — Squid/Varnish — AppServer。
 来源:linux中国 查看全部
Nginx/LVS/HAProxy是目前使用最广泛的三种负载均衡软件,一般对负载均衡的使用是随着网站规模的提升根据不同的阶段来使用不同的技术,具体的应用需求还得具体分析。
如果是中小型的Web应用,比如日PV小于1000万,用Nginx就完全可以了;如果机器不少,可以用DNS轮询,LVS所耗费的机器还是比较多的;大型网站或重要的服务,且服务器比较多时,可以考虑用LVS。
目前关于网站架构一般比较合理流行的架构方案:Web前端采用Nginx/HAProxy+Keepalived作负载均衡器;后端采用MySQL数据库一主多从和读写分离,采用LVS+Keepalived的架构。当然要根据项目具体需求制定方案,下面说说各自的特点和适用场合。
Nginx
Nginx的优点:
  • 工作在网络的7层之上,可以针对http应用做一些分流的策略,比如针对域名、目录结构,它的正则规则比HAProxy更为强大和灵活,这也是它目前广泛流行的主要原因之一,Nginx单凭这点可利用的场合就远多于LVS了。
  • Nginx对网络稳定性的依赖非常小,理论上能ping通就就能进行负载功能,这个也是它的优势之一;相反LVS对网络稳定性依赖比较大,这点用过Nginx的人都深有体会;
  • Nginx安装和配置比较简单,测试起来比较方便,它基本能把错误用日志打印出来。LVS的配置、测试就要花比较长的时间了,LVS对网络依赖比较大。
  • 可以承担高负载压力且稳定,在硬件不差的情况下一般能支撑几万次的并发量,负载度比LVS相对小些。
  • Nginx可以通过端口检测到服务器内部的故障,比如根据服务器处理网页返回的状态码、超时等等,并且会把返回错误的请求重新提交到另一个节点,不过其中缺点就是不支持url来检测。比如用户正在上传一个文件,而处理该上传的节点刚好在上传过程中出现故障,Nginx会把上传切到另一台服务器重新处理,而LVS就直接断掉了,如果是上传一个很大的文件或者很重要的文件的话,用户可能会因此而不满。
  • Nginx不仅仅是一款优秀的负载均衡器/反向代理软件,它同时也是功能强大的Web应用服务器。LNMP也是近几年非常流行的web架构,在高流量的环境中稳定性也很好。
  • Nginx现在作为Web反向加速缓存越来越成熟了,速度比传统的Squid服务器更快,可以考虑用其作为反向代理加速器。
  • Nginx可作为中层反向代理使用,这一层面Nginx基本上无对手,唯一可以对比Nginx的就只有lighttpd了,不过lighttpd目前还没有做到Nginx完全的功能,配置也不那么清晰易读,社区资料也远远没Nginx活跃。
  • Nginx也可作为静态网页和图片服务器,这方面的性能也无对手。还有Nginx社区非常活跃,第三方模块也很多。

Nginx的缺点:
  • Nginx仅能支持http、https和Email协议,这样就在适用范围上面小些,这个是它的缺点。
  • 对后端服务器的健康检查,只支持通过端口来检测,不支持通过url来检测。不支持Session的直接保持,但能通过ip_hash来解决。

LVS
LVS是使用Linux内核集群实现的一个高性能、高可用的负载均衡服务器,它具有很好的可伸缩性(Scalability)、可靠性(Reliability)和可管理性(Manageability)。
LVS的优点:
  • 抗负载能力强,工作在网络4层之上,仅作分发之用,没有流量的产生,这个特点也决定了它在负载均衡软件里的性能最强的,对内存和cpu资源消耗比较低。
  • 配置性比较低,这是一个缺点也是一个优点,因为没有可太多配置的东西,所以并不需要太多接触,大大减少了人为出错的几率。
  • 工作稳定,因为其本身抗负载能力很强,自身有完整的双机热备方案,如LVS+Keepalived,不过我们在项目实施中用得最多的还是LVS/DR+Keepalived。
  • 无流量,LVS只分发请求,而流量并不从它本身出去,这点保证了均衡器IO的性能不会收到大流量的影响。
  • 应用范围比较广,因为LVS工作在4层,所以它几乎可以对所有应用做负载均衡,包括http、数据库、在线聊天室等等。

LVS的缺点:
  • 软件本身不支持正则表达式处理,不能做动静分离;而现在许多网站在这方面都有较强的需求,这个是Nginx/HAProxy+Keepalived的优势所在。
  • 如果是网站应用比较庞大的话,LVS/DR+Keepalived实施起来就比较复杂了,特别后面有Windows Server的机器的话,如果实施及配置还有维护过程就比较复杂了,相对而言,Nginx/HAProxy+Keepalived就简单多了。

HAProxy
HAProxy的特点:
  • HAProxy也是支持虚拟主机的。
  • HAProxy的优点能够补充Nginx的一些缺点,比如支持Session的保持,Cookie的引导;同时支持通过获取指定的url来检测后端服务器的状态。
  • HAProxy跟LVS类似,本身就只是一款负载均衡软件;单纯从效率上来讲HAProxy会比Nginx有更出色的负载均衡速度,在并发处理上也是优于Nginx的。
  • HAProxy支持TCP协议的负载均衡转发,可以对MySQL读进行负载均衡,对后端的MySQL节点进行检测和负载均衡,大家可以用LVS+Keepalived对MySQL主从做负载均衡。
  • 5、HAProxy负载均衡策略非常多,HAProxy的负载均衡算法现在具体有如下8种:

roundrobin:表示简单的轮询,这个不多说,这个是负载均衡基本都具备的;
static-rr:表示根据权重,建议关注;
leastconn:表示最少连接者先处理,建议关注;
source:表示根据请求源IP,这个跟Nginx的IP_hash机制类似,我们用其作为解决session问题的一种方法,建议关注;
ri:表示根据请求的URI;
rl_param:表示根据请求的URl参数’balance url_param’ requires an URL parameter name;
hdr(name):表示根据HTTP请求头来锁定每一次HTTP请求;
rdp-cookie(name):表示根据据cookie(name)来锁定并哈希每一次TCP请求。
Nginx和LVS对比总结:
Nginx工作在网络的7层,所以它可以针对http应用本身来做分流策略,比如针对域名、目录结构等,相比之下LVS并不具备这样的功能,所以Nginx单凭这点可利用的场合就远多于LVS了;但Nginx有用的这些功能使其可调整度要高于LVS,所以经常要去触碰触碰,触碰多了,人为出问题的几率也就会大。
Nginx对网络稳定性的依赖较小,理论上只要ping得通,网页访问正常,Nginx就能连得通,这是Nginx的一大优势!Nginx同时还能区分内外网,如果是同时拥有内外网的节点,就相当于单机拥有了备份线路;LVS就比较依赖于网络环境,目前来看服务器在同一网段内并且LVS使用direct方式分流,效果较能得到保证。
另外注意,LVS需要向托管商至少申请多一个ip来做Visual IP,貌似是不能用本身的IP来做VIP的。要做好LVS管理员,确实得跟进学习很多有关网络通信方面的知识,就不再是一个HTTP那么简单了。
Nginx安装和配置比较简单,测试起来也很方便,因为它基本能把错误用日志打印出来。LVS的安装和配置、测试就要花比较长的时间了;LVS对网络依赖比较大,很多时候不能配置成功都是因为网络问题而不是配置问题,出了问题要解决也相应的会麻烦得多。
Nginx也同样能承受很高负载且稳定,但负载度和稳定度差LVS还有几个等级:Nginx处理所有流量所以受限于机器IO和配置;本身的bug也还是难以避免的。
Nginx可以检测到服务器内部的故障,比如根据服务器处理网页返回的状态码、超时等等,并且会把返回错误的请求重新提交到另一个节点。目前LVS中 ldirectd也能支持针对服务器内部的情况来监控,但LVS的原理使其不能重发请求。
比如用户正在上传一个文件,而处理该上传的节点刚好在上传过程中出现故障,Nginx会把上传切到另一台服务器重新处理,而LVS就直接断掉了,如果是上传一个很大的文件或者很重要的文件的话,用户可能会因此而恼火。
Nginx对请求的异步处理可以帮助节点服务器减轻负载,假如使用apache直接对外服务,那么出现很多的窄带链接时apache服务器将会占用大 量内存而不能释放,使用多一个Nginx做apache代理的话,这些窄带链接会被Nginx挡住,apache上就不会堆积过多的请求,这样就减少了相当多的资源占用。这点使用squid也有相同的作用,即使squid本身配置为不缓存,对apache还是有很大帮助的。
Nginx能支持http、https和email(email的功能比较少用),LVS所支持的应用在这点上会比Nginx更多。在使用上,一般最前端所采取的策略应是LVS,也就是DNS的指向应为LVS均衡器,LVS的优点令它非常适合做这个任务。
重要的ip地址,最好交由LVS托管,比如数据库的 ip、webservice服务器的ip等等,这些ip地址随着时间推移,使用面会越来越大,如果更换ip则故障会接踵而至。所以将这些重要ip交给 LVS托管是最为稳妥的,这样做的唯一缺点是需要的VIP数量会比较多。
Nginx可作为LVS节点机器使用,一是可以利用Nginx的功能,二是可以利用Nginx的性能。当然这一层面也可以直接使用squid,squid的功能方面就比Nginx弱不少了,性能上也有所逊色于Nginx。Nginx也可作为中层代理使用,这一层面Nginx基本上无对手,唯一可以撼动Nginx的就只有lighttpd了,不过lighttpd目前还没有能做到 Nginx完全的功能,配置也不那么清晰易读。
另外,中层代理的IP也是重要的,所以中层代理也拥有一个VIP和LVS是最完美的方案了。具体的应用还得具体分析,如果是比较小的网站(日PV小于1000万),用Nginx就完全可以了,如果机器也不少,可以用DNS轮询,LVS所耗费的机器还是比较多的;大型网站或者重要的服务,机器不发愁的时候,要多多考虑利用LVS。
现在对网络负载均衡的使用是随着网站规模的提升根据不同的阶段来使用不同的技术:
  • 第一阶段:利用Nginx或HAProxy进行单点的负载均衡,这一阶段服务器规模刚脱离开单服务器、单数据库的模式,需要一定的负载均衡,但是仍然规模较小没有专业的维护团队来进行维护,也没有需要进行大规模的网站部署。这样利用Nginx或HAproxy就是第一选择,此时这些东西上手快, 配置容易,在七层之上利用HTTP协议就可以。这时是第一选择。
  • 第二阶段:随着网络服务进一步扩大,这时单点的Nginx已经不能满足,这时使用LVS或者商用Array就是首要选择,Nginx此时就作为LVS或者Array的节点来使用,具体LVS或Array的是选择是根据公司规模和预算来选择,Array的应用交付功能非常强大,本人在某项目中使用过,性价比也远高于F5,商用首选!但是一般来说这阶段相关人才跟不上业务的提升,所以购买商业负载均衡已经成为了必经之路。关人才的能力以及数量也随之提升,这时无论从开发适合自身产品的定制,以及降低成本来讲开源的LVS,已经成为首选,这时LVS会成为主流。
  • 第三阶段:这时网络服务已经成为主流产品,此时随着公司知名度也进一步扩展,相关人才的能力以及数量也随之提升,这时无论从开发适合自身产品的定制,以及降低成本来讲开源的LVS,已经成为首选,这时LVS会成为主流。最终形成比较理想的基本架构为:Array/LVS — Nginx/Haproxy — Squid/Varnish — AppServer。

 来源:linux中国
0
评论

移动5年 Android生态系统的演进 移动开发

oscar 发表了文章 • 984 次浏览 • 2015-07-07 15:15 • 来自相关话题

由Google、HTC、Qualcomm联手打造的第一部Android手机G1,开启了移动时代的Andr​​oid纪元(如图1所示),直到现在Android也是唯一能在移动市场上与iOS相抗衡的平台。简单地说,Android与iOS占尽了移动时代的先机(这个故事要从2007年的iPhone和2008年的Andr​​oid G1开始说起,甚至是更早之前的开发史及并购史),App开发者已在Android及iOS上扎下了深厚的根基,因此再也无力也没有必要去为第三个平台开发或移植自己的App,原因很简单,因为受众太少,支出与收入不成正比。






一开始Android生态系统很简单,就是拉拢App开发者,并且寻求与更多芯片制造商及手机厂商的合作,共同推广Android这个开放平台。但随着Android市场占有率逐步攀升,Google开始一步步地收紧及控制生态系的发展,以期自己能在Android平台上获得更多的利益(简单地说,就是收入,Google希望Android能够为自己带来更多的收益),而不再满足于只是打造及提供Android平台的角色。

随着Android一路开疆辟土,出现在越来越多的移动设备上,再加上Google对Android策略的转变,现今的Andr​​oid生态系统已变得较以往复杂了许多,系统中的角色较以往多了电信运营商、汽车制造商、串流内容及媒体提供商等。Google在全球移动市场的策略也已从“移动优先”转变至“攻占所有屏幕(装置)”,而Android也企图往这个目标上不断迈进(如图2所示)。






时至今日,欧洲、美国、日本的手机制造商节节败退,摩托罗拉、诺基亚、索尼等老牌制造商相继裁员(甚至出售手机及移动业务),而中国手机制造商却不断崛起,中兴、华为、联想、酷派、OPPO、小米等相继杀入手机市场后,如今中国已成为全球最大的智能机生产及销售国,智能机用户数早已超越美国。而新兴的国外市场,如印度、南美、东南亚正刮起一阵低价智能机风暴,Android正是这波低价智能机的推手(如采用MTK芯片的Andr​​oid One)。低价智能机席卷着新兴国家的市场,而新兴国家的市场也俨然成为智能机的一个重要主战场,Android的野心当然不止于此,Android企图发力于高、中、低阶的智能机市场,而这些细微的变化正一点点地牵动着Android生态系统的转变。

Android的开放与制约

Android一开始由Andy Rubin领军,从一开始的全面开放,到像选妃似的,每次释放出新版Android软件的同时,选择与特定的手机制造商合作开发Android原生机,例如HTC、三星等。这一举动令各家手机制造商对Android仰望备至,都想抱上Android的大腿。因为手机制造商一旦获得与Android合作开发新版原生机的机会,就等于能提早得到新版Android软件代码,进而取得先机来开发其他自家的产品(如三星的Galaxy系列),早对手一步将自家产品推向市场销售,从而取得市场先机。这种方式无疑令部分手机制造商对Android产生反感。

2013年3月,Android从Andy Rubin转由原领导Chrome的Sundar Pichai接手负责,而Android也由工程导向转为营利导向,例如减少手机制造商与Google分成Google Play和Google Search的收入。Android更强烈地主导其UI显示的一致性,并与各家手机制造商签订约束性的协议,强加Google的相关应用服务于Android系统上,甚至将应用摆放在Android桌面上的位置都强加限制,大幅度收紧了各家Android设备制造商分散且碎片化的UI风格,以期用户在汽车、电视、可穿戴设备、手机等所有Android设备上都能得到相同的用户体验,Google此举也造成了部分手机制造商及开发者的反感。

归根结底,Google还是希望自己的角色能像苹果一样介于用户和运营商之间,由目前的“用户/手机品牌商→运营商”,转变为“用户/手机品牌商→Google→运营商”,以期收紧分散且碎片化的Andr​​oid生态圈,并获取更大的潜在利益。这一点,我们可以在最新发布的Android L版本的软件中看到,Google加入了更多特定运营商所需的功能。

移动互联网时代,Android已然成为Google的一个标准平台,而非过去传闻的与Chrome整合成一个新的平台,或是将Android整合进Chrome中。这种情况下,Android设备制造商如何应对Google的策略调整及Android版本的快速演进,并调整自己迅速定位市场,从而避免自己成为只是帮Google打工的打工仔是至关重要的。Android设备制造商必须打造出自己独特的生态系统(例如跨手机、平板、电视等),而非只是一个设备制造商。这样一来,我们可以清晰地看到,目前纯手机制造商已越发难以生存。

Android系统与架构演进

从Android 1.0至今(更甚至是1.0之前的m*至今),Android系统每一版都有不少的改动(如图3所示),例如HAL有过两次的版本改进、Camera HAL已迭代至第三版、多媒体核心由一开始的OpenCore直到现在的Stagefright。而一开始的WebView至今则完全被Chrome取代,Android也从ARM一路拓展到x86及MIPS平台。版本演进的过程及内容实在太多,如果真的要巨细靡遗地写,可能三天三夜也写不完,所以我想仅对每一版本的改动给予一句代表性的描述​​,并在最后针对Android的最新版(代号L),做一些基本介绍。






Android 1.0:第一部Android手机以及Google Apps的诞生;

Android 1.5 Cupcake:支持软件键盘;

Android 1.6 Donut:支持CDMA;

Android 2.0 Éclair:GPS大放异彩,GoogleNexus One手机诞生;

Android 2.2 Froyo:加入语音识别功能;

Android 2.3 Gingerbread:Nexus S;

Android 3.0 Honeycomb:第一次专给平板设备设计UI;

Android 4.0 Ice Cream Sandwich:一个新的UI界面Holo与内嵌字体Roboto,并支持人脸解锁;

Android 4.1 Jelly Bean:Nexus 7:Google官方第一台Android平板设备;

Android 4.3 Jelly Bean:引入对可穿​​戴设备的支持;

Android 4.4 KitKat:支持更少内存的移动设备。

接下来是Android L,它的预设虚拟机为ART,支持64位,所需要的系统空间较以往的Andr​​oid版本更大,因为ART有一个转换档案格式的动作,其缺点就是会占用更多的系统空间,但之后软件的执行速度可能有一定的提升。另外,Android L可能会加入部分地区及运营商的特殊需求,例如multi-SIM、NFC、Wi-Fi等;此外​​,Android L也更强调系统安全,它可以预设为强制性安全模式,即一般应用启动时需要多道的身分及权限确认才能执行。

时至今日,Android身影几乎无处不在,回顾以往,Android系统的演进总是先求有、再求好,智能移动时代发展至今,全球正迈向下一个里程碑,希望Android此时能不忘初心,做一个平衡生态系统的维护者及领导者,而非仅是利益上的掮客,不要为了利益而让这个生态圈走向封闭。

作为开发者,此时更应该思考自己拥有如此巨大的市场优势、健全的物流体系及现金流系统,以及众多的手机及移动设备制造商,如果能积极培养系统级的软件人才,有条件打造出一个来自中国的自主生态系统,以期将来与Android分庭抗礼。
 
作者:钟文昌 查看全部
由Google、HTC、Qualcomm联手打造的第一部Android手机G1,开启了移动时代的Andr​​oid纪元(如图1所示),直到现在Android也是唯一能在移动市场上与iOS相抗衡的平台。简单地说,Android与iOS占尽了移动时代的先机(这个故事要从2007年的iPhone和2008年的Andr​​oid G1开始说起,甚至是更早之前的开发史及并购史),App开发者已在Android及iOS上扎下了深厚的根基,因此再也无力也没有必要去为第三个平台开发或移植自己的App,原因很简单,因为受众太少,支出与收入不成正比。

1.jpg


一开始Android生态系统很简单,就是拉拢App开发者,并且寻求与更多芯片制造商及手机厂商的合作,共同推广Android这个开放平台。但随着Android市场占有率逐步攀升,Google开始一步步地收紧及控制生态系的发展,以期自己能在Android平台上获得更多的利益(简单地说,就是收入,Google希望Android能够为自己带来更多的收益),而不再满足于只是打造及提供Android平台的角色。

随着Android一路开疆辟土,出现在越来越多的移动设备上,再加上Google对Android策略的转变,现今的Andr​​oid生态系统已变得较以往复杂了许多,系统中的角色较以往多了电信运营商、汽车制造商、串流内容及媒体提供商等。Google在全球移动市场的策略也已从“移动优先”转变至“攻占所有屏幕(装置)”,而Android也企图往这个目标上不断迈进(如图2所示)。

2.jpg


时至今日,欧洲、美国、日本的手机制造商节节败退,摩托罗拉、诺基亚、索尼等老牌制造商相继裁员(甚至出售手机及移动业务),而中国手机制造商却不断崛起,中兴、华为、联想、酷派、OPPO、小米等相继杀入手机市场后,如今中国已成为全球最大的智能机生产及销售国,智能机用户数早已超越美国。而新兴的国外市场,如印度、南美、东南亚正刮起一阵低价智能机风暴,Android正是这波低价智能机的推手(如采用MTK芯片的Andr​​oid One)。低价智能机席卷着新兴国家的市场,而新兴国家的市场也俨然成为智能机的一个重要主战场,Android的野心当然不止于此,Android企图发力于高、中、低阶的智能机市场,而这些细微的变化正一点点地牵动着Android生态系统的转变。

Android的开放与制约

Android一开始由Andy Rubin领军,从一开始的全面开放,到像选妃似的,每次释放出新版Android软件的同时,选择与特定的手机制造商合作开发Android原生机,例如HTC、三星等。这一举动令各家手机制造商对Android仰望备至,都想抱上Android的大腿。因为手机制造商一旦获得与Android合作开发新版原生机的机会,就等于能提早得到新版Android软件代码,进而取得先机来开发其他自家的产品(如三星的Galaxy系列),早对手一步将自家产品推向市场销售,从而取得市场先机。这种方式无疑令部分手机制造商对Android产生反感。

2013年3月,Android从Andy Rubin转由原领导Chrome的Sundar Pichai接手负责,而Android也由工程导向转为营利导向,例如减少手机制造商与Google分成Google Play和Google Search的收入。Android更强烈地主导其UI显示的一致性,并与各家手机制造商签订约束性的协议,强加Google的相关应用服务于Android系统上,甚至将应用摆放在Android桌面上的位置都强加限制,大幅度收紧了各家Android设备制造商分散且碎片化的UI风格,以期用户在汽车、电视、可穿戴设备、手机等所有Android设备上都能得到相同的用户体验,Google此举也造成了部分手机制造商及开发者的反感。

归根结底,Google还是希望自己的角色能像苹果一样介于用户和运营商之间,由目前的“用户/手机品牌商→运营商”,转变为“用户/手机品牌商→Google→运营商”,以期收紧分散且碎片化的Andr​​oid生态圈,并获取更大的潜在利益。这一点,我们可以在最新发布的Android L版本的软件中看到,Google加入了更多特定运营商所需的功能。

移动互联网时代,Android已然成为Google的一个标准平台,而非过去传闻的与Chrome整合成一个新的平台,或是将Android整合进Chrome中。这种情况下,Android设备制造商如何应对Google的策略调整及Android版本的快速演进,并调整自己迅速定位市场,从而避免自己成为只是帮Google打工的打工仔是至关重要的。Android设备制造商必须打造出自己独特的生态系统(例如跨手机、平板、电视等),而非只是一个设备制造商。这样一来,我们可以清晰地看到,目前纯手机制造商已越发难以生存。

Android系统与架构演进

从Android 1.0至今(更甚至是1.0之前的m*至今),Android系统每一版都有不少的改动(如图3所示),例如HAL有过两次的版本改进、Camera HAL已迭代至第三版、多媒体核心由一开始的OpenCore直到现在的Stagefright。而一开始的WebView至今则完全被Chrome取代,Android也从ARM一路拓展到x86及MIPS平台。版本演进的过程及内容实在太多,如果真的要巨细靡遗地写,可能三天三夜也写不完,所以我想仅对每一版本的改动给予一句代表性的描述​​,并在最后针对Android的最新版(代号L),做一些基本介绍。

3.JPG


Android 1.0:第一部Android手机以及Google Apps的诞生;

Android 1.5 Cupcake:支持软件键盘;

Android 1.6 Donut:支持CDMA;

Android 2.0 Éclair:GPS大放异彩,GoogleNexus One手机诞生;

Android 2.2 Froyo:加入语音识别功能;

Android 2.3 Gingerbread:Nexus S;

Android 3.0 Honeycomb:第一次专给平板设备设计UI;

Android 4.0 Ice Cream Sandwich:一个新的UI界面Holo与内嵌字体Roboto,并支持人脸解锁;

Android 4.1 Jelly Bean:Nexus 7:Google官方第一台Android平板设备;

Android 4.3 Jelly Bean:引入对可穿​​戴设备的支持;

Android 4.4 KitKat:支持更少内存的移动设备。

接下来是Android L,它的预设虚拟机为ART,支持64位,所需要的系统空间较以往的Andr​​oid版本更大,因为ART有一个转换档案格式的动作,其缺点就是会占用更多的系统空间,但之后软件的执行速度可能有一定的提升。另外,Android L可能会加入部分地区及运营商的特殊需求,例如multi-SIM、NFC、Wi-Fi等;此外​​,Android L也更强调系统安全,它可以预设为强制性安全模式,即一般应用启动时需要多道的身分及权限确认才能执行。

时至今日,Android身影几乎无处不在,回顾以往,Android系统的演进总是先求有、再求好,智能移动时代发展至今,全球正迈向下一个里程碑,希望Android此时能不忘初心,做一个平衡生态系统的维护者及领导者,而非仅是利益上的掮客,不要为了利益而让这个生态圈走向封闭。

作为开发者,此时更应该思考自己拥有如此巨大的市场优势、健全的物流体系及现金流系统,以及众多的手机及移动设备制造商,如果能积极培养系统级的软件人才,有条件打造出一个来自中国的自主生态系统,以期将来与Android分庭抗礼。
 
作者:钟文昌
0
评论

技术干货:网络性能测试 移动开发

admin 发表了文章 • 2325 次浏览 • 2015-07-07 13:51 • 来自相关话题

实时音视频这种实时业务一般用udp传输数据,其对网络性能是非常敏感的,在实战中,经常需要测试当前端到端或端到云的网络性能。在这里我们讨论一下网络性能测试中所涉及到指标,技术和相关工具,以及如何编写自己的网络性能测试工具。
 
性能指标

先给出几个比较重要的指标的定义以及它们的意义。
 带宽(吞吐量)
单位时间内传输的数据量,单位通常是每秒比特数,记作bps;带宽反映了网络的传输能力,越大越好;
丢包
数据包丢失个数,等于“发送数据包数” - “接受数据包数”;丢包反映了网络可靠性,越小越好;
时延
数据包从发送开始到接收到该数据所耗费的时间,单位通常是毫秒;时延反映了网络的速度,越小越好;
抖动
指时延的变化,即两个数据包时延的差值;抖动反映了网络的稳定性,越小越好;
乱序
指接收到的数据包顺序和发送顺序不一致的次数;乱序反映了网络的稳定性,越小越好;当乱序比较严重时,丢包也会比较严重,所以一般都以丢包指标为主,忽略乱序指标;
 
测试工具

网上有很多测试网络性能的工具,如果它们能满足需求的话,就不用自己再造轮子了。

ping

ping是最常见的,几乎在所有的OS上都有它的存在。 其工作原理如图






Local发送的数据包,Remote收到数据包后原样发回来;
数据包里包含有序号和时间戳信息;
序号用于判断是否丢包;
时间戳用于计算来回时延(图中蓝色部分),它等于接收时间减去数据包时间戳;

不同OS的ping命令选项可能会略有差别,以Mac OSX的ping为例$ping -s 1024 192.168.1.100

PING www.microsoft.com (23.42.217.205): 1024 data bytes

1032 bytes from 23.42.217.205: icmp_seq=0 ttl=49 time=83.883 ms

1032 bytes from 23.42.217.205: icmp_seq=1 ttl=49 time=77.958 ms

1032 bytes from 23.42.217.205: icmp_seq=2 ttl=49 time=80.053 ms

1032 bytes from 23.42.217.205: icmp_seq=3 ttl=49 time=78.244 ms

1032 bytes from 23.42.217.205: icmp_seq=4 ttl=49 time=77.937 ms

...

^C

--- 192.168.1.100 ping statistics ---

30 packets transmitted, 29 packets received, 3.3% packet loss

round-trip min/avg/max/stddev = 77.843/95.375/141.314/19.167 ms

其中 -s 1024 指示包的大小为1024字节;从ping结果可以看出,发送了30个包,收到29个包,3.3%的丢包率,最小时延77.843毫秒,最大时延141.314毫秒,平均时延95.375毫秒,时延的标准差19.167。另外,ping用的是ICMP协议,网络对ICMP协议处理性能,可能跟UDP或TCP是不一样的,所以测试结果只能做为参考。
小结:ping的优点是简单便捷,可以测试时延和丢包,缺点是无法测试带宽。

iperf

iperf功能功能强一些,可以测带宽,丢包,抖动, 但是测不了时延。它的工作原理如图:






服务端:$iperf -u -s -p 12345 -i 1 -w 1000000
------------------------------------------------------------

Server listening on UDP port 12345

Receiving 1470 byte datagrams

UDP buffer size: 977 KByte

------------------------------------------------------------

客户端:$ iperf -u -c 127.0.0.1 -p 12345 -i 1 -t 5 -b 16K -l 62

------------------------------------------------------------

Client connecting to 127.0.0.1, UDP port 12345

Sending 62 byte datagrams

UDP buffer size: 9.00 KByte (default)

------------------------------------------------------------

[ 4] local 127.0.0.1 port 59805 connected with 127.0.0.1 port 12345

[ ID] Interval Transfer Bandwidth

[ 4] 0.0- 1.0 sec 2.00 KBytes 16.4 Kbits/sec

[ 4] 1.0- 2.0 sec 1.94 KBytes 15.9 Kbits/sec

[ 4] 2.0- 3.0 sec 1.94 KBytes 15.9 Kbits/sec

[ 4] 3.0- 4.0 sec 1.94 KBytes 15.9 Kbits/sec

[ 4] 4.0- 5.0 sec 2.00 KBytes 16.4 Kbits/sec

[ 4] 0.0- 5.1 sec 9.87 KBytes 16.0 Kbits/sec

[ 4] Sent 163 datagrams

[ 4] Server Report:

[ 4] 0.0- 5.1 sec 9.87 KBytes 16.0 Kbits/sec 0.046 ms 0/ 163 (0%)

其中 -b 16K 指定了带宽参数。测试结果为丢包0个,平均抖动为0.046毫秒。
 
自己开发or(unsigned second = 0; second < test_seconds; second++)

{

for(unsigned ui = 0; ui < 8; ui++)

{

sendto 1024 bytes;

}

msleep(1000);

}

从上面可以看出,ping和iperf各有优缺点,通常需要两者组合才能满足我们的需求。有时候现有工具不能满足实际应用的需求,比如说完全模拟实际业务环境或者在产品里集成测试功能,这时候就需要发挥“自己动手,丰衣足食”的精神,造出一个适合自己用的轮子来。我们这里只讨论关键点之一:如何匀速发送数据。
我们以设定发送包长为1024字节,带宽为64kbps为例子,讨论发送数据的实现方案。
发送数据最简单的方法就是,起一个线程,每秒直接发送完当前秒的数据,然后sleep一秒,再继续发送,如下:

这种方法比较简单,但是因为发送数据是需要花费时间的,假如发送64Kbit花费了5毫秒,实际发送码率(带宽)为64/1005≈63.68Kbps,比设定值低一些。把发送时间考虑在内,第2个改进后的代码版本如下:for(unsigned second = 0; second < test_seconds; second++)

{

unsigned ts_start = gettimestamp();

for(unsigned ui = 0; ui < 8; ui++)

{

sendto 1024 bytes;

}

unsigned elapsed = gettimestamp() - ts_start;

msleep(1000-elapsed);

}

从大尺度上看,这个版本确实会按设定带宽发送数据,但从小的的时间片上看,其瞬时发送速率是非常高的。假如发送64Kbit花费了5毫秒,则瞬时速率为 64*1000/5=12800Kbps,是设定值的20倍。这种瞬时高发送速率可能会导致网络中某些路由器或交换机来不及处理而大量丢包。所以我们继续改进,在每发送一个包时check是否发送太快,如果发送太快的话就sleep一下缓一缓。改进后的第三个版本如下:uint64_t sent_bytes = 0;

unsigned kick_time = gettimestamp();

for(unsigned second = 0; second < test_seconds; second++) { sendto 1024 bytes; sent_bytes += 1024; unsigned elapsed = gettimestamp() - kick_time; unsigned normal = sent_bytes * 1000 * 8 / (64*1000); if(normal > elapsed)

{

msleep(normal-elapsed);

}

}

这个版本基本能够按照设定值匀速发送数据了。当然,它还不是最完美的,当设定带宽很高而包长很小时,会导致太多的check,占用太多CPU。这里就不继续改进了,有兴趣的看官可以自己实现之。
 
作者:符宁 查看全部
实时音视频这种实时业务一般用udp传输数据,其对网络性能是非常敏感的,在实战中,经常需要测试当前端到端或端到云的网络性能。在这里我们讨论一下网络性能测试中所涉及到指标,技术和相关工具,以及如何编写自己的网络性能测试工具。
 
性能指标

先给出几个比较重要的指标的定义以及它们的意义。
 带宽(吞吐量)
  • 单位时间内传输的数据量,单位通常是每秒比特数,记作bps;
  • 带宽反映了网络的传输能力,越大越好;

丢包
  • 数据包丢失个数,等于“发送数据包数” - “接受数据包数”;
  • 丢包反映了网络可靠性,越小越好;

时延
  • 数据包从发送开始到接收到该数据所耗费的时间,单位通常是毫秒;
  • 时延反映了网络的速度,越小越好;

抖动
  • 指时延的变化,即两个数据包时延的差值;
  • 抖动反映了网络的稳定性,越小越好;

乱序
  • 指接收到的数据包顺序和发送顺序不一致的次数;
  • 乱序反映了网络的稳定性,越小越好;
  • 当乱序比较严重时,丢包也会比较严重,所以一般都以丢包指标为主,忽略乱序指标;

 
测试工具

网上有很多测试网络性能的工具,如果它们能满足需求的话,就不用自己再造轮子了。

ping

ping是最常见的,几乎在所有的OS上都有它的存在。 其工作原理如图

1.png


Local发送的数据包,Remote收到数据包后原样发回来;
数据包里包含有序号和时间戳信息;
序号用于判断是否丢包;
时间戳用于计算来回时延(图中蓝色部分),它等于接收时间减去数据包时间戳;

不同OS的ping命令选项可能会略有差别,以Mac OSX的ping为例
$ping -s 1024 192.168.1.100

PING www.microsoft.com (23.42.217.205): 1024 data bytes

1032 bytes from 23.42.217.205: icmp_seq=0 ttl=49 time=83.883 ms

1032 bytes from 23.42.217.205: icmp_seq=1 ttl=49 time=77.958 ms

1032 bytes from 23.42.217.205: icmp_seq=2 ttl=49 time=80.053 ms

1032 bytes from 23.42.217.205: icmp_seq=3 ttl=49 time=78.244 ms

1032 bytes from 23.42.217.205: icmp_seq=4 ttl=49 time=77.937 ms

...

^C

--- 192.168.1.100 ping statistics ---

30 packets transmitted, 29 packets received, 3.3% packet loss

round-trip min/avg/max/stddev = 77.843/95.375/141.314/19.167 ms

其中 -s 1024 指示包的大小为1024字节;从ping结果可以看出,发送了30个包,收到29个包,3.3%的丢包率,最小时延77.843毫秒,最大时延141.314毫秒,平均时延95.375毫秒,时延的标准差19.167。另外,ping用的是ICMP协议,网络对ICMP协议处理性能,可能跟UDP或TCP是不一样的,所以测试结果只能做为参考。
小结:ping的优点是简单便捷,可以测试时延和丢包,缺点是无法测试带宽。

iperf

iperf功能功能强一些,可以测带宽,丢包,抖动, 但是测不了时延。它的工作原理如图:

2.png


服务端:
$iperf -u -s -p 12345 -i 1 -w 1000000
------------------------------------------------------------

Server listening on UDP port 12345

Receiving 1470 byte datagrams

UDP buffer size: 977 KByte

------------------------------------------------------------

客户端:
$ iperf -u -c 127.0.0.1 -p 12345 -i 1 -t 5 -b 16K -l 62

------------------------------------------------------------

Client connecting to 127.0.0.1, UDP port 12345

Sending 62 byte datagrams

UDP buffer size: 9.00 KByte (default)

------------------------------------------------------------

[ 4] local 127.0.0.1 port 59805 connected with 127.0.0.1 port 12345

[ ID] Interval Transfer Bandwidth

[ 4] 0.0- 1.0 sec 2.00 KBytes 16.4 Kbits/sec

[ 4] 1.0- 2.0 sec 1.94 KBytes 15.9 Kbits/sec

[ 4] 2.0- 3.0 sec 1.94 KBytes 15.9 Kbits/sec

[ 4] 3.0- 4.0 sec 1.94 KBytes 15.9 Kbits/sec

[ 4] 4.0- 5.0 sec 2.00 KBytes 16.4 Kbits/sec

[ 4] 0.0- 5.1 sec 9.87 KBytes 16.0 Kbits/sec

[ 4] Sent 163 datagrams

[ 4] Server Report:

[ 4] 0.0- 5.1 sec 9.87 KBytes 16.0 Kbits/sec 0.046 ms 0/ 163 (0%)

其中 -b 16K 指定了带宽参数。测试结果为丢包0个,平均抖动为0.046毫秒。
 
自己开发
or(unsigned second = 0; second < test_seconds; second++)

{

for(unsigned ui = 0; ui < 8; ui++)

{

sendto 1024 bytes;

}

msleep(1000);

}

从上面可以看出,ping和iperf各有优缺点,通常需要两者组合才能满足我们的需求。有时候现有工具不能满足实际应用的需求,比如说完全模拟实际业务环境或者在产品里集成测试功能,这时候就需要发挥“自己动手,丰衣足食”的精神,造出一个适合自己用的轮子来。我们这里只讨论关键点之一:如何匀速发送数据。
我们以设定发送包长为1024字节,带宽为64kbps为例子,讨论发送数据的实现方案。
发送数据最简单的方法就是,起一个线程,每秒直接发送完当前秒的数据,然后sleep一秒,再继续发送,如下:

这种方法比较简单,但是因为发送数据是需要花费时间的,假如发送64Kbit花费了5毫秒,实际发送码率(带宽)为64/1005≈63.68Kbps,比设定值低一些。把发送时间考虑在内,第2个改进后的代码版本如下:
for(unsigned second = 0; second < test_seconds; second++)

{

unsigned ts_start = gettimestamp();

for(unsigned ui = 0; ui < 8; ui++)

{

sendto 1024 bytes;

}

unsigned elapsed = gettimestamp() - ts_start;

msleep(1000-elapsed);

}

从大尺度上看,这个版本确实会按设定带宽发送数据,但从小的的时间片上看,其瞬时发送速率是非常高的。假如发送64Kbit花费了5毫秒,则瞬时速率为 64*1000/5=12800Kbps,是设定值的20倍。这种瞬时高发送速率可能会导致网络中某些路由器或交换机来不及处理而大量丢包。所以我们继续改进,在每发送一个包时check是否发送太快,如果发送太快的话就sleep一下缓一缓。改进后的第三个版本如下:
uint64_t sent_bytes = 0;

unsigned kick_time = gettimestamp();

for(unsigned second = 0; second < test_seconds; second++) { sendto 1024 bytes; sent_bytes += 1024; unsigned elapsed = gettimestamp() - kick_time; unsigned normal = sent_bytes * 1000 * 8 / (64*1000); if(normal > elapsed)

{

msleep(normal-elapsed);

}

}

这个版本基本能够按照设定值匀速发送数据了。当然,它还不是最完美的,当设定带宽很高而包长很小时,会导致太多的check,占用太多CPU。这里就不继续改进了,有兴趣的看官可以自己实现之。
 
作者:符宁
0
评论

Airbnb开源的三个大数据神器 移动开发

oscar 发表了文章 • 2667 次浏览 • 2015-07-07 11:56 • 来自相关话题

7月5日 Airbnb召开了第一次开放技术大会OpenAir,重点是数据驱动在airbnb开发过程中的实践,在大会上,Airbnb开源了3个大数据神器

Airpal






第一个神器叫Airpal,是airbnb内部最炙手可热的数据分析工具,目前在github上面有900多个star。

Airpal是建立在Facebook的Prestodb上的一个可视化分布式SQL查询引擎。Airbnb现在大概有1.5PB的数据。传统上是可以用hive查询,但Hive有以下几个缺点。

第一是对于一些小规模的query,map reduce的overhead太大,比如我就想看一张表的前10行,select * from * limit 10 Hive会触发一个map reduce job,然后半分钟过去了还在map阶段。。。而Airpal背后采用的prestodb则没有这个问题,并且Airpal提供对一个表的数据预览。

Hive的第二个缺点是对于非技术人士不大友好,而airpal是图形界面,只要会sql就可以使用,结果直接生成一个csv文件。很多非技术部门,比如finance的分析员需要做大数据分析的时候,Airpal会非常方便。据我观察,在airbnb,数据科学家还是喜欢用命令行的hive,而非技术人士,或者需要做一些简单查询的工程师和产品经理,则多用airpal

Airpal还有个好处是可以直接和公司的LDAP相连,员工用LDAP登陆,可以直接设置相应的访问权限,使得全公司可以放心用一套数据分析系统

Aerosolve

Aerosolve是支撑Airbnb定价建议系统的机器学习引擎。

传统的机器学习引擎更像一个黑箱,很难知道是哪一个feature对最后的结果产生 了最大的影响。比如Airbnb上的房东设定价格后,我们不仅是希望提示这个价格是过高或过低(模型判断结果),而是希望给房东具体的原因,比如位置太偏,或者评价数不够多(feature的权重)。

比如下图就说明了评价数量以及三星评价数量对价格的影响。我们(惊奇)的发现,一个评价和15个评价的效果差不多,房东并不会因为有更多的评价而得到更多的订单,而3星评价甚至会起到副作用






Airflow

大数据的基础还是data pipeline。Airflow则是Airbnb内部发起、排序、监控data pipeline的工具。





来源:用友开发者 查看全部
7月5日 Airbnb召开了第一次开放技术大会OpenAir,重点是数据驱动在airbnb开发过程中的实践,在大会上,Airbnb开源了3个大数据神器

Airpal

1.jpg


第一个神器叫Airpal,是airbnb内部最炙手可热的数据分析工具,目前在github上面有900多个star。

Airpal是建立在Facebook的Prestodb上的一个可视化分布式SQL查询引擎。Airbnb现在大概有1.5PB的数据。传统上是可以用hive查询,但Hive有以下几个缺点。

第一是对于一些小规模的query,map reduce的overhead太大,比如我就想看一张表的前10行,select * from * limit 10 Hive会触发一个map reduce job,然后半分钟过去了还在map阶段。。。而Airpal背后采用的prestodb则没有这个问题,并且Airpal提供对一个表的数据预览。

Hive的第二个缺点是对于非技术人士不大友好,而airpal是图形界面,只要会sql就可以使用,结果直接生成一个csv文件。很多非技术部门,比如finance的分析员需要做大数据分析的时候,Airpal会非常方便。据我观察,在airbnb,数据科学家还是喜欢用命令行的hive,而非技术人士,或者需要做一些简单查询的工程师和产品经理,则多用airpal

Airpal还有个好处是可以直接和公司的LDAP相连,员工用LDAP登陆,可以直接设置相应的访问权限,使得全公司可以放心用一套数据分析系统

Aerosolve

Aerosolve是支撑Airbnb定价建议系统的机器学习引擎。

传统的机器学习引擎更像一个黑箱,很难知道是哪一个feature对最后的结果产生 了最大的影响。比如Airbnb上的房东设定价格后,我们不仅是希望提示这个价格是过高或过低(模型判断结果),而是希望给房东具体的原因,比如位置太偏,或者评价数不够多(feature的权重)。

比如下图就说明了评价数量以及三星评价数量对价格的影响。我们(惊奇)的发现,一个评价和15个评价的效果差不多,房东并不会因为有更多的评价而得到更多的订单,而3星评价甚至会起到副作用

2.jpg


Airflow

大数据的基础还是data pipeline。Airflow则是Airbnb内部发起、排序、监控data pipeline的工具。

3.gif

来源:用友开发者
0
评论

2015 年度开源项目新秀榜 移动开发 开源

oscar 发表了文章 • 1834 次浏览 • 2015-07-07 11:36 • 来自相关话题

黑鸭(Black Duck)软件公布了一份名叫“年度开源项目新秀”的报告,介绍了由全球开源协会发起的10个最有趣、最活跃的新项目。






年度开源项目新秀

每年都有上千新的开源项目问世,但只有少数能够真正的吸引我们的关注。一些项目因为利用了当前比较流行的技术而发展壮大,有一些则真正地开启了一个新的领域。很多开源项目建立的初衷是为了解决一些生产上的问题,还有一些项目则是世界各地志同道合的开发者们共同发起的一个宏伟项目。

从2009年起,开源软件管理公司黑鸭便发起了 年度开源项目新秀 这一活动,它的评选根据 Open Hub 网站(即以前的Ohloh)上的活跃度。今年,我们很荣幸能够报道2015年10大开源项目新秀的得主和2名荣誉奖得主,它们是从上千个开源项目中脱颖而出的。评选采用了加权评分系统,得分标准基于项目的活跃度,交付速度和几个其它因数。

开源俨然成为了产业创新的引擎,就拿今年来说,和Docker容器相关的开源项目在全球各地兴起,这也不恰巧反映了企业最感兴趣的技术领域吗?最后,我们接下来介绍的项目,将会让你了解到全球开源项目的开发者们的在思考什么,这很快将会成为一个指引我们发展的领头羊。

2015年度开源项目新秀: DebOps






DebOps 收集打包了一套 Ansible 方案和规则(Ansible是一种自动化运维工具),可以从1个容器扩展到一个完整的数据中心。它的创始人Maciej Delmanowski将DebOps开源来保证项目长久进行,从而更好的通过外部贡献者的帮助发展下去。

DebOps始创于波兰的一个不起眼大学校园里,他们运营自己的数据中心,一切工作都采用手工配置。有时系统崩溃而导致几天的宕机,这时Delmanowski意识到一个配置管理系统是很有必要的。以Debian作为基础开始,DebOps是一组配置一整个数据基础设施的Ansible方案。此项目已经在许多不同的工作环境下实现,而创始者们则打算继续支持和改进这个项目。

2015年度开源项目新秀: Code Combat






传统的纸笔学习方法已近不能满足技术学科了。然而游戏却有很多人都爱玩,这也就是为什么 CodeCombat 的创始人会去开发一款多人协同编程游戏来教人们如何编码。

刚开始CodeCombat是一个创业想法,但其创始人决定取而代之创建一个开源项目。此想法在社区传播开来,很快不少贡献者加入到项目中来。项目发起仅仅两个月后,这款游戏就被接纳到Google’s Summer of Code活动中。这款游戏吸引了大量玩家,并被翻译成45种语言。CodeCombat希望成为那些想要一边学习代码同时获得乐趣的同学的风向标。

2015年度开源项目新秀: Storj






Storj 是一个点对点的云存储网络,可实现端到端加密,保证用户不用依赖第三方即可传输和共享数据。基于比特币block chain技术和点对点协议,Storj提供安全、私密、加密的云存储。

云数据存储的反对者担心成本开销和漏洞攻击。针对这两个担忧,Storj提供了一个私有云存储市场,用户可以通过Storjcoin X(SJCX) 购买交易存储空间。上传到Storj的文件会被粉碎、加密和存储到整个社区。只有文件所有者拥有密钥加密的信息。

在2014年举办的Texas Bitcoin Conference Hackathon会议上,去中心化的云存储市场概念首次被提出并证明可行。在第一次赢得黑客马拉松活动后,项目创始人们和领导团队利用开放论坛、Reddit、比特币论坛和社交媒体增长成了一个活跃的社区,如今,它们已成为影响Storj发展方向的一个重要组成部分。

2015年度开源项目新秀: Neovim





 
自1991年出现以来,Vim已经成为数以百万计软件开发人员所钟爱的文本编辑器。 而 Neovim 就是它的下一个版本。

在过去的23年里,软件开发生态系统经历了无数增长和创新。Neovim创始人Thiago de Arruda认为Vim缺乏当代元素,跟不上时代的发展。在保留Vim的招牌功能的前提下,Neovim团队同样在寻求改进和发展这个最受欢迎的文本编辑器的技术。早期众筹让Thiago de Arruda可以连续6个月时间投入到此项目。他相信Neovim社区会支持这个项目,激励他继续开发Neovim。

2015年度开源项目新秀: CockroachDB






前谷歌员工开发了一个开源的大型企业数据存储项目 CockroachDB ,它是一个可扩展的、跨地域复制且支持事务的数据存储的解决方案。

为了保证在线的百万兆字节流量业务的质量,Google开发了Spanner系统,这是一个可扩展的,稳定的,支持事务的系统。许多参与开发CockroachDB的团队现在都服务于开源社区。就像真正的蟑螂(cockroach)一样,CockroachDB可以在没有数据头、任意节点失效的情况下正常运行。这个开源项目有很多富有经验的贡献者,创始人们通过社交媒体、Github、网络、会议和聚会结识他们并鼓励他们参与其中。
 
2015年度开源项目新秀: Kubernetes






在将容器化软件到引入开源社区发展时, Docker 是一匹黑马,它创新了一套技术和工具。去年6月谷歌推出了 Kubernetes ,这是一款开源的容器管理工具,用来加快开发和简化操作。

谷歌在它的内部运营上使用容器技术多年了。在2014年夏天的DockerCon上大会上,谷歌这个互联网巨头开源了Kubernetes,Kubernetes的开发是为了满足迅速增长的Docker生态系统的需要。通过和其它的组织、项目合作,比如Red Hat和CoreOS,Kubernetes项目的管理者们推动它登上了Docker Hub的工具下载榜榜首。Kubernetes的开发团队希望扩大这个项目,发展它的社区,这样的话软件开发者就能花更少的时间在管理基础设施上,而更多的去开发他们自己的APP。

2015年度开源项目新秀: Open Bazaar





OpenBazaar是一个使用比特币与其他人交易的去中心化的市场。OpenBazaar这一概念最早在编程马拉松(hackathon)活动中被提出,它的创始人结合了BitTorent、比特币和传统的金融服务方式,创造了一个不受审查的交易平台。OpenBazaar的开发团队在寻求新的成员,而且不久以后他们将极度扩大Open Bazaar社区。Open Bazaar的核心是透明度,其创始人和贡献者的共同目标是在商务交易中掀起一场革命,让他们向着一个真实的、一个无控制的,去中心化的市场奋进。

2015年度开源项目新秀: IPFS





 
IPFS 是一个面向全球的、点对点的分布式版本文件系统。它综合了Git,BitTorrent,HTTP的思想,开启了一个新的数据和数据结构传输协议。

人们所知的开源,它的本意用简单的方法解决复杂的问题,这样产生许多新颖的想法,但是那些强大的项目仅仅是开源社区的冰山一角。IFPS有一个非常激进的团队,这个概念的提出是大胆的,令人惊讶的,有点甚至高不可攀。看起来,一个点对点的分布式文件系统是在寻求将所有的计算设备连在一起。这个可能的 HTTP 替换品通过多种渠道维护着一个社区,包括Git社区和超过100名贡献者的IRC。这个疯狂的想法将在2015年进行软件内部测试。

2015年度开源项目新秀: cAdvisor






cAdvisor (Container Advisor) 是一个针对在运行中的容器进行收集,统计,处理和输出信息的工具,它可以给容器的使用者提供资源的使用情况和工作特性。对于每一个容器,cAdvisor记录着资源的隔离参数,资源使用历史,资源使用历史对比框图,网络状态。这些从容器输出的数据跨越主机传递。

cAdvisor可以在绝大多数的Linux发行版上运行,并且支持包括Docker在内的多种容器类型。事实上它成为了一种容器的代理,并被集成在了很多系统中。cAdvisor在DockerHub下载量也是位居前茅。cAdvisor的开发团队希望把cAdvisor改进到能够更深入地理解应用性能,并且集成到集群系统。

2015年度开源项目新秀: Terraform





Terraform 提供了一些常见设置来创建一个基础设施,从物理机到虚拟机,以及email服务器、DNS服务器等。这个想法包括从家庭个人机解决方案到公共云平台提供的服务。一旦建立好了以后,Terraform可以让运维人员安全又高效地改变你的基础设施,就如同配置一样。

Terraform.io的创始者工作在一个Devops模式的公司,他找到了一个窍门把建立一个完整的数据中心所需的知识结合在一起,可以从添加服务器到支持网络服务的功能齐备的数据中心。基础设施的描述采用高级的配置语法,允许你把数据中心的蓝图按版本管理,并且转换成多种代码。著名开源公司HashiCorp赞助开发这个项目。

荣誉奖: Docker Fig






Drone 是一个基于Docker的持续集成平台,而且它是用Go语言写的。Drone项目不满于现存的设置开发环境的技术和流程。

Drone提供了一个简单的自动测试和持续交付的方法:简单选择一个Docker镜像来满足你的需求,连接并提交至GitHub即可。Drone使用Docker容器来提供隔离的测试环境,让每个项目完全自主控制它的环境,没有传统的服务器管理的负担。Drone背后的100位社区贡献者强烈希望把这个项目带到企业和移动应用程序开发中。

开源新秀





 
作者: Black Duck Software
Linux中国|译者: sevenot 查看全部
黑鸭(Black Duck)软件公布了一份名叫“年度开源项目新秀”的报告,介绍了由全球开源协会发起的10个最有趣、最活跃的新项目。

1.jpg


年度开源项目新秀

每年都有上千新的开源项目问世,但只有少数能够真正的吸引我们的关注。一些项目因为利用了当前比较流行的技术而发展壮大,有一些则真正地开启了一个新的领域。很多开源项目建立的初衷是为了解决一些生产上的问题,还有一些项目则是世界各地志同道合的开发者们共同发起的一个宏伟项目。

从2009年起,开源软件管理公司黑鸭便发起了 年度开源项目新秀 这一活动,它的评选根据 Open Hub 网站(即以前的Ohloh)上的活跃度。今年,我们很荣幸能够报道2015年10大开源项目新秀的得主和2名荣誉奖得主,它们是从上千个开源项目中脱颖而出的。评选采用了加权评分系统,得分标准基于项目的活跃度,交付速度和几个其它因数。

开源俨然成为了产业创新的引擎,就拿今年来说,和Docker容器相关的开源项目在全球各地兴起,这也不恰巧反映了企业最感兴趣的技术领域吗?最后,我们接下来介绍的项目,将会让你了解到全球开源项目的开发者们的在思考什么,这很快将会成为一个指引我们发展的领头羊。

2015年度开源项目新秀: DebOps

2.jpg


DebOps 收集打包了一套 Ansible 方案和规则(Ansible是一种自动化运维工具),可以从1个容器扩展到一个完整的数据中心。它的创始人Maciej Delmanowski将DebOps开源来保证项目长久进行,从而更好的通过外部贡献者的帮助发展下去。

DebOps始创于波兰的一个不起眼大学校园里,他们运营自己的数据中心,一切工作都采用手工配置。有时系统崩溃而导致几天的宕机,这时Delmanowski意识到一个配置管理系统是很有必要的。以Debian作为基础开始,DebOps是一组配置一整个数据基础设施的Ansible方案。此项目已经在许多不同的工作环境下实现,而创始者们则打算继续支持和改进这个项目。

2015年度开源项目新秀: Code Combat

3.jpg


传统的纸笔学习方法已近不能满足技术学科了。然而游戏却有很多人都爱玩,这也就是为什么 CodeCombat 的创始人会去开发一款多人协同编程游戏来教人们如何编码。

刚开始CodeCombat是一个创业想法,但其创始人决定取而代之创建一个开源项目。此想法在社区传播开来,很快不少贡献者加入到项目中来。项目发起仅仅两个月后,这款游戏就被接纳到Google’s Summer of Code活动中。这款游戏吸引了大量玩家,并被翻译成45种语言。CodeCombat希望成为那些想要一边学习代码同时获得乐趣的同学的风向标。

2015年度开源项目新秀: Storj

4.jpg


Storj 是一个点对点的云存储网络,可实现端到端加密,保证用户不用依赖第三方即可传输和共享数据。基于比特币block chain技术和点对点协议,Storj提供安全、私密、加密的云存储。

云数据存储的反对者担心成本开销和漏洞攻击。针对这两个担忧,Storj提供了一个私有云存储市场,用户可以通过Storjcoin X(SJCX) 购买交易存储空间。上传到Storj的文件会被粉碎、加密和存储到整个社区。只有文件所有者拥有密钥加密的信息。

在2014年举办的Texas Bitcoin Conference Hackathon会议上,去中心化的云存储市场概念首次被提出并证明可行。在第一次赢得黑客马拉松活动后,项目创始人们和领导团队利用开放论坛、Reddit、比特币论坛和社交媒体增长成了一个活跃的社区,如今,它们已成为影响Storj发展方向的一个重要组成部分。

2015年度开源项目新秀: Neovim

5.jpg

 
自1991年出现以来,Vim已经成为数以百万计软件开发人员所钟爱的文本编辑器。 而 Neovim 就是它的下一个版本。

在过去的23年里,软件开发生态系统经历了无数增长和创新。Neovim创始人Thiago de Arruda认为Vim缺乏当代元素,跟不上时代的发展。在保留Vim的招牌功能的前提下,Neovim团队同样在寻求改进和发展这个最受欢迎的文本编辑器的技术。早期众筹让Thiago de Arruda可以连续6个月时间投入到此项目。他相信Neovim社区会支持这个项目,激励他继续开发Neovim。

2015年度开源项目新秀: CockroachDB

6.jpg


前谷歌员工开发了一个开源的大型企业数据存储项目 CockroachDB ,它是一个可扩展的、跨地域复制且支持事务的数据存储的解决方案。

为了保证在线的百万兆字节流量业务的质量,Google开发了Spanner系统,这是一个可扩展的,稳定的,支持事务的系统。许多参与开发CockroachDB的团队现在都服务于开源社区。就像真正的蟑螂(cockroach)一样,CockroachDB可以在没有数据头、任意节点失效的情况下正常运行。这个开源项目有很多富有经验的贡献者,创始人们通过社交媒体、Github、网络、会议和聚会结识他们并鼓励他们参与其中。
 
2015年度开源项目新秀: Kubernetes

7.jpg


在将容器化软件到引入开源社区发展时, Docker 是一匹黑马,它创新了一套技术和工具。去年6月谷歌推出了 Kubernetes ,这是一款开源的容器管理工具,用来加快开发和简化操作。

谷歌在它的内部运营上使用容器技术多年了。在2014年夏天的DockerCon上大会上,谷歌这个互联网巨头开源了Kubernetes,Kubernetes的开发是为了满足迅速增长的Docker生态系统的需要。通过和其它的组织、项目合作,比如Red Hat和CoreOS,Kubernetes项目的管理者们推动它登上了Docker Hub的工具下载榜榜首。Kubernetes的开发团队希望扩大这个项目,发展它的社区,这样的话软件开发者就能花更少的时间在管理基础设施上,而更多的去开发他们自己的APP。

2015年度开源项目新秀: Open Bazaar

8.jpg

OpenBazaar是一个使用比特币与其他人交易的去中心化的市场。OpenBazaar这一概念最早在编程马拉松(hackathon)活动中被提出,它的创始人结合了BitTorent、比特币和传统的金融服务方式,创造了一个不受审查的交易平台。OpenBazaar的开发团队在寻求新的成员,而且不久以后他们将极度扩大Open Bazaar社区。Open Bazaar的核心是透明度,其创始人和贡献者的共同目标是在商务交易中掀起一场革命,让他们向着一个真实的、一个无控制的,去中心化的市场奋进。

2015年度开源项目新秀: IPFS

9.jpg

 
IPFS 是一个面向全球的、点对点的分布式版本文件系统。它综合了Git,BitTorrent,HTTP的思想,开启了一个新的数据和数据结构传输协议。

人们所知的开源,它的本意用简单的方法解决复杂的问题,这样产生许多新颖的想法,但是那些强大的项目仅仅是开源社区的冰山一角。IFPS有一个非常激进的团队,这个概念的提出是大胆的,令人惊讶的,有点甚至高不可攀。看起来,一个点对点的分布式文件系统是在寻求将所有的计算设备连在一起。这个可能的 HTTP 替换品通过多种渠道维护着一个社区,包括Git社区和超过100名贡献者的IRC。这个疯狂的想法将在2015年进行软件内部测试。

2015年度开源项目新秀: cAdvisor

10.jpg


cAdvisor (Container Advisor) 是一个针对在运行中的容器进行收集,统计,处理和输出信息的工具,它可以给容器的使用者提供资源的使用情况和工作特性。对于每一个容器,cAdvisor记录着资源的隔离参数,资源使用历史,资源使用历史对比框图,网络状态。这些从容器输出的数据跨越主机传递。

cAdvisor可以在绝大多数的Linux发行版上运行,并且支持包括Docker在内的多种容器类型。事实上它成为了一种容器的代理,并被集成在了很多系统中。cAdvisor在DockerHub下载量也是位居前茅。cAdvisor的开发团队希望把cAdvisor改进到能够更深入地理解应用性能,并且集成到集群系统。

2015年度开源项目新秀: Terraform

11.jpg

Terraform 提供了一些常见设置来创建一个基础设施,从物理机到虚拟机,以及email服务器、DNS服务器等。这个想法包括从家庭个人机解决方案到公共云平台提供的服务。一旦建立好了以后,Terraform可以让运维人员安全又高效地改变你的基础设施,就如同配置一样。

Terraform.io的创始者工作在一个Devops模式的公司,他找到了一个窍门把建立一个完整的数据中心所需的知识结合在一起,可以从添加服务器到支持网络服务的功能齐备的数据中心。基础设施的描述采用高级的配置语法,允许你把数据中心的蓝图按版本管理,并且转换成多种代码。著名开源公司HashiCorp赞助开发这个项目。

荣誉奖: Docker Fig

12.jpg


Drone 是一个基于Docker的持续集成平台,而且它是用Go语言写的。Drone项目不满于现存的设置开发环境的技术和流程。

Drone提供了一个简单的自动测试和持续交付的方法:简单选择一个Docker镜像来满足你的需求,连接并提交至GitHub即可。Drone使用Docker容器来提供隔离的测试环境,让每个项目完全自主控制它的环境,没有传统的服务器管理的负担。Drone背后的100位社区贡献者强烈希望把这个项目带到企业和移动应用程序开发中。

开源新秀

13.jpg

 
作者: Black Duck Software
Linux中国|译者: sevenot
0
评论

环信CEO:“即时通讯云+移动客服”为App打造用户体验闭环 环信 移动开发 IM

oscar 发表了文章 • 1124 次浏览 • 2015-07-06 14:52 • 来自相关话题

 
随着移动互联网的发展,即时通讯、移动客服已经成为了很多移动应用的必备功能,环信作为新晋移动即时通讯PaaS平台服务商,凭借着近期刚刚上线的跨平台移动端客服产品吸引了大量应用开发者的关注。为了进一步了解移动客服产品的发展现状,InfoQ专门对环信联合创始人及CEO刘俊彦进行了专访。
 
InfoQ:环信成立已经有两年的时间,能聊一下这两年环信的整体发展吗?
 刘俊彦:环信在2013年4月成立,2014年6月第一个产品”环信即时通讯云”正式上线。然后在今年4月份上线了移动客服产品。在过去的一年里面,环信做了三轮融资,分别是去年5月份的天使轮,去年8月份的A轮,和去年10月份的A+轮。截止到今年5月底,一共有23000款APP在使用环信即时通讯云SDK。环信的SDK覆盖了2.5亿的终端用户,环信即时通讯平台日活是千万级别,每天处理将近两亿条消息。这就是环信过去两年大概的情况。InfoQ:移动客服可以算是现在移动应用通讯领域的一个刚性需求了,您能否谈一谈移动客服的形式都有哪些?刘俊彦:虽然移动客服是一种移动互联网时代的新产品,但其实也只是形式上的一个创新。基本上每一个APP的设置页面都会有一个“意见反馈”的功能。其实这个功能就是一个客服功能,只是受限于技术、资源等因素,需要以表单的形式来呈现,有的时候还需要用户选择类别、提交联系方式,很难做到实时更新。

最近这一年,随着移动电商、O2O,在线教育,在线旅游,互联网金融产品的发展,出现了很多形式的客服产品。比如:作为电商,做O2O一定要做售前、售中、售后。这个过程中就涉及到用户与商家的沟通。

常见的沟通形式有4种,第一种是在App里面提供一个按钮,用户点击该按钮直接跳转到QQ,然后通过QQ去完成与商家的交流。

第二种是通过链接跳转微信。第三种形式就是我们最开始提到的表单形式,这种形式是非实时的。

最新的一种形式是用即时通讯的方法来跟商家沟通。用户打开一个窗口,在该窗口可以发语音、图片、文字,可以跟商家进行实时互动,这种形式就类似与微信、旺旺。第四种形式是最受大家欢迎,受O2O的商家、电商、医疗、互联网金融认可度最高的的一种客服形式,这种形式非常有利于用户通过手机与商家进行沟通。

InfoQ:针对这种移动客服的形式,存在哪些技术难点?环信是怎样客服这些难点的?刘俊彦:用IM来做客服虽然很方便,但它的技术门槛比较高。第一需要你的服务器能够做到千万级、亿级的并发处理。移动客服是基于IM的长连接技术实现的。举个例子,如果某个App有100万日活用户,那么用户的手机和客服服务器之间就存在一百万条长连接。一些大型的App可能会有几百万、几千万的日活用户,那么提供服务的厂家就需要支持几百万、几千万的用户长连接。如果你的平台要支持上几百家厂商,那么平台就需要有支持几千万到几亿用户同时连接的能力。

第二需要做到不丢消息,并且每一条消息能够做到最实时的到达。即时通讯服务是帮助商家来进行销售的,用户可能是在三线城市,也可能是在四线城市,网络环境可能是2G、3G或4G。要做到任何情况下,只要有网络,消息一定能够即时到达是非常困难的。但如果你的平台做不到,就会给商家带来损失。拿电商来举例:一个消费者想买一样东西,发了一条咨询消息,但这个消息丢失了,那么就意味着这个单子丢了。这个用户可能是商家花了很多钱,从其它平台导流过来的,但是因为一条咨询没有即时收到,结果流失了,这样就给商家带来了损失。

环信对于移动客服的技术已经非常成熟,因为环信从去年6月1日正式上线,做的就是即时通讯云。我们在即时通讯云这一块已经做到了全国有2.3万家APP使用,有2.5亿用户,平台的日活用户是几千万。两年多的技术储备让我们敢保证绝对不丢消息,并且消息能够非常实时的到达。

InfoQ:因为领域的不同导致用户流量分布特点也不同,所以说即时通讯服务里面会经常产生波峰波谷。能不能谈一谈环信在这个弹性方面的具体措施呢?刘俊彦:解决该问题要从技术与非技术两方面着手。非技术其实就只能靠烧钱来解决。我们系统上大概有50%的余量,超过50%的压力之后,就开始加服务器。这样能保证系统在不到50%冗余的情况下运行。当然这也意味着有50%的容量浪费,其实这个“浪费”是应付一些不可预料的波峰和波谷。单个APP的用户行为基本是固定的。社交类APP,大概在晚上十点半会产生波峰。而有一些企业办公类、教育类App是在白天产生波峰。我们为两万多家APP提供服务,综合起来整个波峰和波谷就会比较平均一些。

我们也采取了一些技术手段来解决该问题。现在有一些云服务平台提供秒级计算API。当到半夜两点钟,所有APP都进入波谷后,我们就会调用API释放掉一批服务器。但这样带来的经济效益也不高,因为秒级API走的是另外一套收费体系。

InfoQ:环信开放了UI源码,现在用户可以深度定制应用的UI。环信还建立了自己的开源社区,能不能谈一谈环信在开源方面有什么样的规划?是否考虑给开发者开放更灵活的API,或者是直接开源一些核心技术?刘俊彦:环信的四位创始人有三位都是长期在开源社区工作的。而我从03年以后,基本上没有做过商业软件。所以开源精神已经深深植入到每一位创始人。

除了UI开源之外,我们还建了一个自己的开源社区。在过去的两年里,我们看到了一个很有意思的现象。很多人用环信来做社交,有单聊、群聊、匿名群聊等等各种玩法。但是归纳之后,大概可分为几十种。所以我们希望通过社区的力量,把这几十种常见的社交模块做出来,然后用开源的形式提供给大家。当用户想要做一款新的社交APP时,基于环信这样的底层云服务模块,有可能会节约几个月的时间。

有了上面的基础,我们就想走的更远一点。当你想做一款APP的时候,你可能用到一个朋友圈的功能,用到一个匿名的功能,我们希望这些功能也变成一个现成的模块,甚至整个APP都能够以开源的形式完整呈现。这样大家在开发一款APP的时候,就像是搭积木,选不同的积木模块,然后把他们拼起来。特别是对于创业者,可以把更多的时间用于提升用户体验。

最近这一个月我们开放了三个应用级别的模块:第一个是凡信,它是高仿微信的一款APP。凡信实现了单聊、群聊、朋友群等功能。这是我们社区里一个网友开发的,他完全无私的把服务器端和客服端代码开源出来。第二个是一个类似于陌陌的陌生人交友APP,功能主要是看附近的人,看到附近的人之后可以跟他聊天。第三个是我们面向企业的开源产品。上面提到的开源项目大家都可以到我们的社区下载,当然你也可以成为这些项目的贡献者,一起来推动这些产品往前走。

InfoQ:最近IT行业内数据中心机房出的问题也很多,环信在异地多活这方面有什么样的规划吗?刘俊彦:到现在为止,环信的云服务都托管在国内最一流的云服务平台上。按照他们的星级来说,都是最顶尖的机房,可靠性、安全性都是有保证的。但为了给大家提供更可靠、更放心的云服务,“异地多活”已经列入了我们的开发计划,未来的几个月环信的“异地多活”就会正式上线。InfoQ:最近有消息说环信要开始新一轮的融资,您能不能谈一谈环信在短期内的发展计划呢?刘俊彦:刚刚我提到过环信在过去一年里进行了三轮融资。我们目前其实正在做B轮融资,因为还在进行中,如果有更多的细节我会尽快告诉大家。

环信发展到现在已成规模,下一步我们会继续巩固环信在“即时通讯云”领域国内第一的位置,我们希望以最低的价格、最好的服务为做社交以及各种应用服务者提供即时通讯功能。其次我们在今年4月份上线了环信移动客服产品。移动客服是我们在即时通讯领域一个很大的扩展。在即时通讯领域有两种场景,一种是在APP里面用户和用户之间进行社交活动,另一种是用户与商家之间的聊天,也就是客服。我们一直认为任何一款APP,都需要即时通讯,那么要达到100%的覆盖,光做社交是无法实现的,所以我们要加上客服这一块。我们最终的愿景是用环信的力量和技术为每一款APP提供即时通讯功能。

  查看全部

ban9.png

 
随着移动互联网的发展,即时通讯、移动客服已经成为了很多移动应用的必备功能,环信作为新晋移动即时通讯PaaS平台服务商,凭借着近期刚刚上线的跨平台移动端客服产品吸引了大量应用开发者的关注。为了进一步了解移动客服产品的发展现状,InfoQ专门对环信联合创始人及CEO刘俊彦进行了专访。
 
InfoQ:环信成立已经有两年的时间,能聊一下这两年环信的整体发展吗?
 
刘俊彦:环信在2013年4月成立,2014年6月第一个产品”环信即时通讯云”正式上线。然后在今年4月份上线了移动客服产品。在过去的一年里面,环信做了三轮融资,分别是去年5月份的天使轮,去年8月份的A轮,和去年10月份的A+轮。截止到今年5月底,一共有23000款APP在使用环信即时通讯云SDK。环信的SDK覆盖了2.5亿的终端用户,环信即时通讯平台日活是千万级别,每天处理将近两亿条消息。这就是环信过去两年大概的情况。
InfoQ:移动客服可以算是现在移动应用通讯领域的一个刚性需求了,您能否谈一谈移动客服的形式都有哪些?
刘俊彦:虽然移动客服是一种移动互联网时代的新产品,但其实也只是形式上的一个创新。基本上每一个APP的设置页面都会有一个“意见反馈”的功能。其实这个功能就是一个客服功能,只是受限于技术、资源等因素,需要以表单的形式来呈现,有的时候还需要用户选择类别、提交联系方式,很难做到实时更新。

最近这一年,随着移动电商、O2O,在线教育,在线旅游,互联网金融产品的发展,出现了很多形式的客服产品。比如:作为电商,做O2O一定要做售前、售中、售后。这个过程中就涉及到用户与商家的沟通。

常见的沟通形式有4种,第一种是在App里面提供一个按钮,用户点击该按钮直接跳转到QQ,然后通过QQ去完成与商家的交流。

第二种是通过链接跳转微信。第三种形式就是我们最开始提到的表单形式,这种形式是非实时的。

最新的一种形式是用即时通讯的方法来跟商家沟通。用户打开一个窗口,在该窗口可以发语音、图片、文字,可以跟商家进行实时互动,这种形式就类似与微信、旺旺。第四种形式是最受大家欢迎,受O2O的商家、电商、医疗、互联网金融认可度最高的的一种客服形式,这种形式非常有利于用户通过手机与商家进行沟通。

InfoQ:针对这种移动客服的形式,存在哪些技术难点?环信是怎样客服这些难点的?
刘俊彦:用IM来做客服虽然很方便,但它的技术门槛比较高。第一需要你的服务器能够做到千万级、亿级的并发处理。移动客服是基于IM的长连接技术实现的。举个例子,如果某个App有100万日活用户,那么用户的手机和客服服务器之间就存在一百万条长连接。一些大型的App可能会有几百万、几千万的日活用户,那么提供服务的厂家就需要支持几百万、几千万的用户长连接。如果你的平台要支持上几百家厂商,那么平台就需要有支持几千万到几亿用户同时连接的能力。

第二需要做到不丢消息,并且每一条消息能够做到最实时的到达。即时通讯服务是帮助商家来进行销售的,用户可能是在三线城市,也可能是在四线城市,网络环境可能是2G、3G或4G。要做到任何情况下,只要有网络,消息一定能够即时到达是非常困难的。但如果你的平台做不到,就会给商家带来损失。拿电商来举例:一个消费者想买一样东西,发了一条咨询消息,但这个消息丢失了,那么就意味着这个单子丢了。这个用户可能是商家花了很多钱,从其它平台导流过来的,但是因为一条咨询没有即时收到,结果流失了,这样就给商家带来了损失。

环信对于移动客服的技术已经非常成熟,因为环信从去年6月1日正式上线,做的就是即时通讯云。我们在即时通讯云这一块已经做到了全国有2.3万家APP使用,有2.5亿用户,平台的日活用户是几千万。两年多的技术储备让我们敢保证绝对不丢消息,并且消息能够非常实时的到达。

InfoQ:因为领域的不同导致用户流量分布特点也不同,所以说即时通讯服务里面会经常产生波峰波谷。能不能谈一谈环信在这个弹性方面的具体措施呢?
刘俊彦:解决该问题要从技术与非技术两方面着手。非技术其实就只能靠烧钱来解决。我们系统上大概有50%的余量,超过50%的压力之后,就开始加服务器。这样能保证系统在不到50%冗余的情况下运行。当然这也意味着有50%的容量浪费,其实这个“浪费”是应付一些不可预料的波峰和波谷。单个APP的用户行为基本是固定的。社交类APP,大概在晚上十点半会产生波峰。而有一些企业办公类、教育类App是在白天产生波峰。我们为两万多家APP提供服务,综合起来整个波峰和波谷就会比较平均一些。

我们也采取了一些技术手段来解决该问题。现在有一些云服务平台提供秒级计算API。当到半夜两点钟,所有APP都进入波谷后,我们就会调用API释放掉一批服务器。但这样带来的经济效益也不高,因为秒级API走的是另外一套收费体系。

InfoQ:环信开放了UI源码,现在用户可以深度定制应用的UI。环信还建立了自己的开源社区,能不能谈一谈环信在开源方面有什么样的规划?是否考虑给开发者开放更灵活的API,或者是直接开源一些核心技术?
刘俊彦:环信的四位创始人有三位都是长期在开源社区工作的。而我从03年以后,基本上没有做过商业软件。所以开源精神已经深深植入到每一位创始人。

除了UI开源之外,我们还建了一个自己的开源社区。在过去的两年里,我们看到了一个很有意思的现象。很多人用环信来做社交,有单聊、群聊、匿名群聊等等各种玩法。但是归纳之后,大概可分为几十种。所以我们希望通过社区的力量,把这几十种常见的社交模块做出来,然后用开源的形式提供给大家。当用户想要做一款新的社交APP时,基于环信这样的底层云服务模块,有可能会节约几个月的时间。

有了上面的基础,我们就想走的更远一点。当你想做一款APP的时候,你可能用到一个朋友圈的功能,用到一个匿名的功能,我们希望这些功能也变成一个现成的模块,甚至整个APP都能够以开源的形式完整呈现。这样大家在开发一款APP的时候,就像是搭积木,选不同的积木模块,然后把他们拼起来。特别是对于创业者,可以把更多的时间用于提升用户体验。

最近这一个月我们开放了三个应用级别的模块:第一个是凡信,它是高仿微信的一款APP。凡信实现了单聊、群聊、朋友群等功能。这是我们社区里一个网友开发的,他完全无私的把服务器端和客服端代码开源出来。第二个是一个类似于陌陌的陌生人交友APP,功能主要是看附近的人,看到附近的人之后可以跟他聊天。第三个是我们面向企业的开源产品。上面提到的开源项目大家都可以到我们的社区下载,当然你也可以成为这些项目的贡献者,一起来推动这些产品往前走。

InfoQ:最近IT行业内数据中心机房出的问题也很多,环信在异地多活这方面有什么样的规划吗?
刘俊彦:到现在为止,环信的云服务都托管在国内最一流的云服务平台上。按照他们的星级来说,都是最顶尖的机房,可靠性、安全性都是有保证的。但为了给大家提供更可靠、更放心的云服务,“异地多活”已经列入了我们的开发计划,未来的几个月环信的“异地多活”就会正式上线。
InfoQ:最近有消息说环信要开始新一轮的融资,您能不能谈一谈环信在短期内的发展计划呢?
刘俊彦:刚刚我提到过环信在过去一年里进行了三轮融资。我们目前其实正在做B轮融资,因为还在进行中,如果有更多的细节我会尽快告诉大家。

环信发展到现在已成规模,下一步我们会继续巩固环信在“即时通讯云”领域国内第一的位置,我们希望以最低的价格、最好的服务为做社交以及各种应用服务者提供即时通讯功能。其次我们在今年4月份上线了环信移动客服产品。移动客服是我们在即时通讯领域一个很大的扩展。在即时通讯领域有两种场景,一种是在APP里面用户和用户之间进行社交活动,另一种是用户与商家之间的聊天,也就是客服。我们一直认为任何一款APP,都需要即时通讯,那么要达到100%的覆盖,光做社交是无法实现的,所以我们要加上客服这一块。我们最终的愿景是用环信的力量和技术为每一款APP提供即时通讯功能。

 
2
回复

【环信官方外包一个项目】利用环信IM实现一个在线白板 环信

KevinGong 回复了问题 • 3 人关注 • 734 次浏览 • 2017-09-25 17:48 • 来自相关话题

0
评论

【开源项目】一个基于环信IM开发的开源的私密社交APP-Baby 即时通信 Baby

seven。 发表了文章 • 853 次浏览 • 2017-08-31 14:49 • 来自相关话题

Baby这个开源项目基于环信IM开发,刚开始选择IM的时候,看到知乎上黑环信的人挺多的,就亲自下载了几家IM的demo源码跑一遍,从功能、集成难易和消息稳定几个方面对比,最终还是选择了环信。集成这方面环信做的真不错,尤其是有了EaseUi这个包,基本上一天就能集成完毕。项目运行至今没有出现过什么问题,发送消息挺稳定的。先上效果图




开屏页的登录和注册




编辑个人信息




相册页面




首页的Moment
版本更新:
 
version 1.6
加入Tinker 热修复更新部分依赖修复大量细节问题,加入部分注释

version 1.5
bug fixupdate sth

version 1.4
增加长按删除功能优化Rxbus订阅加载数据外国友人优化的一些细节等等

version 1.3
增加了评论功能优化了相册加载修复了一些内存泄漏等等

version 1.2
修复了一些Bug把登陆注册事件换了个Zip操作符更符合流的思想

version 1.1
修复了主页背景无法切换的问题修复了聊天推送的问题修了语音视频的问题做了一些细节修改
Download



安装包下载体验
 
github地址
github源码
 Development Environment & Library
 
MVP

这个项目是基于MVP框架写的(大体上,聊天那块直接用环信的了),大部分Base类参考FastAndroid里边的基类,参考这个很快就能布好基本的MVP架构。本来是有考虑过MVVM后来想想还是先学习一下MVP吧,看过几个MVVM项目感觉还是挺好用的,不过还是BETA版不知道有没有什么坑。

Material Design

早就手痒想体验一把V7包里边的各种控件了,特喜欢coordinatorlayout和collapsingtoolbarlayout的互动让Tollbar隐藏又现的感觉,但是看起来好看还是要点代价的,在这里捣鼓了不少时间,尤其是collapsingtoolbarlayout的Expanded固定让我Google了好久,因为用英文搜索可能我表达的不太好,最后竟然是一句nestedScroll(false)就可以了。。。。 还是感谢Stackoveflow里边的大腿吧。

Dagger2

依赖注入Dagger2,也是我早就想用的一个框架了,理由是各种配合Mvp十分方便和好用,渐渐也能体会到一次注入到处可用的快感。不过一个新技术真的学习成本,国内没什么中文文档介绍,看国外的看的云里雾里。原理看的明白,用起来好像不太知道如何使用,尤其是在@inject之后对象,也可以在别的地方Inject,原本是被Inject方后来也成了Module提供方。虽然到最后原理还不是特别明白这里,但还是不阻碍用起来的快感。

Realm

一开始被新技术吸引到的是不会放过任何新东西的包括Realm,不过进了坑不代表这个坑可以跳阿。由于我这次用到了leacncloud,Realm感觉会和LeanCloud的子类化冲突让你只能选择其中之一,不过这个也算了,Leancloud提供了类似Map的Put方法也可以接受就是麻烦了点。但是被坑到的地方是Realm所谓的自动数据同步竟然是一改就是改真实的数据,并不是数据的拷贝。。。感觉和我使用到要缓存的数据有点冲突,因为这个Moment里边的项是有点赞的,点赞要修改当前Recycleview的数据(修改数据要开事务)。修改数据后会出现一些很奇怪的现象,不在Recycleview当前Item会跳到当前Item,点赞的动画也会消失。。。真的是想破脑袋也解决不了,就直接跳坑了。最后感觉这个Realm在保存不跟服务器需要同步的数据会好点。

LeanCloud

用LeanCloud是因为在知乎太多吹它的人了而且它的确在BAAS这方面功能比较多(后来才发现即时通信没有语音和视频),所以就尝试使用了,SDK整体来说是不错的都挺好用的,满足了我对存储方面的要求。不过就在我开发的这几天,貌似稳定性没有想象中那么好,好几次上传个头像都会SocketTimeOut,查询也会有点慢,不过还好都在接受范围内(不过要是到了收费的标准我就接受不了)。

环信

baby这个开源项目基于环信IM开发,刚开始选择IM的时候,看到知乎上黑环信的人挺多的,就亲自下载了几家IM的demo源码跑一遍,从功能、集成难易和消息稳定几个方面对比,最终还是选择了环信。集成这方面环信做的真不错,尤其是有了EaseUi这个包,基本上一天就能集成完毕。项目运行至今没有出现过什么问题,发送消息挺稳定的。

Rxjava、RxAndroid

Rxjava我从第一眼看到了就喜欢上了(个人特喜欢那种通过.设置完成的感觉),接触也有几个月,一开始就和Retrofit 、Okhttp一起使用。学习成本还是要有的阿,看了不知道多少篇关于Rxjava使用的文章和例子,对里边的操作符也仅仅停留在那几个最常用的,其他一大堆好多都没用过,看来还用得不够。

Glide

Glide也是一个后来居上让我喜欢的图片加载库,一开始我喜欢picasso 是觉得轻巧而且好用有保证(主要是我偶像Jake Wharton主导,有加成),慢慢觉得Picasso对内存没有Glide来的友好,Glide在加载速度方面也领先,虽然整个库代码量是Picasso的几倍,但是比起重要的内存和用户体验来说还是Glide的领先一筹。

Butterknife、Ucrop等等

当让还有其他的一些润色的轮子啦,不过不是那么重要就不一一感谢啦。

Thanks
感谢Github、LeanCloud、环信、还有造那么多轮子给我们用的Square FaceBook Google的大大们。Thanks for improving my code m-ezzat.

Contacts
Email:379489343zhi@gmail.comQQ:379489343
 Copyright 2016 Roger ou

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. 查看全部
   Baby这个开源项目基于环信IM开发,刚开始选择IM的时候,看到知乎上黑环信的人挺多的,就亲自下载了几家IM的demo源码跑一遍,从功能、集成难易和消息稳定几个方面对比,最终还是选择了环信。集成这方面环信做的真不错,尤其是有了EaseUi这个包,基本上一天就能集成完毕。项目运行至今没有出现过什么问题,发送消息挺稳定的。
先上效果图

003.png

开屏页的登录和注册


001.png

编辑个人信息


002.png

相册页面


004.png

首页的Moment


版本更新:
 
version 1.6
  1. 加入Tinker 热修复
  2. 更新部分依赖
  3. 修复大量细节问题,加入部分注释


version 1.5
  1. bug fix
  2. update sth


version 1.4
  1. 增加长按删除功能
  2. 优化Rxbus订阅加载数据
  3. 外国友人优化的一些细节
  4. 等等


version 1.3
  1. 增加了评论功能
  2. 优化了相册加载
  3. 修复了一些内存泄漏
  4. 等等


version 1.2
  1. 修复了一些Bug
  2. 把登陆注册事件换了个Zip操作符更符合流的思想


version 1.1
  1. 修复了主页背景无法切换的问题
  2. 修复了聊天推送的问题
  3. 修了语音视频的问题
  4. 做了一些细节修改

Download

 
github地址

 Development Environment & Library
 
MVP

这个项目是基于MVP框架写的(大体上,聊天那块直接用环信的了),大部分Base类参考FastAndroid里边的基类,参考这个很快就能布好基本的MVP架构。本来是有考虑过MVVM后来想想还是先学习一下MVP吧,看过几个MVVM项目感觉还是挺好用的,不过还是BETA版不知道有没有什么坑。

Material Design

早就手痒想体验一把V7包里边的各种控件了,特喜欢coordinatorlayout和collapsingtoolbarlayout的互动让Tollbar隐藏又现的感觉,但是看起来好看还是要点代价的,在这里捣鼓了不少时间,尤其是collapsingtoolbarlayout的Expanded固定让我Google了好久,因为用英文搜索可能我表达的不太好,最后竟然是一句nestedScroll(false)就可以了。。。。 还是感谢Stackoveflow里边的大腿吧。

Dagger2

依赖注入Dagger2,也是我早就想用的一个框架了,理由是各种配合Mvp十分方便和好用,渐渐也能体会到一次注入到处可用的快感。不过一个新技术真的学习成本,国内没什么中文文档介绍,看国外的看的云里雾里。原理看的明白,用起来好像不太知道如何使用,尤其是在@inject之后对象,也可以在别的地方Inject,原本是被Inject方后来也成了Module提供方。虽然到最后原理还不是特别明白这里,但还是不阻碍用起来的快感。

Realm

一开始被新技术吸引到的是不会放过任何新东西的包括Realm,不过进了坑不代表这个坑可以跳阿。由于我这次用到了leacncloud,Realm感觉会和LeanCloud的子类化冲突让你只能选择其中之一,不过这个也算了,Leancloud提供了类似Map的Put方法也可以接受就是麻烦了点。但是被坑到的地方是Realm所谓的自动数据同步竟然是一改就是改真实的数据,并不是数据的拷贝。。。感觉和我使用到要缓存的数据有点冲突,因为这个Moment里边的项是有点赞的,点赞要修改当前Recycleview的数据(修改数据要开事务)。修改数据后会出现一些很奇怪的现象,不在Recycleview当前Item会跳到当前Item,点赞的动画也会消失。。。真的是想破脑袋也解决不了,就直接跳坑了。最后感觉这个Realm在保存不跟服务器需要同步的数据会好点。

LeanCloud

用LeanCloud是因为在知乎太多吹它的人了而且它的确在BAAS这方面功能比较多(后来才发现即时通信没有语音和视频),所以就尝试使用了,SDK整体来说是不错的都挺好用的,满足了我对存储方面的要求。不过就在我开发的这几天,貌似稳定性没有想象中那么好,好几次上传个头像都会SocketTimeOut,查询也会有点慢,不过还好都在接受范围内(不过要是到了收费的标准我就接受不了)。

环信

baby这个开源项目基于环信IM开发,刚开始选择IM的时候,看到知乎上黑环信的人挺多的,就亲自下载了几家IM的demo源码跑一遍,从功能、集成难易和消息稳定几个方面对比,最终还是选择了环信。集成这方面环信做的真不错,尤其是有了EaseUi这个包,基本上一天就能集成完毕。项目运行至今没有出现过什么问题,发送消息挺稳定的。

Rxjava、RxAndroid

Rxjava我从第一眼看到了就喜欢上了(个人特喜欢那种通过.设置完成的感觉),接触也有几个月,一开始就和Retrofit 、Okhttp一起使用。学习成本还是要有的阿,看了不知道多少篇关于Rxjava使用的文章和例子,对里边的操作符也仅仅停留在那几个最常用的,其他一大堆好多都没用过,看来还用得不够。

Glide

Glide也是一个后来居上让我喜欢的图片加载库,一开始我喜欢picasso 是觉得轻巧而且好用有保证(主要是我偶像Jake Wharton主导,有加成),慢慢觉得Picasso对内存没有Glide来的友好,Glide在加载速度方面也领先,虽然整个库代码量是Picasso的几倍,但是比起重要的内存和用户体验来说还是Glide的领先一筹。

Butterknife、Ucrop等等

当让还有其他的一些润色的轮子啦,不过不是那么重要就不一一感谢啦。

Thanks
  • 感谢Github、LeanCloud、环信、还有造那么多轮子给我们用的Square FaceBook Google的大大们。
  • Thanks for improving my code m-ezzat.


Contacts

 
Copyright 2016 Roger ou

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
6
评论

【新手快速入门】集成环信常见问题+解决方案汇总 常见问题

dujiepeng 发表了文章 • 6066 次浏览 • 2017-05-22 15:51 • 来自相关话题

   这里整理了集成环信的常见问题和一些功能的实现思路,希望能帮助到大家。感谢热心的开发者贡献,大家在观看过程中有不明白的地方欢迎直接跟帖咨询。
 
ios篇
APNs证书创建和上传到环信后台头像昵称的简述和处理方案音视频离线推送Demo实现环信服务器聊天记录保存多久?离线收不到好友请求IOS中环信聊天窗口如何实现文件发送和预览的功能ios集成常见问题环信推送的一些常见问题实现名片|红包|话题聊天室等自定义cell
 
Android篇
环信3.0SDK集成小米推送教程EaseUI库中V4、v7包冲突解决方案Android EaseUI里的百度地图替换为高德地图android扩展消息(名片集成)关于会话列表的置顶聊天java.lang.UnsatisfiedLinkError: 的问题android 端 app 后台被杀死收不到消息的解决方案
昵称头像篇
android中如何显示开发者服务器上的昵称和头像 Android中显示头像(接上一篇文章看)环信(Android)设置头像和昵称的方法(最简单暴力的基于环信demo的集成)IOS中如何显示开发者服务器上的昵称和头像【环信公开课第12期视频回放】-所有关于环信IM昵称头像的问题听这课就够了
 
直播篇
一言不合你就搞个直播APP
 
客服集成
IM-SDK和客服SDK并存开发指南—Android篇IM-SDK和客服SDK并存开发指南—iOS篇
 
开源项目
Android简版demoios简版demo凡信2.0:超仿微信的开源项目 凡信3.0:携直播和红包而来高仿微信:Github 3,515 Star方圆十里:环信编程大赛冠军项目泛聊:定一个小目标写一个QQSlack聊天机器人:一天时间做一个聊天机器人TV视频通话:在电视上视频通话视频通话:Android手机视频通话酷信:ios高仿微信公众号助手:与订阅用户聊天沟通
 
持续更新ing...小伙伴们还有什么想知道欢迎跟帖提出。
  查看全部
   这里整理了集成环信的常见问题和一些功能的实现思路,希望能帮助到大家。感谢热心的开发者贡献,大家在观看过程中有不明白的地方欢迎直接跟帖咨询。
 
ios篇

 
Android篇

昵称头像篇

 
直播篇
  1. 一言不合你就搞个直播APP

 
客服集成
  1. IM-SDK和客服SDK并存开发指南—Android篇
  2. IM-SDK和客服SDK并存开发指南—iOS篇

 
开源项目

 
持续更新ing...小伙伴们还有什么想知道欢迎跟帖提出。
 
2
回复

【环信官方外包一个项目】利用环信IM实现一个在线白板 环信

回复

KevinGong 回复了问题 • 3 人关注 • 734 次浏览 • 2017-09-25 17:48 • 来自相关话题

0
评论

【开源项目】一个基于环信IM开发的开源的私密社交APP-Baby 即时通信 Baby

seven。 发表了文章 • 853 次浏览 • 2017-08-31 14:49 • 来自相关话题

Baby这个开源项目基于环信IM开发,刚开始选择IM的时候,看到知乎上黑环信的人挺多的,就亲自下载了几家IM的demo源码跑一遍,从功能、集成难易和消息稳定几个方面对比,最终还是选择了环信。集成这方面环信做的真不错,尤其是有了EaseUi这个包,基本上一天就能集成完毕。项目运行至今没有出现过什么问题,发送消息挺稳定的。先上效果图




开屏页的登录和注册




编辑个人信息




相册页面




首页的Moment
版本更新:
 
version 1.6
加入Tinker 热修复更新部分依赖修复大量细节问题,加入部分注释

version 1.5
bug fixupdate sth

version 1.4
增加长按删除功能优化Rxbus订阅加载数据外国友人优化的一些细节等等

version 1.3
增加了评论功能优化了相册加载修复了一些内存泄漏等等

version 1.2
修复了一些Bug把登陆注册事件换了个Zip操作符更符合流的思想

version 1.1
修复了主页背景无法切换的问题修复了聊天推送的问题修了语音视频的问题做了一些细节修改
Download



安装包下载体验
 
github地址
github源码
 Development Environment & Library
 
MVP

这个项目是基于MVP框架写的(大体上,聊天那块直接用环信的了),大部分Base类参考FastAndroid里边的基类,参考这个很快就能布好基本的MVP架构。本来是有考虑过MVVM后来想想还是先学习一下MVP吧,看过几个MVVM项目感觉还是挺好用的,不过还是BETA版不知道有没有什么坑。

Material Design

早就手痒想体验一把V7包里边的各种控件了,特喜欢coordinatorlayout和collapsingtoolbarlayout的互动让Tollbar隐藏又现的感觉,但是看起来好看还是要点代价的,在这里捣鼓了不少时间,尤其是collapsingtoolbarlayout的Expanded固定让我Google了好久,因为用英文搜索可能我表达的不太好,最后竟然是一句nestedScroll(false)就可以了。。。。 还是感谢Stackoveflow里边的大腿吧。

Dagger2

依赖注入Dagger2,也是我早就想用的一个框架了,理由是各种配合Mvp十分方便和好用,渐渐也能体会到一次注入到处可用的快感。不过一个新技术真的学习成本,国内没什么中文文档介绍,看国外的看的云里雾里。原理看的明白,用起来好像不太知道如何使用,尤其是在@inject之后对象,也可以在别的地方Inject,原本是被Inject方后来也成了Module提供方。虽然到最后原理还不是特别明白这里,但还是不阻碍用起来的快感。

Realm

一开始被新技术吸引到的是不会放过任何新东西的包括Realm,不过进了坑不代表这个坑可以跳阿。由于我这次用到了leacncloud,Realm感觉会和LeanCloud的子类化冲突让你只能选择其中之一,不过这个也算了,Leancloud提供了类似Map的Put方法也可以接受就是麻烦了点。但是被坑到的地方是Realm所谓的自动数据同步竟然是一改就是改真实的数据,并不是数据的拷贝。。。感觉和我使用到要缓存的数据有点冲突,因为这个Moment里边的项是有点赞的,点赞要修改当前Recycleview的数据(修改数据要开事务)。修改数据后会出现一些很奇怪的现象,不在Recycleview当前Item会跳到当前Item,点赞的动画也会消失。。。真的是想破脑袋也解决不了,就直接跳坑了。最后感觉这个Realm在保存不跟服务器需要同步的数据会好点。

LeanCloud

用LeanCloud是因为在知乎太多吹它的人了而且它的确在BAAS这方面功能比较多(后来才发现即时通信没有语音和视频),所以就尝试使用了,SDK整体来说是不错的都挺好用的,满足了我对存储方面的要求。不过就在我开发的这几天,貌似稳定性没有想象中那么好,好几次上传个头像都会SocketTimeOut,查询也会有点慢,不过还好都在接受范围内(不过要是到了收费的标准我就接受不了)。

环信

baby这个开源项目基于环信IM开发,刚开始选择IM的时候,看到知乎上黑环信的人挺多的,就亲自下载了几家IM的demo源码跑一遍,从功能、集成难易和消息稳定几个方面对比,最终还是选择了环信。集成这方面环信做的真不错,尤其是有了EaseUi这个包,基本上一天就能集成完毕。项目运行至今没有出现过什么问题,发送消息挺稳定的。

Rxjava、RxAndroid

Rxjava我从第一眼看到了就喜欢上了(个人特喜欢那种通过.设置完成的感觉),接触也有几个月,一开始就和Retrofit 、Okhttp一起使用。学习成本还是要有的阿,看了不知道多少篇关于Rxjava使用的文章和例子,对里边的操作符也仅仅停留在那几个最常用的,其他一大堆好多都没用过,看来还用得不够。

Glide

Glide也是一个后来居上让我喜欢的图片加载库,一开始我喜欢picasso 是觉得轻巧而且好用有保证(主要是我偶像Jake Wharton主导,有加成),慢慢觉得Picasso对内存没有Glide来的友好,Glide在加载速度方面也领先,虽然整个库代码量是Picasso的几倍,但是比起重要的内存和用户体验来说还是Glide的领先一筹。

Butterknife、Ucrop等等

当让还有其他的一些润色的轮子啦,不过不是那么重要就不一一感谢啦。

Thanks
感谢Github、LeanCloud、环信、还有造那么多轮子给我们用的Square FaceBook Google的大大们。Thanks for improving my code m-ezzat.

Contacts
Email:379489343zhi@gmail.comQQ:379489343
 Copyright 2016 Roger ou

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. 查看全部
   Baby这个开源项目基于环信IM开发,刚开始选择IM的时候,看到知乎上黑环信的人挺多的,就亲自下载了几家IM的demo源码跑一遍,从功能、集成难易和消息稳定几个方面对比,最终还是选择了环信。集成这方面环信做的真不错,尤其是有了EaseUi这个包,基本上一天就能集成完毕。项目运行至今没有出现过什么问题,发送消息挺稳定的。
先上效果图

003.png

开屏页的登录和注册


001.png

编辑个人信息


002.png

相册页面


004.png

首页的Moment


版本更新:
 
version 1.6
  1. 加入Tinker 热修复
  2. 更新部分依赖
  3. 修复大量细节问题,加入部分注释


version 1.5
  1. bug fix
  2. update sth


version 1.4
  1. 增加长按删除功能
  2. 优化Rxbus订阅加载数据
  3. 外国友人优化的一些细节
  4. 等等


version 1.3
  1. 增加了评论功能
  2. 优化了相册加载
  3. 修复了一些内存泄漏
  4. 等等


version 1.2
  1. 修复了一些Bug
  2. 把登陆注册事件换了个Zip操作符更符合流的思想


version 1.1
  1. 修复了主页背景无法切换的问题
  2. 修复了聊天推送的问题
  3. 修了语音视频的问题
  4. 做了一些细节修改

Download

 
github地址

 Development Environment & Library
 
MVP

这个项目是基于MVP框架写的(大体上,聊天那块直接用环信的了),大部分Base类参考FastAndroid里边的基类,参考这个很快就能布好基本的MVP架构。本来是有考虑过MVVM后来想想还是先学习一下MVP吧,看过几个MVVM项目感觉还是挺好用的,不过还是BETA版不知道有没有什么坑。

Material Design

早就手痒想体验一把V7包里边的各种控件了,特喜欢coordinatorlayout和collapsingtoolbarlayout的互动让Tollbar隐藏又现的感觉,但是看起来好看还是要点代价的,在这里捣鼓了不少时间,尤其是collapsingtoolbarlayout的Expanded固定让我Google了好久,因为用英文搜索可能我表达的不太好,最后竟然是一句nestedScroll(false)就可以了。。。。 还是感谢Stackoveflow里边的大腿吧。

Dagger2

依赖注入Dagger2,也是我早就想用的一个框架了,理由是各种配合Mvp十分方便和好用,渐渐也能体会到一次注入到处可用的快感。不过一个新技术真的学习成本,国内没什么中文文档介绍,看国外的看的云里雾里。原理看的明白,用起来好像不太知道如何使用,尤其是在@inject之后对象,也可以在别的地方Inject,原本是被Inject方后来也成了Module提供方。虽然到最后原理还不是特别明白这里,但还是不阻碍用起来的快感。

Realm

一开始被新技术吸引到的是不会放过任何新东西的包括Realm,不过进了坑不代表这个坑可以跳阿。由于我这次用到了leacncloud,Realm感觉会和LeanCloud的子类化冲突让你只能选择其中之一,不过这个也算了,Leancloud提供了类似Map的Put方法也可以接受就是麻烦了点。但是被坑到的地方是Realm所谓的自动数据同步竟然是一改就是改真实的数据,并不是数据的拷贝。。。感觉和我使用到要缓存的数据有点冲突,因为这个Moment里边的项是有点赞的,点赞要修改当前Recycleview的数据(修改数据要开事务)。修改数据后会出现一些很奇怪的现象,不在Recycleview当前Item会跳到当前Item,点赞的动画也会消失。。。真的是想破脑袋也解决不了,就直接跳坑了。最后感觉这个Realm在保存不跟服务器需要同步的数据会好点。

LeanCloud

用LeanCloud是因为在知乎太多吹它的人了而且它的确在BAAS这方面功能比较多(后来才发现即时通信没有语音和视频),所以就尝试使用了,SDK整体来说是不错的都挺好用的,满足了我对存储方面的要求。不过就在我开发的这几天,貌似稳定性没有想象中那么好,好几次上传个头像都会SocketTimeOut,查询也会有点慢,不过还好都在接受范围内(不过要是到了收费的标准我就接受不了)。

环信

baby这个开源项目基于环信IM开发,刚开始选择IM的时候,看到知乎上黑环信的人挺多的,就亲自下载了几家IM的demo源码跑一遍,从功能、集成难易和消息稳定几个方面对比,最终还是选择了环信。集成这方面环信做的真不错,尤其是有了EaseUi这个包,基本上一天就能集成完毕。项目运行至今没有出现过什么问题,发送消息挺稳定的。

Rxjava、RxAndroid

Rxjava我从第一眼看到了就喜欢上了(个人特喜欢那种通过.设置完成的感觉),接触也有几个月,一开始就和Retrofit 、Okhttp一起使用。学习成本还是要有的阿,看了不知道多少篇关于Rxjava使用的文章和例子,对里边的操作符也仅仅停留在那几个最常用的,其他一大堆好多都没用过,看来还用得不够。

Glide

Glide也是一个后来居上让我喜欢的图片加载库,一开始我喜欢picasso 是觉得轻巧而且好用有保证(主要是我偶像Jake Wharton主导,有加成),慢慢觉得Picasso对内存没有Glide来的友好,Glide在加载速度方面也领先,虽然整个库代码量是Picasso的几倍,但是比起重要的内存和用户体验来说还是Glide的领先一筹。

Butterknife、Ucrop等等

当让还有其他的一些润色的轮子啦,不过不是那么重要就不一一感谢啦。

Thanks
  • 感谢Github、LeanCloud、环信、还有造那么多轮子给我们用的Square FaceBook Google的大大们。
  • Thanks for improving my code m-ezzat.


Contacts

 
Copyright 2016 Roger ou

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
6
评论

【新手快速入门】集成环信常见问题+解决方案汇总 常见问题

dujiepeng 发表了文章 • 6066 次浏览 • 2017-05-22 15:51 • 来自相关话题

   这里整理了集成环信的常见问题和一些功能的实现思路,希望能帮助到大家。感谢热心的开发者贡献,大家在观看过程中有不明白的地方欢迎直接跟帖咨询。
 
ios篇
APNs证书创建和上传到环信后台头像昵称的简述和处理方案音视频离线推送Demo实现环信服务器聊天记录保存多久?离线收不到好友请求IOS中环信聊天窗口如何实现文件发送和预览的功能ios集成常见问题环信推送的一些常见问题实现名片|红包|话题聊天室等自定义cell
 
Android篇
环信3.0SDK集成小米推送教程EaseUI库中V4、v7包冲突解决方案Android EaseUI里的百度地图替换为高德地图android扩展消息(名片集成)关于会话列表的置顶聊天java.lang.UnsatisfiedLinkError: 的问题android 端 app 后台被杀死收不到消息的解决方案
昵称头像篇
android中如何显示开发者服务器上的昵称和头像 Android中显示头像(接上一篇文章看)环信(Android)设置头像和昵称的方法(最简单暴力的基于环信demo的集成)IOS中如何显示开发者服务器上的昵称和头像【环信公开课第12期视频回放】-所有关于环信IM昵称头像的问题听这课就够了
 
直播篇
一言不合你就搞个直播APP
 
客服集成
IM-SDK和客服SDK并存开发指南—Android篇IM-SDK和客服SDK并存开发指南—iOS篇
 
开源项目
Android简版demoios简版demo凡信2.0:超仿微信的开源项目 凡信3.0:携直播和红包而来高仿微信:Github 3,515 Star方圆十里:环信编程大赛冠军项目泛聊:定一个小目标写一个QQSlack聊天机器人:一天时间做一个聊天机器人TV视频通话:在电视上视频通话视频通话:Android手机视频通话酷信:ios高仿微信公众号助手:与订阅用户聊天沟通
 
持续更新ing...小伙伴们还有什么想知道欢迎跟帖提出。
  查看全部
   这里整理了集成环信的常见问题和一些功能的实现思路,希望能帮助到大家。感谢热心的开发者贡献,大家在观看过程中有不明白的地方欢迎直接跟帖咨询。
 
ios篇

 
Android篇

昵称头像篇

 
直播篇
  1. 一言不合你就搞个直播APP

 
客服集成
  1. IM-SDK和客服SDK并存开发指南—Android篇
  2. IM-SDK和客服SDK并存开发指南—iOS篇

 
开源项目

 
持续更新ing...小伙伴们还有什么想知道欢迎跟帖提出。
 
0
回复

我想问2.3.6安卓用字体管家换字体能成功吗? 环信_Android Android 移动开发

回复

正宗猫奴° 发起了问题 • 1 人关注 • 1610 次浏览 • 2015-07-24 15:04 • 来自相关话题

2
回复

【环信官方外包一个项目】利用环信IM实现一个在线白板 环信

回复

KevinGong 回复了问题 • 3 人关注 • 734 次浏览 • 2017-09-25 17:48 • 来自相关话题

0
评论

【开源项目】一个基于环信IM开发的开源的私密社交APP-Baby 即时通信 Baby

seven。 发表了文章 • 853 次浏览 • 2017-08-31 14:49 • 来自相关话题

Baby这个开源项目基于环信IM开发,刚开始选择IM的时候,看到知乎上黑环信的人挺多的,就亲自下载了几家IM的demo源码跑一遍,从功能、集成难易和消息稳定几个方面对比,最终还是选择了环信。集成这方面环信做的真不错,尤其是有了EaseUi这个包,基本上一天就能集成完毕。项目运行至今没有出现过什么问题,发送消息挺稳定的。先上效果图




开屏页的登录和注册




编辑个人信息




相册页面




首页的Moment
版本更新:
 
version 1.6
加入Tinker 热修复更新部分依赖修复大量细节问题,加入部分注释

version 1.5
bug fixupdate sth

version 1.4
增加长按删除功能优化Rxbus订阅加载数据外国友人优化的一些细节等等

version 1.3
增加了评论功能优化了相册加载修复了一些内存泄漏等等

version 1.2
修复了一些Bug把登陆注册事件换了个Zip操作符更符合流的思想

version 1.1
修复了主页背景无法切换的问题修复了聊天推送的问题修了语音视频的问题做了一些细节修改
Download



安装包下载体验
 
github地址
github源码
 Development Environment & Library
 
MVP

这个项目是基于MVP框架写的(大体上,聊天那块直接用环信的了),大部分Base类参考FastAndroid里边的基类,参考这个很快就能布好基本的MVP架构。本来是有考虑过MVVM后来想想还是先学习一下MVP吧,看过几个MVVM项目感觉还是挺好用的,不过还是BETA版不知道有没有什么坑。

Material Design

早就手痒想体验一把V7包里边的各种控件了,特喜欢coordinatorlayout和collapsingtoolbarlayout的互动让Tollbar隐藏又现的感觉,但是看起来好看还是要点代价的,在这里捣鼓了不少时间,尤其是collapsingtoolbarlayout的Expanded固定让我Google了好久,因为用英文搜索可能我表达的不太好,最后竟然是一句nestedScroll(false)就可以了。。。。 还是感谢Stackoveflow里边的大腿吧。

Dagger2

依赖注入Dagger2,也是我早就想用的一个框架了,理由是各种配合Mvp十分方便和好用,渐渐也能体会到一次注入到处可用的快感。不过一个新技术真的学习成本,国内没什么中文文档介绍,看国外的看的云里雾里。原理看的明白,用起来好像不太知道如何使用,尤其是在@inject之后对象,也可以在别的地方Inject,原本是被Inject方后来也成了Module提供方。虽然到最后原理还不是特别明白这里,但还是不阻碍用起来的快感。

Realm

一开始被新技术吸引到的是不会放过任何新东西的包括Realm,不过进了坑不代表这个坑可以跳阿。由于我这次用到了leacncloud,Realm感觉会和LeanCloud的子类化冲突让你只能选择其中之一,不过这个也算了,Leancloud提供了类似Map的Put方法也可以接受就是麻烦了点。但是被坑到的地方是Realm所谓的自动数据同步竟然是一改就是改真实的数据,并不是数据的拷贝。。。感觉和我使用到要缓存的数据有点冲突,因为这个Moment里边的项是有点赞的,点赞要修改当前Recycleview的数据(修改数据要开事务)。修改数据后会出现一些很奇怪的现象,不在Recycleview当前Item会跳到当前Item,点赞的动画也会消失。。。真的是想破脑袋也解决不了,就直接跳坑了。最后感觉这个Realm在保存不跟服务器需要同步的数据会好点。

LeanCloud

用LeanCloud是因为在知乎太多吹它的人了而且它的确在BAAS这方面功能比较多(后来才发现即时通信没有语音和视频),所以就尝试使用了,SDK整体来说是不错的都挺好用的,满足了我对存储方面的要求。不过就在我开发的这几天,貌似稳定性没有想象中那么好,好几次上传个头像都会SocketTimeOut,查询也会有点慢,不过还好都在接受范围内(不过要是到了收费的标准我就接受不了)。

环信

baby这个开源项目基于环信IM开发,刚开始选择IM的时候,看到知乎上黑环信的人挺多的,就亲自下载了几家IM的demo源码跑一遍,从功能、集成难易和消息稳定几个方面对比,最终还是选择了环信。集成这方面环信做的真不错,尤其是有了EaseUi这个包,基本上一天就能集成完毕。项目运行至今没有出现过什么问题,发送消息挺稳定的。

Rxjava、RxAndroid

Rxjava我从第一眼看到了就喜欢上了(个人特喜欢那种通过.设置完成的感觉),接触也有几个月,一开始就和Retrofit 、Okhttp一起使用。学习成本还是要有的阿,看了不知道多少篇关于Rxjava使用的文章和例子,对里边的操作符也仅仅停留在那几个最常用的,其他一大堆好多都没用过,看来还用得不够。

Glide

Glide也是一个后来居上让我喜欢的图片加载库,一开始我喜欢picasso 是觉得轻巧而且好用有保证(主要是我偶像Jake Wharton主导,有加成),慢慢觉得Picasso对内存没有Glide来的友好,Glide在加载速度方面也领先,虽然整个库代码量是Picasso的几倍,但是比起重要的内存和用户体验来说还是Glide的领先一筹。

Butterknife、Ucrop等等

当让还有其他的一些润色的轮子啦,不过不是那么重要就不一一感谢啦。

Thanks
感谢Github、LeanCloud、环信、还有造那么多轮子给我们用的Square FaceBook Google的大大们。Thanks for improving my code m-ezzat.

Contacts
Email:379489343zhi@gmail.comQQ:379489343
 Copyright 2016 Roger ou

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. 查看全部
   Baby这个开源项目基于环信IM开发,刚开始选择IM的时候,看到知乎上黑环信的人挺多的,就亲自下载了几家IM的demo源码跑一遍,从功能、集成难易和消息稳定几个方面对比,最终还是选择了环信。集成这方面环信做的真不错,尤其是有了EaseUi这个包,基本上一天就能集成完毕。项目运行至今没有出现过什么问题,发送消息挺稳定的。
先上效果图

003.png

开屏页的登录和注册


001.png

编辑个人信息


002.png

相册页面


004.png

首页的Moment


版本更新:
 
version 1.6
  1. 加入Tinker 热修复
  2. 更新部分依赖
  3. 修复大量细节问题,加入部分注释


version 1.5
  1. bug fix
  2. update sth


version 1.4
  1. 增加长按删除功能
  2. 优化Rxbus订阅加载数据
  3. 外国友人优化的一些细节
  4. 等等


version 1.3
  1. 增加了评论功能
  2. 优化了相册加载
  3. 修复了一些内存泄漏
  4. 等等


version 1.2
  1. 修复了一些Bug
  2. 把登陆注册事件换了个Zip操作符更符合流的思想


version 1.1
  1. 修复了主页背景无法切换的问题
  2. 修复了聊天推送的问题
  3. 修了语音视频的问题
  4. 做了一些细节修改

Download

 
github地址

 Development Environment & Library
 
MVP

这个项目是基于MVP框架写的(大体上,聊天那块直接用环信的了),大部分Base类参考FastAndroid里边的基类,参考这个很快就能布好基本的MVP架构。本来是有考虑过MVVM后来想想还是先学习一下MVP吧,看过几个MVVM项目感觉还是挺好用的,不过还是BETA版不知道有没有什么坑。

Material Design

早就手痒想体验一把V7包里边的各种控件了,特喜欢coordinatorlayout和collapsingtoolbarlayout的互动让Tollbar隐藏又现的感觉,但是看起来好看还是要点代价的,在这里捣鼓了不少时间,尤其是collapsingtoolbarlayout的Expanded固定让我Google了好久,因为用英文搜索可能我表达的不太好,最后竟然是一句nestedScroll(false)就可以了。。。。 还是感谢Stackoveflow里边的大腿吧。

Dagger2

依赖注入Dagger2,也是我早就想用的一个框架了,理由是各种配合Mvp十分方便和好用,渐渐也能体会到一次注入到处可用的快感。不过一个新技术真的学习成本,国内没什么中文文档介绍,看国外的看的云里雾里。原理看的明白,用起来好像不太知道如何使用,尤其是在@inject之后对象,也可以在别的地方Inject,原本是被Inject方后来也成了Module提供方。虽然到最后原理还不是特别明白这里,但还是不阻碍用起来的快感。

Realm

一开始被新技术吸引到的是不会放过任何新东西的包括Realm,不过进了坑不代表这个坑可以跳阿。由于我这次用到了leacncloud,Realm感觉会和LeanCloud的子类化冲突让你只能选择其中之一,不过这个也算了,Leancloud提供了类似Map的Put方法也可以接受就是麻烦了点。但是被坑到的地方是Realm所谓的自动数据同步竟然是一改就是改真实的数据,并不是数据的拷贝。。。感觉和我使用到要缓存的数据有点冲突,因为这个Moment里边的项是有点赞的,点赞要修改当前Recycleview的数据(修改数据要开事务)。修改数据后会出现一些很奇怪的现象,不在Recycleview当前Item会跳到当前Item,点赞的动画也会消失。。。真的是想破脑袋也解决不了,就直接跳坑了。最后感觉这个Realm在保存不跟服务器需要同步的数据会好点。

LeanCloud

用LeanCloud是因为在知乎太多吹它的人了而且它的确在BAAS这方面功能比较多(后来才发现即时通信没有语音和视频),所以就尝试使用了,SDK整体来说是不错的都挺好用的,满足了我对存储方面的要求。不过就在我开发的这几天,貌似稳定性没有想象中那么好,好几次上传个头像都会SocketTimeOut,查询也会有点慢,不过还好都在接受范围内(不过要是到了收费的标准我就接受不了)。

环信

baby这个开源项目基于环信IM开发,刚开始选择IM的时候,看到知乎上黑环信的人挺多的,就亲自下载了几家IM的demo源码跑一遍,从功能、集成难易和消息稳定几个方面对比,最终还是选择了环信。集成这方面环信做的真不错,尤其是有了EaseUi这个包,基本上一天就能集成完毕。项目运行至今没有出现过什么问题,发送消息挺稳定的。

Rxjava、RxAndroid

Rxjava我从第一眼看到了就喜欢上了(个人特喜欢那种通过.设置完成的感觉),接触也有几个月,一开始就和Retrofit 、Okhttp一起使用。学习成本还是要有的阿,看了不知道多少篇关于Rxjava使用的文章和例子,对里边的操作符也仅仅停留在那几个最常用的,其他一大堆好多都没用过,看来还用得不够。

Glide

Glide也是一个后来居上让我喜欢的图片加载库,一开始我喜欢picasso 是觉得轻巧而且好用有保证(主要是我偶像Jake Wharton主导,有加成),慢慢觉得Picasso对内存没有Glide来的友好,Glide在加载速度方面也领先,虽然整个库代码量是Picasso的几倍,但是比起重要的内存和用户体验来说还是Glide的领先一筹。

Butterknife、Ucrop等等

当让还有其他的一些润色的轮子啦,不过不是那么重要就不一一感谢啦。

Thanks
  • 感谢Github、LeanCloud、环信、还有造那么多轮子给我们用的Square FaceBook Google的大大们。
  • Thanks for improving my code m-ezzat.


Contacts

 
Copyright 2016 Roger ou

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
6
评论

【新手快速入门】集成环信常见问题+解决方案汇总 常见问题

dujiepeng 发表了文章 • 6066 次浏览 • 2017-05-22 15:51 • 来自相关话题

   这里整理了集成环信的常见问题和一些功能的实现思路,希望能帮助到大家。感谢热心的开发者贡献,大家在观看过程中有不明白的地方欢迎直接跟帖咨询。
 
ios篇
APNs证书创建和上传到环信后台头像昵称的简述和处理方案音视频离线推送Demo实现环信服务器聊天记录保存多久?离线收不到好友请求IOS中环信聊天窗口如何实现文件发送和预览的功能ios集成常见问题环信推送的一些常见问题实现名片|红包|话题聊天室等自定义cell
 
Android篇
环信3.0SDK集成小米推送教程EaseUI库中V4、v7包冲突解决方案Android EaseUI里的百度地图替换为高德地图android扩展消息(名片集成)关于会话列表的置顶聊天java.lang.UnsatisfiedLinkError: 的问题android 端 app 后台被杀死收不到消息的解决方案
昵称头像篇
android中如何显示开发者服务器上的昵称和头像 Android中显示头像(接上一篇文章看)环信(Android)设置头像和昵称的方法(最简单暴力的基于环信demo的集成)IOS中如何显示开发者服务器上的昵称和头像【环信公开课第12期视频回放】-所有关于环信IM昵称头像的问题听这课就够了
 
直播篇
一言不合你就搞个直播APP
 
客服集成
IM-SDK和客服SDK并存开发指南—Android篇IM-SDK和客服SDK并存开发指南—iOS篇
 
开源项目
Android简版demoios简版demo凡信2.0:超仿微信的开源项目 凡信3.0:携直播和红包而来高仿微信:Github 3,515 Star方圆十里:环信编程大赛冠军项目泛聊:定一个小目标写一个QQSlack聊天机器人:一天时间做一个聊天机器人TV视频通话:在电视上视频通话视频通话:Android手机视频通话酷信:ios高仿微信公众号助手:与订阅用户聊天沟通
 
持续更新ing...小伙伴们还有什么想知道欢迎跟帖提出。
  查看全部
   这里整理了集成环信的常见问题和一些功能的实现思路,希望能帮助到大家。感谢热心的开发者贡献,大家在观看过程中有不明白的地方欢迎直接跟帖咨询。
 
ios篇

 
Android篇

昵称头像篇

 
直播篇
  1. 一言不合你就搞个直播APP

 
客服集成
  1. IM-SDK和客服SDK并存开发指南—Android篇
  2. IM-SDK和客服SDK并存开发指南—iOS篇

 
开源项目

 
持续更新ing...小伙伴们还有什么想知道欢迎跟帖提出。
 
0
评论

【环信征文】请不要说自己是Android程序员 移动开发

钢笔布莱恩特 发表了文章 • 109 次浏览 • 2017-08-12 10:31 • 来自相关话题

经常在网上看到各种标题为“Android程序员”、“Java程序员”、“PHP程序员”、“C/C++程序员”的招聘帖子,但这种招聘方式,很难找到好的人才。语言只是一种工具,对一个聪明的程序员来说,用没用过什么工具主要是由他原来的工作需要决定,并不能代表他全部的技能。

软件行业是一个非常强调人的价值的行业,价值就体现在有效的推动产品前进,而语言只是实现这个价值的工具。





一个软件产品往往涉及很多方面的知识,比如网络、数据库、Cache、编译环境工具等。如果这些必要基础知识不足,很难很好的独立完成一个产品的某个部分。

另一方面,一个人的聪明程度、对新知识的好奇心、自我驱动意识、为问题找到最佳解决方案的决心,才是他能不能成为一个好程序员的关键。举个例子,我的一位在某米当cto学长的告诉我,有位同事本来是服务器端以C#语言为主做开发的,完全没有过android开发经验,但他表现出对移动开发很有兴趣,并且在做服务器端开发时,表现出良好的学习能力,后来我把他调到Android组,负责android SDK和APNs相关的工作,结果只花了几个星期,Android SDK的稳定性大幅提升,解决了多个致命问题。

不要仅仅把自己定位为某种语言的程序员,说自己是Java程序员,C#程序员,Python程序员等等。一方面会限制自己的发展,一方面对团队整体的能力提升也不利。几乎所有的语言都有它自己的适用场景,在合适的地方用合适的语言,才能极大的提升生产效率。
正确的做法是,首先要有良好的基础知识,深刻的掌握2~3门语言,然后适用于不同场景的语言要了解概念。基础知识包括各种计算机原理、数据方面的知识,在学校没认真学的,现在有时间也要补充。语言方面比如掌握了C/Java,那C++/Python/Bash/Javascript/CSS等都可以了解下概念,至少要理解在一个完整的产品链里,它们分别适用于哪个环节。

标题用“请不要说自己是Android程序员”没有贬低Android程序员的意思,Java是目前被采用得最多的语言,主要用Java的程序员里,也是有大量牛人。另外,同样的,也不要说自己是C程序员、Python程序员。

 古语说的好,“书中自有黄金屋”。这句话告诉我们书籍是学习知识的第一大根本方向。在与Java相关的专业书籍中,相继记述着关于这门课程的基础知识及进阶内容,先易后难、步步深入,非常适合初学者去学习。
  虚心求教不可少。
往往很多高深莫测,经验丰富,功力深厚的人都埋藏在自己的身边,不容自己去察觉。所以如果大家想要从事Java行业,不妨请假身边从事过该行业的朋友,求学不在高低贵贱之分,只要碰到不懂的地方,就去虚心求教,世界这么大,而且这门知识又是如此让人追捧,比自己懂的人岂止千百?从这些人身上自己一定能够受益匪浅。

现在以Java语言为主的工作非常之多,另外在学校里就以学习Java为主的人也越来越多。但是,从学校就以学习Java这种高级语言为主的人,很多基础知识比较薄弱。高级语言掩盖了太多细节,提高了生产力,但在学习阶段,却不利于基础知识累积。




“Nicholas C. Zakas是全世界最著名的JavaScript程序员之一,之前是在雅虎将近工作5年。三年前,他写了一篇长文,回顾自己的职业生涯,提到七个对他来说最重要的建议,希望对大家的职业生涯有帮助:

1、 不要别人点什么,就做什么

我的第一份工作,只干了8个月,那家公司就倒闭了。我问经理,接下来我该怎么办,他说:"小伙子,千万不要当一个被人点菜的厨师,别人点什么,你就烧什么。不要接受那样一份工作,别人下命令你该干什么,以及怎么干。你要去一个地方,那里的人肯定你对产品的想法,相信你的能力,放手让你去做。"

我从此明白,单单实现一个产品是不够的,你还必须参与决定怎么实现。好的工程师并不仅仅服从命令,而且还给出反馈,帮助产品的拥有者改进它。

2、 推销自己




我进入雅虎公司以后,经理有一天跟我谈话,他觉得我还做得不够。

"你工作得很好,代码看上去不错,很少出Bug。但是,问题是别人都没看到这一点。为了让其他人相信你,你必须首先让别人知道你做了什么。你需要推销自己,引起别人的注意。"

我这才意识到,即使做出了很好的工作,别人都不知道,也没用。做一个角落里静静编码的工程师,并不可取。你的主管会支持你,但是他没法替你宣传。公司的其他人需要明白你的价值,最好的办法就是告诉别人你做了什么。一封简单的Email:"嗨,我完成了XXX,欢迎将你的想法告诉我",就很管用。

3、 学会带领团队
工作几年后,已经没人怀疑我的技术能力了,大家知道我能写出高质量的可靠代码。有一次,我问主管,怎么才能得到提升,他说:"当你的技术能力过关以后,就要考验你与他人相处的能力了。"
于是,我看到了,自己缺乏的是领导能力,如何带领一个团队,有效地与其他人协同工作,取到更大的成果。

4、 生活才是最重要的
有一段时间,我在雅虎公司很有挫折感,对公司的一些做法不认同,经常会对别人发火。我问一个同事,他怎么能对这种事情保持平静,他回答:"你要想通,这一切并不重要。有人提交了烂代码,网站下线了,又怎么样?工作并不是你的整个生活。它们不是真正的问题,只是工作上的问题。真正重要的事情都发生在工作以外。我回到家,家里人正在等我,这才重要啊。"
从此,我就把工作和生活分开了,只把它当作"工作问题"看待。这样一来,我对工作就总能心平气和,与人交流也更顺利了。
5、 自己找到道路
我被提升为主管以后,不知道该怎么做。我请教了上级,他回答:"以前都是我们告诉你做什么,从现在开始,你必须自己回答这个问题了,我期待你来告诉我,什么事情需要做。"
很多工程师都没有完成这个转变,如果能够做到,可能就说明你成熟了,学会了取舍。你不可能把时间花在所有事情上面,必须找到一个重点。
6、 把自己当成主人

我每天要开很多会,有些会议我根本无话可说。我对一个朋友说,我不知道自己为什么要参加这个会,也没有什么可以贡献,他说:"不要再去开这样的会了。你参加一个会,那是因为你参与了某件事。如果不确定自己为什么要在场,就停下来问。如果这件事不需要你,就离开。不要从头到尾都静静地参加一个会,要把自己当成负责人,大家会相信你的。"
从那时起,我从没有一声不发地参加会议。我确保只参加那些需要我参加的会议。
7、 找到水平更高的人
最后,让我从自己的经历出发,给我的学员一个建议。
"找到那些比你水平更高、更聪明的人,尽量和他们在一起,吃饭或者喝咖啡,向他们讨教,了解他们拥有的知识。你的职业,甚至你的生活,都会因此变得更好。"
 我的感受是IT行业是当今社会的热门行业,说它热门是因为它的发展潜力是无穷的,所以我们能进入到这个行业是一种幸运。在此,我特别感谢上家公司带我教我前辈们和师傅,在学习期间给了我莫大的帮助,在我遇到困难时,给我很大的鼓励和帮助,让我更加有信心坚持下来,找到工作。最后送大家一句话:相信自己没有选错行业,相信自己有立足的能力,为自己制定明确的目标,然后努力地去学习、体会、感悟、进步!
  查看全部
经常在网上看到各种标题为“Android程序员”、“Java程序员”、“PHP程序员”、“C/C++程序员”的招聘帖子,但这种招聘方式,很难找到好的人才。语言只是一种工具,对一个聪明的程序员来说,用没用过什么工具主要是由他原来的工作需要决定,并不能代表他全部的技能。

软件行业是一个非常强调人的价值的行业,价值就体现在有效的推动产品前进,而语言只是实现这个价值的工具。
(W[}_`X~BVTQM{3A`@HN4JU.png


一个软件产品往往涉及很多方面的知识,比如网络、数据库、Cache、编译环境工具等。如果这些必要基础知识不足,很难很好的独立完成一个产品的某个部分。

另一方面,一个人的聪明程度、对新知识的好奇心、自我驱动意识、为问题找到最佳解决方案的决心,才是他能不能成为一个好程序员的关键。举个例子,我的一位在某米当cto学长的告诉我,有位同事本来是服务器端以C#语言为主做开发的,完全没有过android开发经验,但他表现出对移动开发很有兴趣,并且在做服务器端开发时,表现出良好的学习能力,后来我把他调到Android组,负责android SDK和APNs相关的工作,结果只花了几个星期,Android SDK的稳定性大幅提升,解决了多个致命问题。

不要仅仅把自己定位为某种语言的程序员,说自己是Java程序员,C#程序员,Python程序员等等。一方面会限制自己的发展,一方面对团队整体的能力提升也不利。几乎所有的语言都有它自己的适用场景,在合适的地方用合适的语言,才能极大的提升生产效率。
正确的做法是,首先要有良好的基础知识,深刻的掌握2~3门语言,然后适用于不同场景的语言要了解概念。基础知识包括各种计算机原理、数据方面的知识,在学校没认真学的,现在有时间也要补充。语言方面比如掌握了C/Java,那C++/Python/Bash/Javascript/CSS等都可以了解下概念,至少要理解在一个完整的产品链里,它们分别适用于哪个环节。

标题用“请不要说自己是Android程序员”没有贬低Android程序员的意思,Java是目前被采用得最多的语言,主要用Java的程序员里,也是有大量牛人。另外,同样的,也不要说自己是C程序员、Python程序员。

 古语说的好,“书中自有黄金屋”。这句话告诉我们书籍是学习知识的第一大根本方向。在与Java相关的专业书籍中,相继记述着关于这门课程的基础知识及进阶内容,先易后难、步步深入,非常适合初学者去学习。
  虚心求教不可少。
往往很多高深莫测,经验丰富,功力深厚的人都埋藏在自己的身边,不容自己去察觉。所以如果大家想要从事Java行业,不妨请假身边从事过该行业的朋友,求学不在高低贵贱之分,只要碰到不懂的地方,就去虚心求教,世界这么大,而且这门知识又是如此让人追捧,比自己懂的人岂止千百?从这些人身上自己一定能够受益匪浅。

现在以Java语言为主的工作非常之多,另外在学校里就以学习Java为主的人也越来越多。但是,从学校就以学习Java这种高级语言为主的人,很多基础知识比较薄弱。高级语言掩盖了太多细节,提高了生产力,但在学习阶段,却不利于基础知识累积。
MSBFLGP1I{8KVLTCJ9)Q46.png

“Nicholas C. Zakas是全世界最著名的JavaScript程序员之一,之前是在雅虎将近工作5年。三年前,他写了一篇长文,回顾自己的职业生涯,提到七个对他来说最重要的建议,希望对大家的职业生涯有帮助:

1、 不要别人点什么,就做什么

我的第一份工作,只干了8个月,那家公司就倒闭了。我问经理,接下来我该怎么办,他说:"小伙子,千万不要当一个被人点菜的厨师,别人点什么,你就烧什么。不要接受那样一份工作,别人下命令你该干什么,以及怎么干。你要去一个地方,那里的人肯定你对产品的想法,相信你的能力,放手让你去做。"

我从此明白,单单实现一个产品是不够的,你还必须参与决定怎么实现。好的工程师并不仅仅服从命令,而且还给出反馈,帮助产品的拥有者改进它。

2、 推销自己




我进入雅虎公司以后,经理有一天跟我谈话,他觉得我还做得不够。

"你工作得很好,代码看上去不错,很少出Bug。但是,问题是别人都没看到这一点。为了让其他人相信你,你必须首先让别人知道你做了什么。你需要推销自己,引起别人的注意。"

我这才意识到,即使做出了很好的工作,别人都不知道,也没用。做一个角落里静静编码的工程师,并不可取。你的主管会支持你,但是他没法替你宣传。公司的其他人需要明白你的价值,最好的办法就是告诉别人你做了什么。一封简单的Email:"嗨,我完成了XXX,欢迎将你的想法告诉我",就很管用。

3、 学会带领团队
工作几年后,已经没人怀疑我的技术能力了,大家知道我能写出高质量的可靠代码。有一次,我问主管,怎么才能得到提升,他说:"当你的技术能力过关以后,就要考验你与他人相处的能力了。"
于是,我看到了,自己缺乏的是领导能力,如何带领一个团队,有效地与其他人协同工作,取到更大的成果。

4、 生活才是最重要的
有一段时间,我在雅虎公司很有挫折感,对公司的一些做法不认同,经常会对别人发火。我问一个同事,他怎么能对这种事情保持平静,他回答:"你要想通,这一切并不重要。有人提交了烂代码,网站下线了,又怎么样?工作并不是你的整个生活。它们不是真正的问题,只是工作上的问题。真正重要的事情都发生在工作以外。我回到家,家里人正在等我,这才重要啊。"
从此,我就把工作和生活分开了,只把它当作"工作问题"看待。这样一来,我对工作就总能心平气和,与人交流也更顺利了。
5、 自己找到道路
我被提升为主管以后,不知道该怎么做。我请教了上级,他回答:"以前都是我们告诉你做什么,从现在开始,你必须自己回答这个问题了,我期待你来告诉我,什么事情需要做。"
很多工程师都没有完成这个转变,如果能够做到,可能就说明你成熟了,学会了取舍。你不可能把时间花在所有事情上面,必须找到一个重点。
6、 把自己当成主人

我每天要开很多会,有些会议我根本无话可说。我对一个朋友说,我不知道自己为什么要参加这个会,也没有什么可以贡献,他说:"不要再去开这样的会了。你参加一个会,那是因为你参与了某件事。如果不确定自己为什么要在场,就停下来问。如果这件事不需要你,就离开。不要从头到尾都静静地参加一个会,要把自己当成负责人,大家会相信你的。"
从那时起,我从没有一声不发地参加会议。我确保只参加那些需要我参加的会议。
7、 找到水平更高的人
最后,让我从自己的经历出发,给我的学员一个建议。
"找到那些比你水平更高、更聪明的人,尽量和他们在一起,吃饭或者喝咖啡,向他们讨教,了解他们拥有的知识。你的职业,甚至你的生活,都会因此变得更好。"
 我的感受是IT行业是当今社会的热门行业,说它热门是因为它的发展潜力是无穷的,所以我们能进入到这个行业是一种幸运。在此,我特别感谢上家公司带我教我前辈们和师傅,在学习期间给了我莫大的帮助,在我遇到困难时,给我很大的鼓励和帮助,让我更加有信心坚持下来,找到工作。最后送大家一句话:相信自己没有选错行业,相信自己有立足的能力,为自己制定明确的目标,然后努力地去学习、体会、感悟、进步!
 
0
评论

【转载】组合式测试:移动测试服务的发展趋势 移动开发 移动互联网 app开发 APP测试

chieei 发表了文章 • 709 次浏览 • 2016-03-15 15:37 • 来自相关话题

由于国内移动设备和系统版本的碎片化,移动测试对于应用的质量保证变得至关重要,同时也催生了一批提供第三方测试服务的创业公司,BAT也都发布了自己的测试服务。但是,单一的测试服务往往不能完全满足开发者需求,测试服务的提供商也都在探索满足开发者需求的新方式。

自动化测试不能满足开发者需求

因为碎片化原因,开发者不可能手动测试所有的移动设备和系统版本,因此自动化测试对于移动测试来说是必须的。传统的第三方测试服务就是从这一点入手,以庞大 的云端真机测试为卖点,受到了开发者的认可。在社区里,自动化测试也最受关注,自动化测试的框架层出不穷,如何搭建自动化测试系统、编写测试脚本的内容最 受欢迎。一时间,自动化测试有一种彻底取代人工测试的势头。

但是,自动化测试实际上存在着一些问题,导致它并不实用,至少不能完全满足开发者的需求。据顾昕彪介绍,自动化测试的主要问题有:

新的功能很难做自动化测试。自动化测试大多数的作用是回归以前已经稳定下来的功能,对于一个新的功能,开发完以后要编写相应的测试用例,再进行自动化测试,这个时间比人工测试更长,因为人工测试可以直接开始测试,自动化测试有一个编写过程。

自动化测试需要有一些测试用例的积累,在版本大的迭代之后,很多测试用例可能就失效了,需要重新编写。因为移动应用发版很快,测试用例维护成本相对比较高。

自动化测试质量取决于编写测试用例的人的能力。有些时候测试用例能通过,但实际功能并不能用,要避免这点需要有丰富的测试经验和对移动开发的透彻的理解,而这对测试人员的要求太高了。

因此,自动化测试只能帮助开发者解决一部分兼容性问题,通常为了保证质量,开发者仍然需要采取其它测试手段。

施佳樑认为,人工测试之所以没有被市场所重视,是因为第三方人工测试服务的成本太高,如果能把人工测试的成本降下来,那么开发者还是会选择更有效的方式来满足测试需求,众测解决了这个问题。

众测成为测试工程师的业余职业

众包测试是在国外兴起的一种测试模式,通过将测试分配到多人手里,从而解决碎片化问题,并且避免自动化测试的一些弊端。

施佳樑介绍道,他们的众测平台拥有1500万用户,在这些用户中经过培训筛选,筛选出1000多个测试专家。这些测试专家已经能够像专业的测试人员一样,提供标准的测试报告来帮助开发者定位问题。

值得一提的是,这些测试专家里有些本来就是专业的测试人员,比如百度众测里会有百度的测试工程师利用业余时间来帮助别人做测试。事实上测试是一个需要经验和知识积累的职业,一般的众测人员只能模拟普通用户,效率较低,只有专业的测试人员才能高效的找出问题并提出报告。

通过众测这种模式,开发者能够以较低的成本请到多个较专业的测试人员进行测试,而测试工程师也能够在业余时间用职业技能赚些外快,这是一个双赢的事情。笔者认为这很可能成为众测模式的发展方向。

移动应用测试的未来:一体化服务

自动化测试和人工测试结合,能够得到一个较好的测试结果。但是,有一些情况没有包含在其中,比如应用crash,不借助辅助工具,要定位问题仍然比较困难,而crash上报服务正是为解决这个问题而生。

另外,对于应用性能,特别是不同网络条件下的应用表现的监测,使用应用性能管理服务(APM)更加有针对性。

要使用第三方服务来完全测试一个应用里可能出现的问题,开发者需要注册不同的服务,登录不同网站的管理后台来进行,这显然是很不方便的。而提供所有这些服务,同时将它们整合起来,将是移动测试服务未来一段时间的发展方向。

届时,开发者将只需登录一个网站,提交一次应用就可以得到一个多维度的、完整的测试报告,只有发展到这个阶段,移动测试服务才真正满足开发者的需求。



基于全球首创的对象识别技术,TestBird可以为客户提供深入到移动APP&游戏内部所有功能的深度解析能力。通过自助功能测试、远程真机调试、真机兼容性测试、真人体验测试、 真人压力测试和崩溃分析等产品,TestBird建立了云手机、云测试和云分析三大测试平台,为移动应用提供从研发到上线再到运营的一站式质量管理服务,帮助移动应用企业建立完善的质量管理体系和能力,全面提高移动应用的DAU、留存率以及付费情况。 查看全部


由于国内移动设备和系统版本的碎片化,移动测试对于应用的质量保证变得至关重要,同时也催生了一批提供第三方测试服务的创业公司,BAT也都发布了自己的测试服务。但是,单一的测试服务往往不能完全满足开发者需求,测试服务的提供商也都在探索满足开发者需求的新方式。

自动化测试不能满足开发者需求

因为碎片化原因,开发者不可能手动测试所有的移动设备和系统版本,因此自动化测试对于移动测试来说是必须的。传统的第三方测试服务就是从这一点入手,以庞大 的云端真机测试为卖点,受到了开发者的认可。在社区里,自动化测试也最受关注,自动化测试的框架层出不穷,如何搭建自动化测试系统、编写测试脚本的内容最 受欢迎。一时间,自动化测试有一种彻底取代人工测试的势头。

但是,自动化测试实际上存在着一些问题,导致它并不实用,至少不能完全满足开发者的需求。据顾昕彪介绍,自动化测试的主要问题有:

新的功能很难做自动化测试。自动化测试大多数的作用是回归以前已经稳定下来的功能,对于一个新的功能,开发完以后要编写相应的测试用例,再进行自动化测试,这个时间比人工测试更长,因为人工测试可以直接开始测试,自动化测试有一个编写过程。

自动化测试需要有一些测试用例的积累,在版本大的迭代之后,很多测试用例可能就失效了,需要重新编写。因为移动应用发版很快,测试用例维护成本相对比较高。

自动化测试质量取决于编写测试用例的人的能力。有些时候测试用例能通过,但实际功能并不能用,要避免这点需要有丰富的测试经验和对移动开发的透彻的理解,而这对测试人员的要求太高了。

因此,自动化测试只能帮助开发者解决一部分兼容性问题,通常为了保证质量,开发者仍然需要采取其它测试手段。

施佳樑认为,人工测试之所以没有被市场所重视,是因为第三方人工测试服务的成本太高,如果能把人工测试的成本降下来,那么开发者还是会选择更有效的方式来满足测试需求,众测解决了这个问题。

众测成为测试工程师的业余职业

众包测试是在国外兴起的一种测试模式,通过将测试分配到多人手里,从而解决碎片化问题,并且避免自动化测试的一些弊端。

施佳樑介绍道,他们的众测平台拥有1500万用户,在这些用户中经过培训筛选,筛选出1000多个测试专家。这些测试专家已经能够像专业的测试人员一样,提供标准的测试报告来帮助开发者定位问题。

值得一提的是,这些测试专家里有些本来就是专业的测试人员,比如百度众测里会有百度的测试工程师利用业余时间来帮助别人做测试。事实上测试是一个需要经验和知识积累的职业,一般的众测人员只能模拟普通用户,效率较低,只有专业的测试人员才能高效的找出问题并提出报告。

通过众测这种模式,开发者能够以较低的成本请到多个较专业的测试人员进行测试,而测试工程师也能够在业余时间用职业技能赚些外快,这是一个双赢的事情。笔者认为这很可能成为众测模式的发展方向。

移动应用测试的未来:一体化服务

自动化测试和人工测试结合,能够得到一个较好的测试结果。但是,有一些情况没有包含在其中,比如应用crash,不借助辅助工具,要定位问题仍然比较困难,而crash上报服务正是为解决这个问题而生。

另外,对于应用性能,特别是不同网络条件下的应用表现的监测,使用应用性能管理服务(APM)更加有针对性。

要使用第三方服务来完全测试一个应用里可能出现的问题,开发者需要注册不同的服务,登录不同网站的管理后台来进行,这显然是很不方便的。而提供所有这些服务,同时将它们整合起来,将是移动测试服务未来一段时间的发展方向。

届时,开发者将只需登录一个网站,提交一次应用就可以得到一个多维度的、完整的测试报告,只有发展到这个阶段,移动测试服务才真正满足开发者的需求。



基于全球首创的对象识别技术,TestBird可以为客户提供深入到移动APP&游戏内部所有功能的深度解析能力。通过自助功能测试、远程真机调试、真机兼容性测试、真人体验测试、 真人压力测试和崩溃分析等产品,TestBird建立了云手机、云测试和云分析三大测试平台,为移动应用提供从研发到上线再到运营的一站式质量管理服务,帮助移动应用企业建立完善的质量管理体系和能力,全面提高移动应用的DAU、留存率以及付费情况。
0
评论

环信移动客服助力58到家打造一站式客服体验闭环 移动开发

admin 发表了文章 • 1217 次浏览 • 2015-08-17 19:37 • 来自相关话题

近日,环信B轮融资及移动客服新品发布会在北京顺利举行。发布会上,环信CEO刘俊彦宣布,环信成功获得B轮1250万美元融资,同时环信CTO马晓宇宣布环信移动客服3.0产品正式上线,主打移动、智能、全渠道。而环信将以“连接人与商业”为愿景,开启万亿级企业云服务市场。






58到家客服总监王辉现场解读环信移动客服是怎么服务客户的

58到家客服总监王辉表示:“58到家原来只有呼叫中心一条服务渠道,对及时响应问题做得非常不好,虽然我们服务水平一直维持在85%以上,但是我们仍有客户打不进来电话,这些客户意味着订单的损失。O2O行业特点就是客户要求及时响应,快速解决,同时要满足任何下单需求。接入环信移动客服以后解决了58到家业务量暴增导致客服资源严重不足的问题,同时环信移动客服支持全渠道接入把服务渠道统一,把客户引流到在线客服上,提供了一站式的客户服务体验解决方案。同时帮助58到家把客服部门完成了从成本中心向盈利和营销中心的变革。”






据悉,环信移动客服产品已经有国美在线、58到家、楚楚街9块9等大批互联网巨头企业签约,累计签约客服座席已经达4万个,据艾媒咨询《2015年中国移动客服市场发展研究报告》显示,环信移动客服在新兴的移动客服市场占有率第一。

环信CTO马晓宇介绍,环信之所以受到市场如此欢迎,是因为环信移动客服是有别于传统客服的划时代产品。在环信CTO马晓宇看来,客服经历了三个时代传统callcenter的时代,互联网尚未普及,电话客服客户等待时间长,客户服务人员压力大,工作重复内容多;到了PC网页客服时代,随着互联网的普及,网页客服的成本明显小于电话客服,客户服务人员工作量较小,客户满意度有所提高,但相应依然不能及时有效;当今,随着智能手机用户的快速增长,客户要求能够随时在移动端获取咨询服务。移动端客服的重要性将不断上升。移动客服时代随之到来。

然而在环信基于IM长连接技术推出移动客服之前,业界并没有一款真正适合移动端和社交化时代的可靠的云端移动客服产品。此前,业界普遍存在的是两种移动客服产品,一类是工单客服,可以被视为移动客服1.0,基于工单方式和客服交互,技术实现简单,但无法做到实时交互,沟通效率低,用户体验差。另一类是轮询技术客服,可以被视为移动客服2.0,基于HTTP轮询技术,通过不断向服务器发送查询请求来准实时的收取消息。不能做到实时收取消息,流量和电量消耗高,APP在后台时无法接收消息,容易丢失客户。

而环信推出的移动客服产品是业界唯一一款具有IM长连接技术的移动客服产品,这被视为更适合移动端的客服产品。这一类型的移动客服可以定义为“交互型智能移动客服”,可以被视为移动客服3.0,以环信为代表的这一类新型移动客服是基于亿级IM长连接,系统稳定;智能机器人技术可处理大部分重复问题。相较环信移动客服的能力,传统的电话、工单、轮询客服在移动端和社交趋势下就显得捉襟见肘,有些OUT了。

环信移动客服实现了跨平台多渠道接入:支持 App、微信公众账号、微博、网页等,均可以快速统一接入客户服务后台管理。

其次,满足了开放性与自定义信息:这种新型的移动客服实现了代码开源、UI开源,还提供多套UI模版,便于与APP快速集成,平滑接入。同时第三方集成功能也很强大,可与第三方工单、知识库、CRM 系统等进行扩展集成。

第三,富媒体消息交互体验:移动客服平台提供了基于IM技术的类似微信体验的友好富媒体消息交互,不仅可以实时收发文字、表情,还可以即时收发图片、位置、实时语音、还可自定义消息,大大方便了与客户的沟通交流。

第四,精准客户画像功能:移动客服的IM沟通帮助企业辅助判断客户需求与诉求,通过自定义客户分类标签,客户再次访问时可获知客户的类型。并且还支持自定义会话小结,根据会话小结统计会话的分类,通过会话小结追踪客户诉求。通过轨迹分析功能,即通过发送客户访问页面的轨迹,判断客户意图,获取客户个性化细节,了解客户基础信息,分析客户行为,可以极大提高订单效率。

第五,“智能机器人+智能知识库”:作为一套智能化的客服系统,让企业建立基于业务的智能知识库,智能辅助归结业务信息和应答客户信息,历史常见问题系统梳理,提高客服效率。“智能机器人+智能知识库”组合目前可自动回复80%常见问题,随着智能知识库的不断训练,这一比例能够提高到90%。 查看全部
近日,环信B轮融资及移动客服新品发布会在北京顺利举行。发布会上,环信CEO刘俊彦宣布,环信成功获得B轮1250万美元融资,同时环信CTO马晓宇宣布环信移动客服3.0产品正式上线,主打移动、智能、全渠道。而环信将以“连接人与商业”为愿景,开启万亿级企业云服务市场。

113R92H4-0.png


58到家客服总监王辉现场解读环信移动客服是怎么服务客户的

58到家客服总监王辉表示:“58到家原来只有呼叫中心一条服务渠道,对及时响应问题做得非常不好,虽然我们服务水平一直维持在85%以上,但是我们仍有客户打不进来电话,这些客户意味着订单的损失。O2O行业特点就是客户要求及时响应,快速解决,同时要满足任何下单需求。接入环信移动客服以后解决了58到家业务量暴增导致客服资源严重不足的问题,同时环信移动客服支持全渠道接入把服务渠道统一,把客户引流到在线客服上,提供了一站式的客户服务体验解决方案。同时帮助58到家把客服部门完成了从成本中心向盈利和营销中心的变革。”

113R95c2-1.png


据悉,环信移动客服产品已经有国美在线、58到家、楚楚街9块9等大批互联网巨头企业签约,累计签约客服座席已经达4万个,据艾媒咨询《2015年中国移动客服市场发展研究报告》显示,环信移动客服在新兴的移动客服市场占有率第一。

环信CTO马晓宇介绍,环信之所以受到市场如此欢迎,是因为环信移动客服是有别于传统客服的划时代产品。在环信CTO马晓宇看来,客服经历了三个时代传统callcenter的时代,互联网尚未普及,电话客服客户等待时间长,客户服务人员压力大,工作重复内容多;到了PC网页客服时代,随着互联网的普及,网页客服的成本明显小于电话客服,客户服务人员工作量较小,客户满意度有所提高,但相应依然不能及时有效;当今,随着智能手机用户的快速增长,客户要求能够随时在移动端获取咨询服务。移动端客服的重要性将不断上升。移动客服时代随之到来。

然而在环信基于IM长连接技术推出移动客服之前,业界并没有一款真正适合移动端和社交化时代的可靠的云端移动客服产品。此前,业界普遍存在的是两种移动客服产品,一类是工单客服,可以被视为移动客服1.0,基于工单方式和客服交互,技术实现简单,但无法做到实时交互,沟通效率低,用户体验差。另一类是轮询技术客服,可以被视为移动客服2.0,基于HTTP轮询技术,通过不断向服务器发送查询请求来准实时的收取消息。不能做到实时收取消息,流量和电量消耗高,APP在后台时无法接收消息,容易丢失客户。

而环信推出的移动客服产品是业界唯一一款具有IM长连接技术的移动客服产品,这被视为更适合移动端的客服产品。这一类型的移动客服可以定义为“交互型智能移动客服”,可以被视为移动客服3.0,以环信为代表的这一类新型移动客服是基于亿级IM长连接,系统稳定;智能机器人技术可处理大部分重复问题。相较环信移动客服的能力,传统的电话、工单、轮询客服在移动端和社交趋势下就显得捉襟见肘,有些OUT了。

环信移动客服实现了跨平台多渠道接入:支持 App、微信公众账号、微博、网页等,均可以快速统一接入客户服务后台管理。

其次,满足了开放性与自定义信息:这种新型的移动客服实现了代码开源、UI开源,还提供多套UI模版,便于与APP快速集成,平滑接入。同时第三方集成功能也很强大,可与第三方工单、知识库、CRM 系统等进行扩展集成。

第三,富媒体消息交互体验:移动客服平台提供了基于IM技术的类似微信体验的友好富媒体消息交互,不仅可以实时收发文字、表情,还可以即时收发图片、位置、实时语音、还可自定义消息,大大方便了与客户的沟通交流。

第四,精准客户画像功能:移动客服的IM沟通帮助企业辅助判断客户需求与诉求,通过自定义客户分类标签,客户再次访问时可获知客户的类型。并且还支持自定义会话小结,根据会话小结统计会话的分类,通过会话小结追踪客户诉求。通过轨迹分析功能,即通过发送客户访问页面的轨迹,判断客户意图,获取客户个性化细节,了解客户基础信息,分析客户行为,可以极大提高订单效率。

第五,“智能机器人+智能知识库”:作为一套智能化的客服系统,让企业建立基于业务的智能知识库,智能辅助归结业务信息和应答客户信息,历史常见问题系统梳理,提高客服效率。“智能机器人+智能知识库”组合目前可自动回复80%常见问题,随着智能知识库的不断训练,这一比例能够提高到90%。
0
评论

环信ONE SDK架构介绍 移动开发

admin 发表了文章 • 1301 次浏览 • 2015-08-10 15:41 • 来自相关话题

环信即时通讯SDK自2014年6月正式发布2.0版本至今已走过一个年头,从基本的单聊功能,到群聊功能,再到聊天室的实现,SDK不管是功能,稳定性,还是易集成性都在一步一步的走向完善与稳定,感谢开发者们给与提供的反馈与帮助,使我们的SDK迅速的在诸多方面得到提高与改进。

随着现在物联网的兴起,环信现在的SDK的架构对应对未来物联网平台还是略有不足,使我们不得不在今年年初就考虑到如何去改善我们的架构,使之能够较容易的适配到各个主流平台和物联网平台。

现在的Android, IOS, SDK都是各自维护了自己逻辑,给2.0开发带来了很多不便,相同的功能需要维护两份代码,同一个bug要在不同的平台修复两次,由于不同平台的实现,导致Android,IOS架构设计不统一,API不一致,再加上在不同的平台开发的工程师之间由于不同的实现导致沟通问题诸多,这样导致的问题就是,不同平台的开发进度大多数情况下都不相同。

所以针对以上的问题,我们今年年初就计划我们SDK3.0的开发,我们称之为ONE SDK,基本的理念就是我们实现共同IM 内核,使代码可被不同的平台最大化的重用,但是设计和实现却是面临着巨大的挑战,如何适配到不同的平台,如何最大化的重用代码都是要面临的问题。

ONE SDK 架构设计
总体设计






ONE SDK的设计总体分为3层,平台层-Platfrom layer,适配层-Porting layer,核心层-Common layer.

平台层会根据各平台的不同,实现不同的接口,开放符合平台层的API给第三方开发者。

适配层主要要适配到ONE SDK 核心层所需要的一些接口,起到承上启下的作用。

核心层主要提供IM 功能和业务逻辑,保证最大化的代码重用。

考虑到跨平台共享代码,我们ONE SDK主要是用C++这种跨平台的语言来实现。

平台层

我们计划要支持的平台为Android,IOS,MAC OS,Windows,Windows phone, Linux,Embedded Linux, 还有较为广泛应用的物联网平台-IOT OS。

我们会针对不同平台提供给开发者,和平台一致API规范,使各平台的开发者无难度的集成SDK,例如我们会提供JAVA给Android,Objective-C 给IOS和MAC, C++ 给Linux, IOT平台。


适配层






适配层主要就是各平台需要实现核心层所需要的一些接口类例如,上图给出的线程模型,定时器模型,数据库模型,还有HTTP模型。

这些模型都是和平台相关的,例如有的平台提供sqllite的访问,有的没有,有的线程模型和定时器模型都有自己的实现方式例如物联网IOT OS,所以实现了上述的模型,就可以使核心层可以工作,不过也可能会遇到一些问题,这都会在具体的实现中会具体的应对,但结构是清晰的。

其实例如Android,Linux, IOS, Mac OS,Windows都是支持C++11,也就是说都是支持C++11所提供的线程模型,所以这几个操作系统的线程模型的实现应该是同样的,所以代码是可以共享的, 但是数据库Anroid NDK是不支持sqlite访问,所以这部分Android有两种策略一个是集成sqlite源代码,二是回调给JAVA层,前一种策略是代码逻辑清晰,但坏处就是增加了代码量。

还有就是HTTP模型,默认的android,iOS,Mac OS,windows都有自己的API提供,所以ONE SDK策略就是如果有平台有原生的HTTP API 支持我们就会尽量用平台的,但是类似linux,就需要第三方库的支持例如libcurl.

所以综上所述适配层的意义重大,保证我们ONE SDK代码共享最大化的目的。

核心层

核心层是具体实现环信相关功能的模块,它里面也包含的几个部分,核心业务逻辑API实现,抽象协议层,和独立实时音视频模块。

Core Common






业务逻辑层,负责提供基本的IM功能。

会话管理
消息收发
登录鉴权
连接管理

Audio/Video Call

实时音视频模块是一个独立的模块,可以单独存在,这样可以灵活处理,不需要时不用加载此模块。






实时音视频
多人语音

Abstract Protocol Layer

协议抽象层,主要用来处理具体的IM底层协议,这层是比较独立的主要实现环信定义的IM传输协议,也为为日后协议改造,扩展提供承上启下的作用。





定义抽象消息载体基本的消息发送基本的消息回调定义基本的通知
上述ONE SDK架构是我们计划要实现的,现在一些基本的设计已经在Linux SDK上得到了实现,下面让我们继续了解下Linux SDK。

Linux SDK

经过几个月的开发,我们已经推出了Linux SDK测试版,有兴趣的开发者可以小试一下去我们的官网 http://www.easemob.com/downloads 下载。

通过EMChatClient Facade类开发者可以访问到任何IM停供的功能
登录注册消息收发,支持TXT, IMAGE, VIDEO, AUDIO, FILE, LOCATION, 类型的message会话管理联系人管理

在开发linux SDK的时候我们利用了C++11提供的很多优良feature,例如lambda,shared ptr,thread等较新的功能,通过这些功能的使用,让我们能够迅速并且高效的开发出Linux SDK测试版。

Lambda是我们的代码逻辑阅读起来更清楚,shared ptr使我们对内存的管理更为简单,thread的使用使我们能迅速的建立好线程模型,加快开发的速度。

我们在Linux SDK porting layer实现了线程模型,数据库模型,定时器模型和HTTP模型
线程模型,利用C++11的thread进行封装数据库模型,使用Linux的sqliteHTTP模型,我们使用了Libcurl进行了封装定时器模型,我们使用了C++11进行了封装

我们对Linux SDK还在紧锣密鼓,夜以继日的紧张开发中,群组和实时音视频功能还在开发中,但是在开发过程中我们也遇到了些的问题,例如不linux平台对库的支持也不尽相同,所以势必会对我们的架构有些改变,有些重构的工作也在进行中,我们希望8月底能够实现大部分的功能。

选择linux SDK为开始主要是因为大多数的嵌入式智能平台还是以linux为主,所以首先开发Linux 版SDK也是必先的一步,感谢我们的工程师,我么的Linux SDK已经能够支持树莓派的开发环境,这对于很多开发者来说确实是个好消息。

如果想了解如何集成Linux SDK请参考环信IM Linux SDK 集成说明

展望

Linux SDK 只是实现我们ONE SDK 的第一步,我们下半年还要实现基于ONE SDK 的Android ,IOS,MAC OS, 还有主流物联网平台的SDK,通过借鉴Linux SDK的实现方式,我们认为实现ONE SDK是可以做到的。

我们还会进一步和主要IOT平台供应商合作,实现某个具体IOT平台的环信SDK,使环信即时通讯平台生态圈更加壮大。 查看全部
环信即时通讯SDK自2014年6月正式发布2.0版本至今已走过一个年头,从基本的单聊功能,到群聊功能,再到聊天室的实现,SDK不管是功能,稳定性,还是易集成性都在一步一步的走向完善与稳定,感谢开发者们给与提供的反馈与帮助,使我们的SDK迅速的在诸多方面得到提高与改进。

随着现在物联网的兴起,环信现在的SDK的架构对应对未来物联网平台还是略有不足,使我们不得不在今年年初就考虑到如何去改善我们的架构,使之能够较容易的适配到各个主流平台和物联网平台。

现在的Android, IOS, SDK都是各自维护了自己逻辑,给2.0开发带来了很多不便,相同的功能需要维护两份代码,同一个bug要在不同的平台修复两次,由于不同平台的实现,导致Android,IOS架构设计不统一,API不一致,再加上在不同的平台开发的工程师之间由于不同的实现导致沟通问题诸多,这样导致的问题就是,不同平台的开发进度大多数情况下都不相同。

所以针对以上的问题,我们今年年初就计划我们SDK3.0的开发,我们称之为ONE SDK,基本的理念就是我们实现共同IM 内核,使代码可被不同的平台最大化的重用,但是设计和实现却是面临着巨大的挑战,如何适配到不同的平台,如何最大化的重用代码都是要面临的问题。

ONE SDK 架构设计
总体设计

20150806175739849.png


ONE SDK的设计总体分为3层,平台层-Platfrom layer,适配层-Porting layer,核心层-Common layer.

平台层会根据各平台的不同,实现不同的接口,开放符合平台层的API给第三方开发者。

适配层主要要适配到ONE SDK 核心层所需要的一些接口,起到承上启下的作用。

核心层主要提供IM 功能和业务逻辑,保证最大化的代码重用。

考虑到跨平台共享代码,我们ONE SDK主要是用C++这种跨平台的语言来实现。

平台层

我们计划要支持的平台为Android,IOS,MAC OS,Windows,Windows phone, Linux,Embedded Linux, 还有较为广泛应用的物联网平台-IOT OS。

我们会针对不同平台提供给开发者,和平台一致API规范,使各平台的开发者无难度的集成SDK,例如我们会提供JAVA给Android,Objective-C 给IOS和MAC, C++ 给Linux, IOT平台。


适配层

20150806181806647.png


适配层主要就是各平台需要实现核心层所需要的一些接口类例如,上图给出的线程模型,定时器模型,数据库模型,还有HTTP模型。

这些模型都是和平台相关的,例如有的平台提供sqllite的访问,有的没有,有的线程模型和定时器模型都有自己的实现方式例如物联网IOT OS,所以实现了上述的模型,就可以使核心层可以工作,不过也可能会遇到一些问题,这都会在具体的实现中会具体的应对,但结构是清晰的。

其实例如Android,Linux, IOS, Mac OS,Windows都是支持C++11,也就是说都是支持C++11所提供的线程模型,所以这几个操作系统的线程模型的实现应该是同样的,所以代码是可以共享的, 但是数据库Anroid NDK是不支持sqlite访问,所以这部分Android有两种策略一个是集成sqlite源代码,二是回调给JAVA层,前一种策略是代码逻辑清晰,但坏处就是增加了代码量。

还有就是HTTP模型,默认的android,iOS,Mac OS,windows都有自己的API提供,所以ONE SDK策略就是如果有平台有原生的HTTP API 支持我们就会尽量用平台的,但是类似linux,就需要第三方库的支持例如libcurl.

所以综上所述适配层的意义重大,保证我们ONE SDK代码共享最大化的目的。

核心层

核心层是具体实现环信相关功能的模块,它里面也包含的几个部分,核心业务逻辑API实现,抽象协议层,和独立实时音视频模块。

Core Common

20150806191008517.png


业务逻辑层,负责提供基本的IM功能。

会话管理
消息收发
登录鉴权
连接管理

Audio/Video Call

实时音视频模块是一个独立的模块,可以单独存在,这样可以灵活处理,不需要时不用加载此模块。

20150806191418690.png


实时音视频
多人语音

Abstract Protocol Layer

协议抽象层,主要用来处理具体的IM底层协议,这层是比较独立的主要实现环信定义的IM传输协议,也为为日后协议改造,扩展提供承上启下的作用。

20150806192326297.png

  • 定义抽象消息载体
  • 基本的消息发送
  • 基本的消息回调
  • 定义基本的通知

上述ONE SDK架构是我们计划要实现的,现在一些基本的设计已经在Linux SDK上得到了实现,下面让我们继续了解下Linux SDK。

Linux SDK

经过几个月的开发,我们已经推出了Linux SDK测试版,有兴趣的开发者可以小试一下去我们的官网 http://www.easemob.com/downloads 下载。

通过EMChatClient Facade类开发者可以访问到任何IM停供的功能
  • 登录注册
  • 消息收发,支持TXT, IMAGE, VIDEO, AUDIO, FILE, LOCATION, 类型的message
  • 会话管理
  • 联系人管理


在开发linux SDK的时候我们利用了C++11提供的很多优良feature,例如lambda,shared ptr,thread等较新的功能,通过这些功能的使用,让我们能够迅速并且高效的开发出Linux SDK测试版。

Lambda是我们的代码逻辑阅读起来更清楚,shared ptr使我们对内存的管理更为简单,thread的使用使我们能迅速的建立好线程模型,加快开发的速度。

我们在Linux SDK porting layer实现了线程模型,数据库模型,定时器模型和HTTP模型
  • 线程模型,利用C++11的thread进行封装
  • 数据库模型,使用Linux的sqlite
  • HTTP模型,我们使用了Libcurl进行了封装
  • 定时器模型,我们使用了C++11进行了封装


我们对Linux SDK还在紧锣密鼓,夜以继日的紧张开发中,群组和实时音视频功能还在开发中,但是在开发过程中我们也遇到了些的问题,例如不linux平台对库的支持也不尽相同,所以势必会对我们的架构有些改变,有些重构的工作也在进行中,我们希望8月底能够实现大部分的功能。

选择linux SDK为开始主要是因为大多数的嵌入式智能平台还是以linux为主,所以首先开发Linux 版SDK也是必先的一步,感谢我们的工程师,我么的Linux SDK已经能够支持树莓派的开发环境,这对于很多开发者来说确实是个好消息。

如果想了解如何集成Linux SDK请参考环信IM Linux SDK 集成说明

展望

Linux SDK 只是实现我们ONE SDK 的第一步,我们下半年还要实现基于ONE SDK 的Android ,IOS,MAC OS, 还有主流物联网平台的SDK,通过借鉴Linux SDK的实现方式,我们认为实现ONE SDK是可以做到的。

我们还会进一步和主要IOT平台供应商合作,实现某个具体IOT平台的环信SDK,使环信即时通讯平台生态圈更加壮大。
2
评论

开发经验:如何优雅的进行页面间的跳转 移动开发 iOS

oscar1212 发表了文章 • 1759 次浏览 • 2015-07-31 14:57 • 来自相关话题

在你的开发过程中,是否遇到过如下的需求:
在tableView类型的展示列表中,点击每个cell中人物头像都可以跳转到人物详情,可参见微博中的头像,同理包括转发、评论按钮、各种链接及linkcard。跳转到任意页面
产品要求,某个页面的不同banner图,点击可以跳转到任何一个页面,可能是原生的页面A、页面B,或者是web页C。在web页面,可以跳转到任何一个原生页面。在远程推送中跳转到任意指定的页面。

以上2种需求,我想大多数开发者都遇到过,并且可以实现这种功能。毕竟,这是比较基础的功能。但是代码未必那么优雅。

一般处理办法

针对1.,一般初学者会用target或者block等方法在tableView的代理方法拿到事件,并把要执行的跳转写到controller里。功能是可以实现的,但问题是这种cell及相似的cell(布局有些变化,或者多几个少几个控件)一般出现在多个页面。这样的话相同的代码就会出现在多个地方。就算把跳转方法抽取出来写成category,但是target或者block总是每个地方都要写的。
针对2.,初级的方法是每个地方写一坨判断及跳转,高级一些是抽取出来写在基类或者category。

优雅的解决办法

纵观上面各种情况,总结起来就是一句话,在任意的地方触发事件(可以是推送,拦截的js跳转,各种控件的点击事件)可以跳转到任意界面。所以我们可以统一用一个控制跳转的manager来完成跳转。
与后端约定好数据结构,例如:
NSDictionary *target = @{@"action" : @"user",
@"data" : @{@"user_id" : @(123456)}};



就是跳转到id为123456的用户页面,如果跳转需要更多的数据,可以在data的value里面继续添加。
创建一个用来跳转的类,可以起的牛x的名字,XXCoreActionManager。
创建一个类方法:+ (BOOL)doActionForTarget:(NSDictionary *)target{
//根据你的app结构,来取得你当前的controller,由它来进行跳转
UIApplication *application = [UIApplication sharedApplication];
AppDelegate *myAppDelegate = (AppDelegate *)[application delegate];
UIViewController *viewController;
if ([myAppDelegate getTabbarSelectedView]) {
viewController = [myAppDelegate getTabbarSelectedView].visibleViewController;
}else {
return NO;
}

if([json[@"action"] isEqualToString:@"film_view"]){
MFMaterialListViewController *materialListVC = [[MFMaterialListViewController alloc] initWithNibName:@"MFMaterialListViewController" bundle:nil];
materialListVC.hidesBottomBarWhenPushed = YES;
materialListVC.filmId = json[@"data"][@"film_id"];
[viewController.navigationController pushViewController:materialListVC animated:YES];
return YES;
}else if([json[@"action"] isEqualToString:@"home"]){
[myAppDelegate getTabbar].selectedIndex = 0;
[viewController.navigationController popToRootViewControllerAnimated:YES];
return YES;
}

return NO;
}在刚才定义的数据结构中,action的值为需要跳转的页面,data的值跳转所需要要的参数,比如id、type等。服务器只需要传入相应的数据就可以用[XXCoreActionManager doActionForTarget:target];




针对头像、评论、转发等多处使用的子控件,可以把事件由自己接收,通过XXCoreActionManager来进行跳转。即做到了代码分离,使之成为真正独立的控件,便于复用。

下面是一个简单例子:implementation MFUserHeadButton
-(void)awakeFromNib{
[self addTarget:self action:@selector(toUserDetail) forControlEvents:UIControlEventTouchUpInside];

}

- (void)toUserDetail{
NSDictionary *target = @{@"action":@"user",
@"data":@{@"user_id":@(self.tag)}};
[XXCoreActionManager doActionForTarget:target];

}这就是一个简单的实现跳转到个人页功能的头像控件实现。

如果你问user_id的值怎么来的?

当然是configCell的时候传给view的tag的。

你可能会说,我的跳转需要多个参数啊,你一个tag不够用啊亲。

可以定义一个NSDictionary属性接收啊。

如果你用原生的UI控件,那让强大的runtime给你加喽- (void)setDict:(NSDictionary *)dict {
objc_setAssociatedObject(self, dictKey, dict, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (NSDictionary *)dict {
return objc_getAssociatedObject(self, dictKey);
}总结
通过XXCoreActionManager,你可以做到无论你身在何处(哪一个controller),要到何处去(跳转到哪一个controller),你只需要叫来XXCoreActionManager,告诉它你的目的地(target)。你就可以做到想跳就跳。真正的write once,use anywhere。针对各种有跳转功能的控件,可以做到真的解耦。只需要把它放到他需要显示的位置。告诉它对应的参数就可以了。方便复用和后期的维护。这次想说的只是一个思路,代码很简单。其实可以使用的地方还有很多。不只是跳转各位童鞋可以自己思考。有什么不明白的可以留言,如果觉得那里不合适更欢迎留言指教或交流。

写在后面的废话

从读大学接触到计算机技术这一领域,我就被这个圈子的氛围深深的触动了,这是一个如此自由、分享、开放的圈子。我从无数人的的分享中汲取着知识(开源的代码,分享的博客),我受益于这种环境,我就想对它做出回馈,写出这篇文章,即希望能帮助一些人,也希望能与大家有更多的交流。最后,谢谢那些无私的做出各种奉献的人。
 
来源:csdn 查看全部
在你的开发过程中,是否遇到过如下的需求:
  1. 在tableView类型的展示列表中,点击每个cell中人物头像都可以跳转到人物详情,可参见微博中的头像,同理包括转发、评论按钮、各种链接及linkcard。
  2. 跳转到任意页面

  • 产品要求,某个页面的不同banner图,点击可以跳转到任何一个页面,可能是原生的页面A、页面B,或者是web页C。
  • 在web页面,可以跳转到任何一个原生页面。
  • 在远程推送中跳转到任意指定的页面。


以上2种需求,我想大多数开发者都遇到过,并且可以实现这种功能。毕竟,这是比较基础的功能。但是代码未必那么优雅。

一般处理办法

针对1.,一般初学者会用target或者block等方法在tableView的代理方法拿到事件,并把要执行的跳转写到controller里。功能是可以实现的,但问题是这种cell及相似的cell(布局有些变化,或者多几个少几个控件)一般出现在多个页面。这样的话相同的代码就会出现在多个地方。就算把跳转方法抽取出来写成category,但是target或者block总是每个地方都要写的。
针对2.,初级的方法是每个地方写一坨判断及跳转,高级一些是抽取出来写在基类或者category。

优雅的解决办法

纵观上面各种情况,总结起来就是一句话,在任意的地方触发事件(可以是推送,拦截的js跳转,各种控件的点击事件)可以跳转到任意界面。所以我们可以统一用一个控制跳转的manager来完成跳转。
  • 与后端约定好数据结构,例如:

NSDictionary *target = @{@"action" : @"user",
@"data" : @{@"user_id" : @(123456)}};



就是跳转到id为123456的用户页面,如果跳转需要更多的数据,可以在data的value里面继续添加。
  • 创建一个用来跳转的类,可以起的牛x的名字,XXCoreActionManager。

创建一个类方法:
+ (BOOL)doActionForTarget:(NSDictionary *)target{
//根据你的app结构,来取得你当前的controller,由它来进行跳转
UIApplication *application = [UIApplication sharedApplication];
AppDelegate *myAppDelegate = (AppDelegate *)[application delegate];
UIViewController *viewController;
if ([myAppDelegate getTabbarSelectedView]) {
viewController = [myAppDelegate getTabbarSelectedView].visibleViewController;
}else {
return NO;
}

if([json[@"action"] isEqualToString:@"film_view"]){
MFMaterialListViewController *materialListVC = [[MFMaterialListViewController alloc] initWithNibName:@"MFMaterialListViewController" bundle:nil];
materialListVC.hidesBottomBarWhenPushed = YES;
materialListVC.filmId = json[@"data"][@"film_id"];
[viewController.navigationController pushViewController:materialListVC animated:YES];
return YES;
}else if([json[@"action"] isEqualToString:@"home"]){
[myAppDelegate getTabbar].selectedIndex = 0;
[viewController.navigationController popToRootViewControllerAnimated:YES];
return YES;
}

return NO;
}
在刚才定义的数据结构中,action的值为需要跳转的页面,data的值跳转所需要要的参数,比如id、type等。服务器只需要传入相应的数据就可以用
[XXCoreActionManager doActionForTarget:target];




  • 针对头像、评论、转发等多处使用的子控件,可以把事件由自己接收,通过XXCoreActionManager来进行跳转。即做到了代码分离,使之成为真正独立的控件,便于复用。


下面是一个简单例子:
implementation MFUserHeadButton
-(void)awakeFromNib{
[self addTarget:self action:@selector(toUserDetail) forControlEvents:UIControlEventTouchUpInside];

}

- (void)toUserDetail{
NSDictionary *target = @{@"action":@"user",
@"data":@{@"user_id":@(self.tag)}};
[XXCoreActionManager doActionForTarget:target];

}
这就是一个简单的实现跳转到个人页功能的头像控件实现。

如果你问user_id的值怎么来的?

当然是configCell的时候传给view的tag的。

你可能会说,我的跳转需要多个参数啊,你一个tag不够用啊亲。

可以定义一个NSDictionary属性接收啊。

如果你用原生的UI控件,那让强大的runtime给你加喽
- (void)setDict:(NSDictionary *)dict {
objc_setAssociatedObject(self, dictKey, dict, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (NSDictionary *)dict {
return objc_getAssociatedObject(self, dictKey);
}
总结
  1. 通过XXCoreActionManager,你可以做到无论你身在何处(哪一个controller),要到何处去(跳转到哪一个controller),你只需要叫来XXCoreActionManager,告诉它你的目的地(target)。你就可以做到想跳就跳。真正的write once,use anywhere。
  2. 针对各种有跳转功能的控件,可以做到真的解耦。只需要把它放到他需要显示的位置。告诉它对应的参数就可以了。方便复用和后期的维护。
  3. 这次想说的只是一个思路,代码很简单。其实可以使用的地方还有很多。不只是跳转各位童鞋可以自己思考。有什么不明白的可以留言,如果觉得那里不合适更欢迎留言指教或交流。


写在后面的废话

从读大学接触到计算机技术这一领域,我就被这个圈子的氛围深深的触动了,这是一个如此自由、分享、开放的圈子。我从无数人的的分享中汲取着知识(开源的代码,分享的博客),我受益于这种环境,我就想对它做出回馈,写出这篇文章,即希望能帮助一些人,也希望能与大家有更多的交流。最后,谢谢那些无私的做出各种奉献的人。
 
来源:csdn
0
评论

环信移动客服3.0上线签约国美在线、58到家、楚楚街9块9等龙头企业 开发者 移动开发 环信

admin 发表了文章 • 2125 次浏览 • 2015-07-29 11:23 • 来自相关话题

7月28日,环信B轮融资及移动客服新品发布会在北京JW万豪酒店举行。发布会上,环信CEO刘俊彦宣布,环信成功获得B轮融资,同时环信移动客服3.0产品也正式上线,而环信将以“连接人与商业”为愿景,开启万亿级企业云服务市场。






据悉,环信移动客服产品已经有国美在线、58到家、楚楚街等大批龙头企业签约,累计签约客服座席已经达4万个,而按艾媒咨询的报告显示,环信已占据市场份额第一的宝座。

发布会现场,据启动环信移动客服3.0产品上线的环信CTO马晓宇介绍,环信之所以受到市场如此欢迎,是因为环信移动客服是有别于传统客服的划时代产品。在环信CTO马晓宇看来,客服经历了三个时代——
传统 call center的时代: 互联网尚未普及,电话客服客户等待时间长,客户服务人员压力大,工作重复内容多;到了PC网页客服时代,随着互联网的普及,网页客服的成本明显小于电话客服,客户服务人员工作量较小,客户满意度有所提高,但相应依然不能及时有效;当今,随着智能手机用户的快速增长,客户要求能够随时在移动端获取咨询服务。移动端客服的重要性将不断上升。移动客服时代随之到来。





然而在环信基于IM长连接技术推出移动客服之前,业界并没有一款真正适合移动端和社交化时代的可靠的云端移动客服产品。此前,业界普遍存在的是两种移动客服产品,
一类是工单客服,可以被视为移动客服1.0,基于工单方式和客服交互,技术实现简单,但无法做到实时交互,沟通效率低,用户体验差。另一类是轮询技术客服,可以被视为移动客服2.0,基于HTTP轮询技术,通过不断向服务器发送查询请求来准实时的收取消息。不能做到实时收取消息,流量和电量消耗高,APP在后台时无法接收消息,容易丢失客户。
而环信推出的移动客服产品是业界唯一一款具有IM长连接技术的移动客服产品,这被视为更适合移动端的客服产品。

这一类型的移动客服可以定义为“交互型智能移动客服”,可以被视为移动客服3.0,以环信为代表的这一类新型移动客服是基于亿级IM长连接,系统稳定;智能机器人技术可处理大部分重复问题。相较环信移动客服的能力,传统的电话、工单、轮询客服在移动端和社交趋势下就显得捉襟见肘,有些OUT了。
 
环信移动客服实现了跨平台多渠道接入:支持 App、微信公众账号、微博、网页等,均可以快速统一接入客户服务后台管理。





其次,满足了开放性与自定义信息:这种新型的移动客服实现了代码开源、UI开源,还提供多套UI模版,便于与APP快速集成,平滑接入。同时第三方集成功能也很强大,可与第三方工单、知识库、CRM 系统等进行扩展集成。第三,富媒体消息交互体验:移动客服平台提供了基于IM技术的类似微信体验的友好富媒体消息交互,不仅可以实时收发文字、表情,还可以即时收发图片、位置、实时语音、还可自定义消息,大大方便了与客户的沟通交流。第四,精准客户画像功能:移动客服的IM沟通帮助企业辅助判断客户需求与诉求,通过自定义客户分类标签,客户再次访问时可获知客户的类型。并且还支持自定义会话小结,根据会话小结统计会话的分类,通过会话小结追踪客户诉求。通过轨迹分析功能,即通过发送客户访问页面的轨迹,判断客户意图,获取客户个性化细节,了解客户基础信息,分析客户行为,可以极大提高订单效率。第五,“智能机器人+智能知识库”:作为一套智能化的客服系统,让企业建立基于业务的智能知识库,智能辅助归结业务信息和应答客户信息,历史常见问题系统梳理,提高客服效率。“智能机器人+智能知识库”组合目前可自动回复80%常见问题,随着智能知识库的不断训练,这一比例能够提高到90%。第六、真正实现不丢订单:环信是中国乃至全球领先的即时通讯云服务提供商,上线1年来,已成为唯一一家经历了亿级长连接真实稳定运行的即时通讯云平台,中国主流的采用第三方即时通讯云服务的App几乎都是环信的客户,每日环信平台的消息量达到数亿条,有着即时通讯云领域亿级长连接的绝对垄断优势。环信基于IM长连接技术,帮助企业实现超线拉取排队会话,让等待时间过长或有订单需求的客户得到优先服务,提升客服效率,即使客户关闭会话,退出App,甚至关闭手机,基于IM长连接技术依然能找回客户会话,提升客服效率,不丢客户订单。同时,基于IM长连接技术,即使在断网或复杂网络切换时也依然能找回客户会话,不丢客户订单。第七、实现了质检系统透明管理:移动客服自带实时监控系统,可实时监控当前所有会话,管理员在线质检,在线查看会话信息,还提供了历史会话查询、质检考核。通过实时与历史查看,可以统计出客服代表的接入量、在线时间及应答等待时间。





环信CTO Johnson向大家介绍客服产品

总之,通过部署环信移动客服,较于传统客服产品可以节省成本约60%,在移动端省电省流量高达80%,同时留住70%会话客户,订单量和客单价均可以获得不同幅度提升。 查看全部
7月28日,环信B轮融资及移动客服新品发布会在北京JW万豪酒店举行。发布会上,环信CEO刘俊彦宣布,环信成功获得B轮融资,同时环信移动客服3.0产品也正式上线,而环信将以“连接人与商业”为愿景,开启万亿级企业云服务市场。

5.png


据悉,环信移动客服产品已经有国美在线、58到家、楚楚街等大批龙头企业签约,累计签约客服座席已经达4万个,而按艾媒咨询的报告显示,环信已占据市场份额第一的宝座

发布会现场,据启动环信移动客服3.0产品上线的环信CTO马晓宇介绍,环信之所以受到市场如此欢迎,是因为环信移动客服是有别于传统客服的划时代产品。在环信CTO马晓宇看来,客服经历了三个时代——
  1. 传统 call center的时代: 互联网尚未普及,电话客服客户等待时间长,客户服务人员压力大,工作重复内容多;
  2. 到了PC网页客服时代,随着互联网的普及,网页客服的成本明显小于电话客服,客户服务人员工作量较小,客户满意度有所提高,但相应依然不能及时有效;
  3. 当今,随着智能手机用户的快速增长,客户要求能够随时在移动端获取咨询服务。移动端客服的重要性将不断上升。移动客服时代随之到来。


9.png

然而在环信基于IM长连接技术推出移动客服之前,业界并没有一款真正适合移动端和社交化时代的可靠的云端移动客服产品。此前,业界普遍存在的是两种移动客服产品
  1. 一类是工单客服,可以被视为移动客服1.0,基于工单方式和客服交互,技术实现简单,但无法做到实时交互,沟通效率低,用户体验差。
  2. 另一类是轮询技术客服,可以被视为移动客服2.0,基于HTTP轮询技术,通过不断向服务器发送查询请求来准实时的收取消息。不能做到实时收取消息,流量和电量消耗高,APP在后台时无法接收消息,容易丢失客户。

而环信推出的移动客服产品是业界唯一一款具有IM长连接技术的移动客服产品,这被视为更适合移动端的客服产品。

这一类型的移动客服可以定义为“交互型智能移动客服”,可以被视为移动客服3.0,以环信为代表的这一类新型移动客服是基于亿级IM长连接,系统稳定;智能机器人技术可处理大部分重复问题。相较环信移动客服的能力,传统的电话、工单、轮询客服在移动端和社交趋势下就显得捉襟见肘,有些OUT了。
 
  • 环信移动客服实现了跨平台多渠道接入:支持 App、微信公众账号、微博、网页等,均可以快速统一接入客户服务后台管理。


8.png

  • 其次,满足了开放性与自定义信息:这种新型的移动客服实现了代码开源、UI开源,还提供多套UI模版,便于与APP快速集成,平滑接入。同时第三方集成功能也很强大,可与第三方工单、知识库、CRM 系统等进行扩展集成。
  • 第三,富媒体消息交互体验:移动客服平台提供了基于IM技术的类似微信体验的友好富媒体消息交互,不仅可以实时收发文字、表情,还可以即时收发图片、位置、实时语音、还可自定义消息,大大方便了与客户的沟通交流。
  • 第四,精准客户画像功能:移动客服的IM沟通帮助企业辅助判断客户需求与诉求,通过自定义客户分类标签,客户再次访问时可获知客户的类型。并且还支持自定义会话小结,根据会话小结统计会话的分类,通过会话小结追踪客户诉求。通过轨迹分析功能,即通过发送客户访问页面的轨迹,判断客户意图,获取客户个性化细节,了解客户基础信息,分析客户行为,可以极大提高订单效率。
  • 第五,“智能机器人+智能知识库”:作为一套智能化的客服系统,让企业建立基于业务的智能知识库,智能辅助归结业务信息和应答客户信息,历史常见问题系统梳理,提高客服效率。“智能机器人+智能知识库”组合目前可自动回复80%常见问题,随着智能知识库的不断训练,这一比例能够提高到90%。
  • 第六、真正实现不丢订单:环信是中国乃至全球领先的即时通讯云服务提供商,上线1年来,已成为唯一一家经历了亿级长连接真实稳定运行的即时通讯云平台,中国主流的采用第三方即时通讯云服务的App几乎都是环信的客户,每日环信平台的消息量达到数亿条,有着即时通讯云领域亿级长连接的绝对垄断优势。环信基于IM长连接技术,帮助企业实现超线拉取排队会话,让等待时间过长或有订单需求的客户得到优先服务,提升客服效率,即使客户关闭会话,退出App,甚至关闭手机,基于IM长连接技术依然能找回客户会话,提升客服效率,不丢客户订单。同时,基于IM长连接技术,即使在断网或复杂网络切换时也依然能找回客户会话,不丢客户订单。
  • 第七、实现了质检系统透明管理:移动客服自带实时监控系统,可实时监控当前所有会话,管理员在线质检,在线查看会话信息,还提供了历史会话查询、质检考核。通过实时与历史查看,可以统计出客服代表的接入量、在线时间及应答等待时间。


6.png

环信CTO Johnson向大家介绍客服产品

总之,通过部署环信移动客服,较于传统客服产品可以节省成本约60%,在移动端省电省流量高达80%,同时留住70%会话客户,订单量和客单价均可以获得不同幅度提升。
0
评论

gcm推送 移动开发 Android

admin 发表了文章 • 6800 次浏览 • 2015-07-27 15:12 • 来自相关话题

一.gcm前期准备





 
Apple有apns推送,Google有gcm推送,iOS接收通知调用系统通知栏提示,Android接收通知启动应用调用通知栏提示。
相对于apns,gcm则多了一些限制,需要一些必备条件达到才可以使用。
1.在国内,首先就是Google被墙,无法连接到Google服务器,需要你走VPN或者其它方式可以连接到Google服务器。
2.在你的开发环境下,需要通过Android SDK Manager—>Extras下安装Google Play services,成功之后在你的SDK文件/sdk/extras/google/google_play_services/libproject下会看到google-play-services_lib类库,可以从里面直接复制jar包到你的项目libs下
3.Android客户端,要求安装了Google核心服务Google Play服务,Google Play 商店才能使用gcm





以上是Google官方文档描述:
大意就是gcm要求设备运行在Android系统2.2或更高版本并且安装了Google play商店应用,或者虚拟机运行在Android系统2.2版本的并且支持Google API,但是并不限制你的应用必须部署在Google play 商店。
然而,如果你想要使用gcm 新的API就需要设备运行在Android系统2.3或更高版本,或者使用虚拟机运行在Android系统2.3并且支持Google API
在一个现有连接Google服务的设备上,对于前置3.0的设备,就要求在Android设备上设置Google账号,4.0.4或者更高版本则不需要设置Google账号
注:gcm只是简单的推送一个通知到客户端,其消息内容应小于4Kb,Google服务器存储时间为4个星期。在客户端,gcm是通过客户端设备注册一个系统广播来唤醒应用并发出通知提示,所以这个时候客户端不需要一直运行来接收消息,gcm一次发送最多可发送100个用户
 
二.官网创建项目获取信息

去Google Developers Console(https://console.developers.google.com/project)创建项目,输入你的project name和project id,创建成功如下图:





在应用中我们会用到这个project number,再去Credentials下创建一个server key,得到的api key会在自己的服务器端用到,如图




顺便说一下,默认Cloud Messaging for Android是可用的,如果不能用,就需要去API & auth—> API下查看Cloud Messaging for Android是否disable

三.创建一个客户端app

首先要在AndroidManifest.xml文件配置gcm权限等信息<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />//当GCM需要谷歌账户(设备版本低于4.0.4时需要)
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission android:name="applicationPackage.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="applicationPackage.permission.C2D_MESSAGE" />
applicationPackage要改成自己的报名

android:minSdkVersion="8"不得低于8





根据官网文档介绍:

1.我们应该在配置文件注册一个系统广播<receiver
android:name="com.google.android.gms.gcm.GcmReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.example.gcm" />
</intent-filter>
</receiver>
2.注册监听通知服务(在app中创建一个服务类并继承GcmListenerService类)<pre name="code" class="html"><service
android:name="com.example.MyGcmListenerService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>

public class MyGcmListenerService extends GcmListenerService {

@Override
public void onMessageReceived(String from, Bundle data) {
String message = data.getString("message");
/**
* Production applications would usually process the message here.
* Eg: - Syncing with server.
* - Store message in local database.
* - Update UI.
*/

/**
* In some cases it may be useful to show a notification indicating to the user
* that a message was received.
*/
sendNotification(message);
}
// [END receive_message]

/**
* Create and show a simple notification containing the received GCM message.
*
* @param message GCM message received.
*/
private void sendNotification(String message) {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);

Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_stat_ic_notification)
.setContentTitle("this is a new new GCM Message")
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);

NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
}
 
3.注册监听token改变的服务(在app中创建一个服务类继承InstanceIDListenerService类,本服务存在于新的Google play服务版本上) android:name="com.example.MyInstanceIDListenerService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.gms.iid.InstanceID"/>
</intent-filter>
</service>

public class MyInstanceIDListenerService extends InstanceIDListenerService {

@Override
public void onTokenRefresh() {
// Fetch updated Instance ID token and notify our app's server of any changes (if applicable).
}
}
 
gcm通过注册的系统广播可以自行启动GcmListenerService类,所以不需要在app创建一个广播类

注册token

App发送 project number到GCM Server注册接收推送信息。 

GCM Server 向App返回token(token是GCM服务器自行生产的,能够保证某一终端设备上的某一个应用,很重要)。 
在设备上应该先判断是否安装了Google play 服务int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
GooglePlayServicesUtil.getErrorDialog(resultCode, this, PLAY_SERVICES_RESOLUTION_REQUEST).show();//会提示错误对话框,其他错误信息可参考官网API
} else {
Log.i(TAG, "This device is not supported.”);
}
 
 
Google play服务存在,那接下来就需要去注册token了,在上边创建项目得到的project number在这里就需要用它来注册token










 InstanceID instanceID = InstanceID.getInstance(this);
String token = instanceID.getToken(PROJECT_NUMBER,
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
 
对于旧版本还是要使用以下方式来注册token(用于Google play 服务7.5版本之前)GoogleCloudMessaging.getInstance(Context).register(PROJECT_NUMBER);
 
在自己的服务器端注册api key

App向我们自己服务器发送token(推送消息的时候要使用token,GCM服务器是使用token来确定某一终端设备上的某一个应用接收消息的,所以第三方服务器需要保存它,需要注意的是token很长,存数据库时需要注意字段长度) ,将我们在上边create new key 得到的apikey添加到自己的服务器端保存,我们的服务器向GCM Server发送消息,传递apikey和token ,GCM Server把消息推送给App 
最后注意一下,关于app卸载出现的问题,看一下官方的介绍






app会发生卸载过程并不能很快完成,卸载app需要花时间从GCM移除当前关联的token,这个过程就会出现发送消息是成功的,但是不能到达app客户端,在最后,token被移除了,服务器端发送的消息失败,得到一个NotRegistered错误,这个时候就应该在服务器端删除相对应的token 查看全部
一.gcm前期准备

20150727113000901_(1).jpg

 
Apple有apns推送,Google有gcm推送,iOS接收通知调用系统通知栏提示,Android接收通知启动应用调用通知栏提示。
相对于apns,gcm则多了一些限制,需要一些必备条件达到才可以使用。
1.在国内,首先就是Google被墙,无法连接到Google服务器,需要你走VPN或者其它方式可以连接到Google服务器。
2.在你的开发环境下,需要通过Android SDK Manager—>Extras下安装Google Play services,成功之后在你的SDK文件/sdk/extras/google/google_play_services/libproject下会看到google-play-services_lib类库,可以从里面直接复制jar包到你的项目libs下
3.Android客户端,要求安装了Google核心服务Google Play服务,Google Play 商店才能使用gcm

20150727113107623.jpg

以上是Google官方文档描述:
大意就是gcm要求设备运行在Android系统2.2或更高版本并且安装了Google play商店应用,或者虚拟机运行在Android系统2.2版本的并且支持Google API,但是并不限制你的应用必须部署在Google play 商店。
然而,如果你想要使用gcm 新的API就需要设备运行在Android系统2.3或更高版本,或者使用虚拟机运行在Android系统2.3并且支持Google API
在一个现有连接Google服务的设备上,对于前置3.0的设备,就要求在Android设备上设置Google账号,4.0.4或者更高版本则不需要设置Google账号
注:gcm只是简单的推送一个通知到客户端,其消息内容应小于4Kb,Google服务器存储时间为4个星期。在客户端,gcm是通过客户端设备注册一个系统广播来唤醒应用并发出通知提示,所以这个时候客户端不需要一直运行来接收消息,gcm一次发送最多可发送100个用户
 
二.官网创建项目获取信息

去Google Developers Console(https://console.developers.google.com/project)创建项目,输入你的project name和project id,创建成功如下图:

6.jpg

在应用中我们会用到这个project number,再去Credentials下创建一个server key,得到的api key会在自己的服务器端用到,如图
7.jpg

顺便说一下,默认Cloud Messaging for Android是可用的,如果不能用,就需要去API & auth—> API下查看Cloud Messaging for Android是否disable

三.创建一个客户端app

首先要在AndroidManifest.xml文件配置gcm权限等信息
<uses-permission android:name="android.permission.INTERNET" />  
<uses-permission android:name="android.permission.GET_ACCOUNTS" />//当GCM需要谷歌账户(设备版本低于4.0.4时需要)
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission android:name="applicationPackage.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="applicationPackage.permission.C2D_MESSAGE" />

applicationPackage要改成自己的报名

android:minSdkVersion="8"不得低于8

8.jpg

根据官网文档介绍:

1.我们应该在配置文件注册一个系统广播
<receiver  
android:name="com.google.android.gms.gcm.GcmReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.example.gcm" />
</intent-filter>
</receiver>

2.注册监听通知服务(在app中创建一个服务类并继承GcmListenerService类)
<pre name="code" class="html"><service  
android:name="com.example.MyGcmListenerService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>

public class MyGcmListenerService extends GcmListenerService {

@Override
public void onMessageReceived(String from, Bundle data) {
String message = data.getString("message");
/**
* Production applications would usually process the message here.
* Eg: - Syncing with server.
* - Store message in local database.
* - Update UI.
*/

/**
* In some cases it may be useful to show a notification indicating to the user
* that a message was received.
*/
sendNotification(message);
}
// [END receive_message]

/**
* Create and show a simple notification containing the received GCM message.
*
* @param message GCM message received.
*/
private void sendNotification(String message) {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);

Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_stat_ic_notification)
.setContentTitle("this is a new new GCM Message")
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);

NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
}

 
3.注册监听token改变的服务(在app中创建一个服务类继承InstanceIDListenerService类,本服务存在于新的Google play服务版本上)
 android:name="com.example.MyInstanceIDListenerService"  
android:exported="false">
<intent-filter>
<action android:name="com.google.android.gms.iid.InstanceID"/>
</intent-filter>
</service>

public class MyInstanceIDListenerService extends InstanceIDListenerService {

@Override
public void onTokenRefresh() {
// Fetch updated Instance ID token and notify our app's server of any changes (if applicable).
}
}

 
gcm通过注册的系统广播可以自行启动GcmListenerService类,所以不需要在app创建一个广播类

注册token

App发送 project number到GCM Server注册接收推送信息。 

GCM Server 向App返回token(token是GCM服务器自行生产的,能够保证某一终端设备上的某一个应用,很重要)。 

在设备上应该先判断是否安装了Google play 服务
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);  
if (resultCode != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
GooglePlayServicesUtil.getErrorDialog(resultCode, this, PLAY_SERVICES_RESOLUTION_REQUEST).show();//会提示错误对话框,其他错误信息可参考官网API
} else {
Log.i(TAG, "This device is not supported.”);
}

 
 
Google play服务存在,那接下来就需要去注册token了,在上边创建项目得到的project number在这里就需要用它来注册token

10.jpg


9.jpg

 
InstanceID instanceID = InstanceID.getInstance(this);  
String token = instanceID.getToken(PROJECT_NUMBER,
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);

 
对于旧版本还是要使用以下方式来注册token(用于Google play 服务7.5版本之前)
GoogleCloudMessaging.getInstance(Context).register(PROJECT_NUMBER);  

 
在自己的服务器端注册api key

App向我们自己服务器发送token(推送消息的时候要使用token,GCM服务器是使用token来确定某一终端设备上的某一个应用接收消息的,所以第三方服务器需要保存它,需要注意的是token很长,存数据库时需要注意字段长度) ,将我们在上边create new key 得到的apikey添加到自己的服务器端保存,我们的服务器向GCM Server发送消息,传递apikey和token ,GCM Server把消息推送给App 
最后注意一下,关于app卸载出现的问题,看一下官方的介绍

11.jpg


app会发生卸载过程并不能很快完成,卸载app需要花时间从GCM移除当前关联的token,这个过程就会出现发送消息是成功的,但是不能到达app客户端,在最后,token被移除了,服务器端发送的消息失败,得到一个NotRegistered错误,这个时候就应该在服务器端删除相对应的token
0
评论

开发实战:Android自定义标题栏 Android 移动开发

oscar1212 发表了文章 • 2240 次浏览 • 2015-07-24 15:48 • 来自相关话题

本文要讲自己定义一个标题栏,能加事件。然后可以移值到不同的手机上,基本上不用改什么,调用也很简单

在layout文件夹下,新建一个XML。名字叫做layout_title_bar.xml然后来看看布局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="45.0dip"
android:background="@drawable/bg_title_bar"
android:gravity="top" >

<ImageView
android:id="@+id/title_bar_menu_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="3.0dip"
android:layout_marginRight="3.0dip"
android:layout_marginTop="3.0dip"
android:gravity="center"
android:src="@drawable/ic_top_bar_category" />

<ImageView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_toRightOf="@id/title_bar_menu_btn"
android:background="@drawable/ic_top_divider" />

<TextView
android:id="@+id/title_bar_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:ellipsize="end"
android:gravity="center"
android:paddingLeft="75.0dip"
android:paddingRight="75.0dip"
android:singleLine="true"
android:text="Java学习宝典"
android:textColor="#ffffff"
android:textSize="22sp" />

</RelativeLayout> 看下效果:





接下要就是要用了,在要用到的地方:我这里是activity_main.xml文件中:

加上一句:  <include layout="@layout/layout_title_bar" />这样就行了,

然后我们要给标题栏上的按钮添加事件,这个更加简单了:

在MainActivity.java(对应activity_main.xml)中,onCreate函数中添加:事件可以自己改,我这里是让它控制左右滑动的功能。
ImageView menuImg = (ImageView) findViewById(R.id.title_bar_menu_btn);
menuImg.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View arg0) {
if (!menuIsShow)
showMenu();
else {
hideMenu();
}

}

}); 这样就可以了:

我们来看看效果






这就是效果了,很简单吧,想用直接把上面的布局复制过去就OK了!
 
作者:林炳文Evankaka 查看全部
本文要讲自己定义一个标题栏,能加事件。然后可以移值到不同的手机上,基本上不用改什么,调用也很简单

在layout文件夹下,新建一个XML。名字叫做layout_title_bar.xml然后来看看布局:
<?xml version="1.0" encoding="utf-8"?>  
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="45.0dip"
android:background="@drawable/bg_title_bar"
android:gravity="top" >

<ImageView
android:id="@+id/title_bar_menu_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="3.0dip"
android:layout_marginRight="3.0dip"
android:layout_marginTop="3.0dip"
android:gravity="center"
android:src="@drawable/ic_top_bar_category" />

<ImageView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_toRightOf="@id/title_bar_menu_btn"
android:background="@drawable/ic_top_divider" />

<TextView
android:id="@+id/title_bar_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:ellipsize="end"
android:gravity="center"
android:paddingLeft="75.0dip"
android:paddingRight="75.0dip"
android:singleLine="true"
android:text="Java学习宝典"
android:textColor="#ffffff"
android:textSize="22sp" />

</RelativeLayout>
看下效果:

20150220004910963.png

接下要就是要用了,在要用到的地方:我这里是activity_main.xml文件中:

加上一句:  <include layout="@layout/layout_title_bar" />这样就行了,

然后我们要给标题栏上的按钮添加事件,这个更加简单了:

在MainActivity.java(对应activity_main.xml)中,onCreate函数中添加:事件可以自己改,我这里是让它控制左右滑动的功能。
ImageView menuImg = (ImageView) findViewById(R.id.title_bar_menu_btn);  
menuImg.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View arg0) {
if (!menuIsShow)
showMenu();
else {
hideMenu();
}

}

});
这样就可以了:

我们来看看效果

20150220004942958.gif


这就是效果了,很简单吧,想用直接把上面的布局复制过去就OK了!
 
作者:林炳文Evankaka
0
评论

中国互联网大会感受:技术人员最好的创业时代 云计算 移动开发 环信

admin 发表了文章 • 1422 次浏览 • 2015-07-24 15:25 • 来自相关话题

“年年岁岁花相似,岁岁年年人不同”,用这句千古名句来形容中国互联网大会的发展历程可以说再贴切不过了。在经历了互联网的1.0时代(PC互联网)、2.0时代(移动互联网)后,互联网的发展正快速步入下一个迭代周期,你可以认为是3.0时代,也可以给这个时代打上一个互联网+的标签。总之,当下这个时代互联网已不再是某个或某些企业的专属,谈全民互联网甚至也不觉得夸张。 在日前举办的第十四届中国互联网大会上,笔者也选取了三个非常有代表性的企业进行采访报道,看看透过它们是否能觉察出一些互联网+的典型特征。这三家企业分别是传统互联网的代表百度、传统制造业的代表联想,以及新兴的科技型创业企业环信。要说本次中国互联网大会上三家企业的所讲所展,有一个共同点是它们都在做云相关的内容,当然不同就多了去了,这里也不细说了,毕竟是三家几乎不搭杠的企业。 

首先,我们来聊聊环信。 

作为一家刚刚成立不过2年多的创业型企业,可能很多人还不太熟悉,这里先做个介绍。环信即时通讯云成立于2013年4月,是一家提供移动即时通讯能力的云计算 PaaS (Platform as a Service, 平台即服务) 平台服务商。 

这么听起来可能还是有些难懂,我们举个例子来进一步说明一下,即时通讯相信大家并不陌生,电话、QQ、微信之类的都算是即时通讯工具,即时通讯云简单理解就是用于承载这些工具的平台。而基于该平台,环信有自己开发的即时通讯工具移动客服。





 
环信CEO刘俊彦
 
据环信CEO刘俊彦介绍,目前其即时通讯云平台上线已一年多时间,SDK(Software Development Kit,软件开发工具包)覆盖用户近1个亿,有3万余个APP集成了该平台的即时通讯能力,终端用户覆盖超3个亿。而另一款拳头产品移动客服上线仅3个月,已签约数百家企业,包括国美在线、58到家在内的众多龙头企业都已是环信的用户。 

关于即时通讯云前文已有相应的解释,这里不再赘述,而是介绍下何谓移动客服。顾名思义,移动客服就是主要面向移动终端的客服,更准确地讲就是针对各种APP打造的客服工具。相信大家都打过400、800之类的客服电话,估计也用过PC端的网页客服,但随着移动互联网的兴起,这些方式在应对移动端客户的需求时已变得捉襟见肘。 

为什么呢?
 
一是移动端的量大,一个APP同时在线的人数可能在数十上百万;二是一旦APP打开,与客服之间的连接就是一直长期保持的关系。而在PC端,网页一旦关闭,与客服之间的对话就已经中断。无疑,移动客服后台数据中心所承载的压力和成本是要远高于传统客服方式的。刘俊彦表示,这也是移动客服市场的主要门槛之一。 

显然,作为国内较早进入该行业的企业,环信无疑已经占领了先机,前文已经提到了环信目前的用户情况,可以说非常不错,而更关键的是环信基本已经实现了收支平衡,要知道这在创业一两年的企业中可是为数不多的。 

放眼未来,环信也有着明确的规划。当前,其B轮融资已经到位,至于具体数额会于下周公布,但这些钱用在什么地方,他们早就想清楚了。刘俊彦表示,公司下一步的拓展方向主要是两个方面,一是由现在更多面向服务电商、O2O、互联网金融、互联网教育、医疗、旅游行业的移动客服向覆盖传统客服和移动客服的全领域扩张,二则是向物联网领域发展。 

具体来说,一是为了向用户提供客服的整体解决方案,而这么做的规划其实也是客户需求促使。据刘俊彦介绍,现在就有客户问他是不是能提供一整套完整的解决方案,而不需要移动客服找你们,网页客服找另一家,电话客服再找一家。二则是面向未来广阔的物联网市场,用不了几年,冰箱、洗衣机坏了的时候你已经无需再查找厂商的客服电话,而可能通过电器上的一个按钮就能实现报修,想一想是不是很美好。 

但话说回来,作为一个具有广阔市场前景的行业,环信所不可避免的要面临竞争,而且随着市场的不断扩大,竞争也会愈发剧烈。不过在笔者将这个问题抛给刘俊彦时,他倒是相当坦然。要说技术出身的人总是那么的质朴,可能是被问的多了回答的也多了,他很平淡地说,“市场这么大(美国大概是100亿美金,中国市场比这个还要大),我们能拿下个位数的份额,已经是足够大的体量了。现在更重要的是有更多的人进来,把这个行业先做大,做好用户服务。”

在写有关环信内容的最后,加一点刘俊彦的个人履历,17年研发,先后任职IONA、RedHat,专注于高并发消息中间件,实时消息系统,异构分布式企业系统集成,应用服务器。联想到最近一两年兴起的一批批创业公司,包括很多都在本次互联网大会上亮了相,笔者只想说,这是技术人员最好的创业时代。  查看全部
“年年岁岁花相似,岁岁年年人不同”,用这句千古名句来形容中国互联网大会的发展历程可以说再贴切不过了。在经历了互联网的1.0时代(PC互联网)、2.0时代(移动互联网)后,互联网的发展正快速步入下一个迭代周期,你可以认为是3.0时代,也可以给这个时代打上一个互联网+的标签。总之,当下这个时代互联网已不再是某个或某些企业的专属,谈全民互联网甚至也不觉得夸张。 在日前举办的第十四届中国互联网大会上,笔者也选取了三个非常有代表性的企业进行采访报道,看看透过它们是否能觉察出一些互联网+的典型特征。这三家企业分别是传统互联网的代表百度、传统制造业的代表联想,以及新兴的科技型创业企业环信。要说本次中国互联网大会上三家企业的所讲所展,有一个共同点是它们都在做云相关的内容,当然不同就多了去了,这里也不细说了,毕竟是三家几乎不搭杠的企业。 

首先,我们来聊聊环信。 

作为一家刚刚成立不过2年多的创业型企业,可能很多人还不太熟悉,这里先做个介绍。环信即时通讯云成立于2013年4月,是一家提供移动即时通讯能力的云计算 PaaS (Platform as a Service, 平台即服务) 平台服务商。 

这么听起来可能还是有些难懂,我们举个例子来进一步说明一下,即时通讯相信大家并不陌生,电话、QQ、微信之类的都算是即时通讯工具,即时通讯云简单理解就是用于承载这些工具的平台。而基于该平台,环信有自己开发的即时通讯工具移动客服。

lij5o8EpD9NFA_600.jpg

 
环信CEO刘俊彦
 
据环信CEO刘俊彦介绍,目前其即时通讯云平台上线已一年多时间,SDK(Software Development Kit,软件开发工具包)覆盖用户近1个亿,有3万余个APP集成了该平台的即时通讯能力,终端用户覆盖超3个亿。而另一款拳头产品移动客服上线仅3个月,已签约数百家企业,包括国美在线、58到家在内的众多龙头企业都已是环信的用户。 

关于即时通讯云前文已有相应的解释,这里不再赘述,而是介绍下何谓移动客服顾名思义,移动客服就是主要面向移动终端的客服,更准确地讲就是针对各种APP打造的客服工具。相信大家都打过400、800之类的客服电话,估计也用过PC端的网页客服,但随着移动互联网的兴起,这些方式在应对移动端客户的需求时已变得捉襟见肘。 

为什么呢?
 
  • 一是移动端的量大,一个APP同时在线的人数可能在数十上百万;
  • 二是一旦APP打开,与客服之间的连接就是一直长期保持的关系。而在PC端,网页一旦关闭,与客服之间的对话就已经中断。无疑,移动客服后台数据中心所承载的压力和成本是要远高于传统客服方式的。刘俊彦表示,这也是移动客服市场的主要门槛之一。 


显然,作为国内较早进入该行业的企业,环信无疑已经占领了先机,前文已经提到了环信目前的用户情况,可以说非常不错,而更关键的是环信基本已经实现了收支平衡,要知道这在创业一两年的企业中可是为数不多的。 

放眼未来,环信也有着明确的规划。当前,其B轮融资已经到位,至于具体数额会于下周公布,但这些钱用在什么地方,他们早就想清楚了。刘俊彦表示,公司下一步的拓展方向主要是两个方面,一是由现在更多面向服务电商、O2O、互联网金融、互联网教育、医疗、旅游行业的移动客服向覆盖传统客服和移动客服的全领域扩张,二则是向物联网领域发展。 

具体来说,一是为了向用户提供客服的整体解决方案,而这么做的规划其实也是客户需求促使。据刘俊彦介绍,现在就有客户问他是不是能提供一整套完整的解决方案,而不需要移动客服找你们,网页客服找另一家,电话客服再找一家。二则是面向未来广阔的物联网市场,用不了几年,冰箱、洗衣机坏了的时候你已经无需再查找厂商的客服电话,而可能通过电器上的一个按钮就能实现报修,想一想是不是很美好。 

但话说回来,作为一个具有广阔市场前景的行业,环信所不可避免的要面临竞争,而且随着市场的不断扩大,竞争也会愈发剧烈。不过在笔者将这个问题抛给刘俊彦时,他倒是相当坦然。要说技术出身的人总是那么的质朴,可能是被问的多了回答的也多了,他很平淡地说,“市场这么大(美国大概是100亿美金,中国市场比这个还要大),我们能拿下个位数的份额,已经是足够大的体量了。现在更重要的是有更多的人进来,把这个行业先做大,做好用户服务。”

在写有关环信内容的最后,加一点刘俊彦的个人履历,17年研发,先后任职IONA、RedHat,专注于高并发消息中间件,实时消息系统,异构分布式企业系统集成,应用服务器。联想到最近一两年兴起的一批批创业公司,包括很多都在本次互联网大会上亮了相,笔者只想说,这是技术人员最好的创业时代。 
0
评论

iOS开发生涯的初恋:详解Objective-C多项改进 iOS 移动开发

oscar1212 发表了文章 • 1662 次浏览 • 2015-07-24 11:42 • 来自相关话题

对于许多iOS开发者而言,Objective-C就是开发生涯中的初恋。如今,Swift正在以迅雷不及掩耳之势碾压Objective-C的份额,但Objective-C多项性能改进依然让开发者非常激动,本文作者对OC的提升进行了详解。
 
The Setup

下面的代码你们一定再熟悉不过了,我们来重温一下吧:
@property (strong, nonatomic) NSArray *someViews; 这绝对符合Objective-C完美主义开发者的标准。对它表示的属性,不同人有不同观点。但是,其中仍然存在着一些难以察觉的缺陷。

是否可能返回nil?

除非有现成的文件,或开发者全程都在一旁,否则光凭看是无法获取信息的。

除了UIView之外还有什么?

还是那句话——不确定。也许答案是reflection? 或许问题可以改成:除了UIView,有可能出现UIView子类吗?

看样子会出现诸多转换(casting)

因为是一队列……东西,知道那东西是什么之后,经过cast后才能利用。

会弱化Swift代码和可读性

很遗憾,Swift支持泛型(generics)就意味着(Objective-C )只会以optional的AnyObject集合的形式出现。如此一来,开发者要使用该属性就必须在Swift和Objective-C之间进行转换。

Nullability Annotations

单单一个属性就引发了这么多担忧,还挺让人不安的。如果代码本身引发很多质疑,出现error的可能性就大大增加,更别提在广为熟知的Objective-C和语言新秀Swift之间相互调用(interoperability)了。现在有了nullability annotations——我最爱的Objective-C新功能之一,问题就简单多了,编程也会省下很多麻烦。

intent.

现在谈到API,(intent.)可能会,也可能不会返回nil。简而言之,终于不用花费数小时来排除漏洞了。以下有三个选项:
nullable — Think UIViewnonnull — Think UIViewnull_unspecified — Think UIView!

再回到实例属性。假设在运行时迭代这个属性来创建某个用户界面,在相应的位置应该有UIButton和UIView。

但是,天哪!——不论怎么样它们也不应该是nil啊。现在出现如下的信息:
@property (strong, nonatomic, nonnull) NSArray *someViews; intent.大大提升了Objective-C,而且这个属性也不会在Swift里满满都是optional了。

开发者看看代码就知道有没有nil pointer了,太棒了!

计算机的静态检验和Swift的可用性都得到了提升,最重要的是实现了API的intent通讯。

泛型

……Objective-C开发者们举国欢庆。呜呼,泛型的恩泽终于笼罩大地,这无疑是那些开发者勇士们的功劳。

如果把Cocoa Touch比作孩子们的睡前故事,那么Objective-C就好比是主演,故事书肯定是以上面那段话结尾的。泛型的缺席一直以来是Objective-C开发者心头之痛,而诞生32年之后,Objective-C终于也支持泛型了。2015 WWDC上Swift 2成为了镁光灯下的宠儿,而Objective-C这一巨大的跨越却被忽视了,实在委屈。支持泛型将带来诸多改变,而且都是积极的改变。

现在可以定义属性,下指令给编译器来显示所有UIView:
@property (strong, nonatomic, nonnull) NSArray<UIView *> *someViews; 向属性强加UIView之外的东西时,编译器会报错。而且如今不用做大量头痛的转换(cast)了。

Objective-C支持泛型对Swift而言也是好消息。上次更新时,我们让Swift知道对象不应该是optional的,现在Swift还知道它们是UIViews,如此一来含混不清的AnyObject声明就不需要了。如今的Objective-C可以像C#、C++、Swift等语言一样通过<>括号来表示类型了。虽然通常是对协议表示一致性(conformance),但编译器知道何时、何地以及如何运用它们,且运用是经过推理的。

再进一步,可以用参数来表示扩展(extensions)、类别(categories)和类(classes),好处不仅仅体现在集合(collections)上。泛型的强大体现在整个Objective-C之中,集合仅仅是结果而已。举个例子,看看NSDictionary,开发者肯定会偷着乐吧:
@interface NSDictionary<KeyType, ObjectType> (Lookup)
- (nullable ObjectType)objectForKey:(KeyType)aKey;
@end 刚开始知道类型擦除(type erasure)是为了这个的时候,我有点儿不满意,但考虑到老旧的Objective-C程序堆积在一起的问题,也就释怀了。

类型擦除(type erasure)不但能实现二进制兼容,而且不改变Objective-C的执行时间。所以亲爱的开发者们,C#的泛型的确胜过其他语言,皱皱眉头,发几句牢骚就算了,日子还得继续呢。

KindOf Types

啊,这是最后一部分重要内容。再次调用之前定义的属性,就会显示UIView。判断里面包含着views和buttons是再正常不过的事。

这种情况下,添加如下代码会发生什么呢?
[self.someViews[0] addTarget:self action:selector(aMethod:) forControlEvents:UIControlEventTouchUpInside]; 啊,编译器警告。

这就对啦,因为即便可以在这个属性里插入一个button,就算可以假设是个UIView,button也不一定没有经过转换。

新的KindOf特性能够轻松解决这种始料未及的情况。我们再回到实例属性上:
@property (strong, nonatomic, nonnull) NSArray<__kindof UIView *> *someViews; 实际上我们已经告诉编译器:属性及其集合会出现一些UIView。这样在类型协议里显示更多我们之前看不到的信息。其本质向下转型(downcasting)。

这意味着上述代码编译没什么问题,因为编译器知道集合里肯定会出现一个button。

现在那些担忧就都解释得清了。

虽然不喜欢Swift的人可能会刻意夸大Objective-C的优点,但如今两种语言实现了互相调用,这是Objective-C所有提升的最大价值所在,我们应该心存感激。

毋庸置疑,Objective-C的确比以往更加强大。

总结

对我来说,Objective-C是开发生涯中的初恋,相比其他语言,它是那么与众不同——直到今天都是如此,它的好、它的坏都让我欲罢不能。虽然如今Swift正以迅雷不及掩耳之势征服着我的心,我还是希望Objective-C陪伴在身边。

Objective-C的提升能够帮助开发者写出更好的代码,这是好事。而且这些优势已经在Foundation中随处可见了。
 
来源:csdn 查看全部
对于许多iOS开发者而言,Objective-C就是开发生涯中的初恋。如今,Swift正在以迅雷不及掩耳之势碾压Objective-C的份额,但Objective-C多项性能改进依然让开发者非常激动,本文作者对OC的提升进行了详解。
 
The Setup

下面的代码你们一定再熟悉不过了,我们来重温一下吧:
@property (strong, nonatomic) NSArray *someViews;  
这绝对符合Objective-C完美主义开发者的标准。对它表示的属性,不同人有不同观点。但是,其中仍然存在着一些难以察觉的缺陷。

是否可能返回nil?

除非有现成的文件,或开发者全程都在一旁,否则光凭看是无法获取信息的。

除了UIView之外还有什么?

还是那句话——不确定。也许答案是reflection? 或许问题可以改成:除了UIView,有可能出现UIView子类吗?

看样子会出现诸多转换(casting)

因为是一队列……东西,知道那东西是什么之后,经过cast后才能利用。

会弱化Swift代码和可读性

很遗憾,Swift支持泛型(generics)就意味着(Objective-C )只会以optional的AnyObject集合的形式出现。如此一来,开发者要使用该属性就必须在Swift和Objective-C之间进行转换。

Nullability Annotations

单单一个属性就引发了这么多担忧,还挺让人不安的。如果代码本身引发很多质疑,出现error的可能性就大大增加,更别提在广为熟知的Objective-C和语言新秀Swift之间相互调用(interoperability)了。现在有了nullability annotations——我最爱的Objective-C新功能之一,问题就简单多了,编程也会省下很多麻烦。

intent.

现在谈到API,(intent.)可能会,也可能不会返回nil。简而言之,终于不用花费数小时来排除漏洞了。以下有三个选项:
  • nullable — Think UIView
  • nonnull — Think UIView
  • null_unspecified — Think UIView!


再回到实例属性。假设在运行时迭代这个属性来创建某个用户界面,在相应的位置应该有UIButton和UIView。

但是,天哪!——不论怎么样它们也不应该是nil啊。现在出现如下的信息:
@property (strong, nonatomic, nonnull) NSArray *someViews; 
intent.大大提升了Objective-C,而且这个属性也不会在Swift里满满都是optional了。

开发者看看代码就知道有没有nil pointer了,太棒了!

计算机的静态检验和Swift的可用性都得到了提升,最重要的是实现了API的intent通讯。

泛型

……Objective-C开发者们举国欢庆。呜呼,泛型的恩泽终于笼罩大地,这无疑是那些开发者勇士们的功劳。

如果把Cocoa Touch比作孩子们的睡前故事,那么Objective-C就好比是主演,故事书肯定是以上面那段话结尾的。泛型的缺席一直以来是Objective-C开发者心头之痛,而诞生32年之后,Objective-C终于也支持泛型了。2015 WWDC上Swift 2成为了镁光灯下的宠儿,而Objective-C这一巨大的跨越却被忽视了,实在委屈。支持泛型将带来诸多改变,而且都是积极的改变。

现在可以定义属性,下指令给编译器来显示所有UIView:
@property (strong, nonatomic, nonnull) NSArray<UIView *> *someViews;  
向属性强加UIView之外的东西时,编译器会报错。而且如今不用做大量头痛的转换(cast)了。

Objective-C支持泛型对Swift而言也是好消息。上次更新时,我们让Swift知道对象不应该是optional的,现在Swift还知道它们是UIViews,如此一来含混不清的AnyObject声明就不需要了。如今的Objective-C可以像C#、C++、Swift等语言一样通过<>括号来表示类型了。虽然通常是对协议表示一致性(conformance),但编译器知道何时、何地以及如何运用它们,且运用是经过推理的。

再进一步,可以用参数来表示扩展(extensions)、类别(categories)和类(classes),好处不仅仅体现在集合(collections)上。泛型的强大体现在整个Objective-C之中,集合仅仅是结果而已。举个例子,看看NSDictionary,开发者肯定会偷着乐吧:
@interface NSDictionary<KeyType, ObjectType> (Lookup)  
- (nullable ObjectType)objectForKey:(KeyType)aKey;
@end
刚开始知道类型擦除(type erasure)是为了这个的时候,我有点儿不满意,但考虑到老旧的Objective-C程序堆积在一起的问题,也就释怀了。

类型擦除(type erasure)不但能实现二进制兼容,而且不改变Objective-C的执行时间。所以亲爱的开发者们,C#的泛型的确胜过其他语言,皱皱眉头,发几句牢骚就算了,日子还得继续呢。

KindOf Types

啊,这是最后一部分重要内容。再次调用之前定义的属性,就会显示UIView。判断里面包含着views和buttons是再正常不过的事。

这种情况下,添加如下代码会发生什么呢?
[self.someViews[0] addTarget:self action:selector(aMethod:) forControlEvents:UIControlEventTouchUpInside];  
啊,编译器警告。

这就对啦,因为即便可以在这个属性里插入一个button,就算可以假设是个UIView,button也不一定没有经过转换。

新的KindOf特性能够轻松解决这种始料未及的情况。我们再回到实例属性上:
@property (strong, nonatomic, nonnull) NSArray<__kindof UIView *> *someViews;  
实际上我们已经告诉编译器:属性及其集合会出现一些UIView。这样在类型协议里显示更多我们之前看不到的信息。其本质向下转型(downcasting)。

这意味着上述代码编译没什么问题,因为编译器知道集合里肯定会出现一个button。

现在那些担忧就都解释得清了。

虽然不喜欢Swift的人可能会刻意夸大Objective-C的优点,但如今两种语言实现了互相调用,这是Objective-C所有提升的最大价值所在,我们应该心存感激。

毋庸置疑,Objective-C的确比以往更加强大。

总结

对我来说,Objective-C是开发生涯中的初恋,相比其他语言,它是那么与众不同——直到今天都是如此,它的好、它的坏都让我欲罢不能。虽然如今Swift正以迅雷不及掩耳之势征服着我的心,我还是希望Objective-C陪伴在身边。

Objective-C的提升能够帮助开发者写出更好的代码,这是好事。而且这些优势已经在Foundation中随处可见了。
 
来源:csdn
0
评论

值得推荐:理解 JavaScript 的原型链和继承 开发者 移动开发

oscar1212 发表了文章 • 1247 次浏览 • 2015-07-16 15:58 • 来自相关话题

instanceof 运算符可以用来判断某个构造函数的prototype属性是否存在另外一个要检测对象的原型链上1
 
什么意思呢?

来个题Function instanceof Object;用高中数学的话就是把x,y代入公式得:

instanceof 运算符可以用来判断Object的 prototype属性 是否存在Function的 原型链 上。
等等,斜体字的这俩到底是什么鬼意思?

prototype属性是原型链吗?

JS是基于原型链面向对象语言,也就是说所有对象都是以对象为模板创建实例的。如果是其他oo语言的背景比如Java或Ruby,都习惯于创建一个class模板,class创建object实例。比如ruby:
class A
def initialize name @name = name end
def to_s
@name
end
endputs A.new('hehe') # => hehe这里的类A就是所有 A.new 创建出来的实例的模板而已。而对于原型链语言JS来说,同意的事情要这样做
function A(name){ this.name = name
}
A.prototype.toString = function(){ return this.name
}var a = new A('hehe')
console.log('object name is:' + new A ('hehe')) // => object name is: hehe
这里的怪怪的函数其实就是constructor,相当于ruby例子里的initialize而prototype上的方法toString也就是类似class模板上的方法。
为什么要把方法绑到prototype上?直接 A.toString…= 不行吗?
在解释prototype之前,先解释一下 new A 到底发生了什么2:
1: // var a = new A('hehe') =>2: var a = new Object();3: a.__proto__ = A.prototype; (proto)4: A.call(a, 'hehe');其中 A.call 的意思是先把A的this设置为a,然后执行A的body也就是this.name=name

但是 __proto__ 又是什么

__proto__ 才是原型链

__proto__ 是内部 [ [Prototype ]] (说了半天原型链这就是牛逼闪闪的 原型链, 指向对象或者null)的getter和setter方法(已加入ES6规范3,但是还是建议只使用Object.getPrototypeOf())

JS对象能使用它原型链对象的所有方法,比如所有的对象的原型链(的原型链的原型链的原型链…)都最终会指向Object(或null)。因此,所有的对象都能使用Object.prototype上的方法,比如我之前覆盖掉的 toString 本身就是Object.prototype上的方法,如果没有覆盖,它是可以拿到所有Object上的方法的:
a.toString === A.prototype.toString // truea.toLocalString === Object.prototype.toLocalString // truea.__proto__ === A.prototype // true所以,现在是否可以理解这句话了呢
instanceof 运算符可以用来判断Object的 prototype属性 是否存在Function的 原型链 上。

所以instanceof其实就是
Function.__proto__ === Object.prototype// false擦,假设失败了呢,让我们来看看为什么不对,Function.__proto__到底指哪去了
Function.__proto__ === Function.prototype//true原来指向自己的prototype了呢,那就意味着…
Function instanceof Function//trueyes,然而 Function instanceof Object似乎也能解释了
Function.__proto__ === Function.prototypeFunction.__proto__.__proto__ === Object.prototype所以如果我们让
Function.__proto__.__proto__ = nullFunction instanceof Object//false这回知道为什么不要用 __proto__ 了吧,一不小心重写了会导致所有继承自它的对象都受影响。
为了养成良好的习惯,实际项目最好使用 getPrototypeOf 取原型链,这里只是为了方便我采用__proto__
下面来看第二个题
Object instanceof Function
难道可以互相链吗?这意味着
Object.__proto__ === Function.prototype// true// 但是Firefox取不到Object.__proto__, 看来做了保护,必须要用// Object.getPrototypeOf(Object) === Function.prototype要晕了, 忍不住要画个图





多简单呢,一共就分别有两类:

原型链指向Function.prototype的函数们

原型链指向Object.propotype的对象们

而原型链顶端的Object.prototype就再没有原型链了,所以是空

现在再回头看题目是不是so easy了。

也没什么卵用得 contructor

如果你好奇的在FireFox Console中看一下 a 除了刚才那些玩意,还有一个奇怪的东西





话说 A 里面这个constructor是个什么鬼,我们来玩它一下
a.constructor === A.prototype.constructor
A.prototype.constructor === A
A.prototype.constructor = nulla.constructor // => nulla instanceof A // true这只是函数都有的一个玩意而已, 由于js的函数可以作为构造器,也就是可以 new ,所以所有的 函数的prototype.constructor都指向自己,因此所有的 new 出来的对象也都有一个reference能找到自己的构造器。

然而除了这个功能也并没有什么卵用嘛。

真的是这样吗?
.

..



….

…..

……

…….
恩,真的!

Bonus 继承

下面这个是babel 从es6 class
class A{
constructor(name) { this.name= name
}
toString() { return this.name
}
}class B extends A {
toString(){ return this.name + 'b'
}
}编译出来的ES5继承
function _inherits(subClass, superClass) {
// 密}var A = (function () { function A(name) { this.name = name;
}

A.prototype.toString = function toString() { return this.name;
}; return A;
})();var B = (function (_A) { function B() { if (_A != null) {
_A.apply(this, arguments);
}
}

_inherits(B, _A);

B.prototype.toString = function toString() { return this.name + 'b';
}; return B;
})(A);其他地方都不用看了,inherits 函数用到了之前学到的所有玩意,要求实现要满足下列所有的cases,就当是课后练习了:
var a= new A('A');var b= new B('B');
a.constructor === A &&
b.constructor === B &&
a instanceof A &&
b instanceof A &&
b instanceof B
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/instanceof这里只是意思,但是如果真的改变 __proto__ 是非常低效的https://developer.mozilla.org/ ... protohttp://www.ecma-international.org/ecma-262/6.0/#sec-additional-properties-of-the-object.prototype-object

Author: Jichao Ouyang 查看全部
instanceof 运算符可以用来判断某个构造函数的prototype属性是否存在另外一个要检测对象的原型链上1
 
什么意思呢?

来个题Function instanceof Object;用高中数学的话就是把x,y代入公式得:

instanceof 运算符可以用来判断Object的 prototype属性 是否存在Function的 原型链 上。
等等,斜体字的这俩到底是什么鬼意思?

prototype属性是原型链吗?

JS是基于原型链面向对象语言,也就是说所有对象都是以对象为模板创建实例的。如果是其他oo语言的背景比如Java或Ruby,都习惯于创建一个class模板,class创建object实例。比如ruby:
  class A
def initialize name @name = name end
def to_s
@name
end
endputs A.new('hehe') # => hehe
这里的类A就是所有 A.new 创建出来的实例的模板而已。而对于原型链语言JS来说,同意的事情要这样做
function A(name){  this.name = name
}
A.prototype.toString = function(){ return this.name
}var a = new A('hehe')
console.log('object name is:' + new A ('hehe')) // => object name is: hehe

  • 这里的怪怪的函数其实就是constructor,相当于ruby例子里的initialize
  • 而prototype上的方法toString也就是类似class模板上的方法。

为什么要把方法绑到prototype上?直接 A.toString…= 不行吗?
在解释prototype之前,先解释一下 new A 到底发生了什么2:
1: // var a = new A('hehe') =>2: var a = new Object();3: a.__proto__ = A.prototype; (proto)4: A.call(a, 'hehe');
其中 A.call 的意思是先把A的this设置为a,然后执行A的body也就是this.name=name

但是 __proto__ 又是什么

__proto__ 才是原型链

__proto__ 是内部 [ [Prototype ]] (说了半天原型链这就是牛逼闪闪的 原型链, 指向对象或者null)的getter和setter方法(已加入ES6规范3,但是还是建议只使用Object.getPrototypeOf())

JS对象能使用它原型链对象的所有方法,比如所有的对象的原型链(的原型链的原型链的原型链…)都最终会指向Object(或null)。因此,所有的对象都能使用Object.prototype上的方法,比如我之前覆盖掉的 toString 本身就是Object.prototype上的方法,如果没有覆盖,它是可以拿到所有Object上的方法的:
a.toString === A.prototype.toString // truea.toLocalString === Object.prototype.toLocalString // truea.__proto__ === A.prototype // true
所以,现在是否可以理解这句话了呢
instanceof 运算符可以用来判断Object的 prototype属性 是否存在Function的 原型链 上。

所以instanceof其实就是
Function.__proto__ === Object.prototype// false
擦,假设失败了呢,让我们来看看为什么不对,Function.__proto__到底指哪去了
Function.__proto__ === Function.prototype//true
原来指向自己的prototype了呢,那就意味着…
Function instanceof Function//true
yes,然而 Function instanceof Object似乎也能解释了
Function.__proto__ === Function.prototypeFunction.__proto__.__proto__ === Object.prototype
所以如果我们让
Function.__proto__.__proto__ = nullFunction instanceof Object//false
这回知道为什么不要用 __proto__ 了吧,一不小心重写了会导致所有继承自它的对象都受影响。
为了养成良好的习惯,实际项目最好使用 getPrototypeOf 取原型链,这里只是为了方便我采用__proto__
下面来看第二个题
Object instanceof Function
难道可以互相链吗?这意味着
Object.__proto__ === Function.prototype// true// 但是Firefox取不到Object.__proto__, 看来做了保护,必须要用// Object.getPrototypeOf(Object) === Function.prototype
要晕了, 忍不住要画个图

1.png

多简单呢,一共就分别有两类:

原型链指向Function.prototype的函数们

原型链指向Object.propotype的对象们

而原型链顶端的Object.prototype就再没有原型链了,所以是空

现在再回头看题目是不是so easy了。

也没什么卵用得 contructor

如果你好奇的在FireFox Console中看一下 a 除了刚才那些玩意,还有一个奇怪的东西

2.png

话说 A 里面这个constructor是个什么鬼,我们来玩它一下
a.constructor === A.prototype.constructor
A.prototype.constructor === A
A.prototype.constructor = nulla.constructor // => nulla instanceof A // true
这只是函数都有的一个玩意而已, 由于js的函数可以作为构造器,也就是可以 new ,所以所有的 函数的prototype.constructor都指向自己,因此所有的 new 出来的对象也都有一个reference能找到自己的构造器。

然而除了这个功能也并没有什么卵用嘛。

真的是这样吗?
.

..



….

…..

……

…….
恩,真的!

Bonus 继承

下面这个是babel 从es6 class
class A{
constructor(name) { this.name= name
}
toString() { return this.name
}
}class B extends A {
toString(){ return this.name + 'b'
}
}
编译出来的ES5继承
function _inherits(subClass, superClass) { 
// 密}var A = (function () { function A(name) { this.name = name;
}

A.prototype.toString = function toString() { return this.name;
}; return A;
})();var B = (function (_A) { function B() { if (_A != null) {
_A.apply(this, arguments);
}
}

_inherits(B, _A);

B.prototype.toString = function toString() { return this.name + 'b';
}; return B;
})(A);
其他地方都不用看了,inherits 函数用到了之前学到的所有玩意,要求实现要满足下列所有的cases,就当是课后练习了:
var a= new A('A');var b= new B('B');
a.constructor === A &&
b.constructor === B &&
a instanceof A &&
b instanceof A &&
b instanceof B

  • https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/instanceof
  • 这里只是意思,但是如果真的改变 __proto__ 是非常低效的https://developer.mozilla.org/ ... proto
  • http://www.ecma-international.org/ecma-262/6.0/#sec-additional-properties-of-the-object.prototype-object


Author: Jichao Ouyang
0
评论

不算“真正的语言”?详说Swift 2.0中的错误处理 移动开发 swift

oscar1212 发表了文章 • 1595 次浏览 • 2015-07-15 17:25 • 来自相关话题

苹果公司在今年的全球开发者大会(Worldwide Developers Conference, WWDC)上宣布推出Swift2.0,该语言的首席架构师Chris Lattner表示,Swift 2.0主要在语言基本语法、安全性和格式美观度这三方面进行了改进。除了这些新的功能特性,还有对语法的优化、修饰及美化,最后是Swift 1.x中最具影响力的错误处理机制。
 
历史一瞬:不起眼的开端

我们都知道,Swift语言作为Objective-C当前替代语言被推出,是OS X和iOS应用程序开发的“通用语”。在最初的版本中,Objective-C没有原生的异常处理机制。后来通过添加NSException类,还有 NS_DURING, NS_HANDLER和 NS_ENDHANDLER宏才有了异常处理。这种方案现在被称为“经典的异常处理”,还有这些宏都是基于setjmp()和longjmp()这两个C语言函数的。

异常捕获(exception-catching)看起来如下所示,在NS_DURING和NS_HANDLER宏之间抛出的任何异常都将会导致在NS_HANDLER和NS_ENDHANDLER宏之间执行相应的代码。
NS_DURING
2. // Call a dangerous method or function that raises an exception:
3. [obj someRiskyMethod];
4.NS_HANDLER
5. NSLog(@"Oh no!");
6. [anotherObj makeItRight];
7.NS_ENDHANDLER
下面是立刻能触发抛出异常的方法(现在仍然可用):

[cpp] view plaincopy
1.- (void)someRiskyMethod
2.{
3. [NSException raise:@"Kablam"
4. format:@"This method is not implemented yet. Do not call!"];
5.}
可以想象,这种手工处理异常的方式戏弄的是早期Cocoa框架程序开发人员。但是这些程序员还不至于到这份儿上,因为他们很少使用这种方式。无论在Cocoa还是Cocoa Touch框架下,异常通常都被归为灾难性的,不可恢复的错误,比如程序员造成的错误。上面的-someRiskyMethod就是很好的例子,由于实现部分没有准备好而引发了异常。在Cocoa和Cocoa Touch框架中,可恢复的错误由稍后讨论的NSError类来处理。

原生的异常处理

我想由于Objective-C中的经典异常处理机制对应的手工处理方式让人感觉闹心,于是苹果公司在Mac OS X 10.3(2003年10月)中发布了原生的异常处理机制,彼时还没有iOS系统。这本质上是将C++的异常处理嫁接到了Objective-C。异常处理的结构目前看起来是这样的:
@try {
2. [obj someRiskyMethod];
3.}
4.@catch (SomeClass *exception) {
5. // Handle the error.
6. // Can use the exception object to gather information.
7.}
8.@catch (SomeOtherClass *exception) {
9. // ...
10.}
11.@catch (id allTheRest) {
12. // ...
13.}
14.@finally {
15. // Code that is executed whether an exception is thrown or not.
16. // Use for cleanup.
17.}
原生的异常处理使你有机会为每个异常类型指定不同@catch部分。无论@try结果如何,@finally都要执行其对应的代码。

尽管原生的异常处理如所预期的那样抛出一个NSException异常,但是最明确的方法还是“@throw <expression>;”语句。通常你抛出的是NSException实例,但说不定什么对象会被抛出。

NSError

尽管Objective-C原生与经典的异常处理有许多优点,但Cocoa和Cocoa Touch框架应用程序开发人员仍然很少使用异常,而是限制程序出现程序员所导致的不可恢复的错误。使用NSError类处理可恢复的错误,这种方法早于使用异常处理。Swift 1.x也继承了NSError的样式。

在Swift 1.x中,Cocoa和Cocoa Touch的方法和函数可能不会返回一个布尔类型的false或者nil来表示一个失败(failure)的对象。另外,NSErrorPointer对象会被当作一个参数返回特定的失败信息。下面是个典型的例子:

cpp] view plaincopy
1.// A local variable to store an error object if one comes back:
2.var error: NSError?
3.// success is a Bool:
4.let success = someString.writeToURL(someURL,
5. atomically: true,
6. encoding: NSUTF8StringEncoding,
7. error: &error)
8.if !success {
9. // Log information about the error:
10. println("Error writing to URL: \(error!)")
11.}
程序员所导致的错误可以用Swift标准库(Swift Standard Library)函数fatalError("Error message”)来标记,将其在控制台记录为错误消息并无条件中止执行。还可以使用assert(), assertionFailure(), precondition()和preconditionFailure()这些函数。

Swift第一次发布时,一些非苹果平台开发人员已经准备好了火把和干草叉。他们声称Swift不能算是“真正的语言”,因为它缺乏异常处理。但是,Cocoa和Cocoa Touch社区对此不予理睬,我们知道NSError和NSException那个时候就存在了。就我个人而言,我相信苹果公司仍然在思考实现错误和异常处理的正确方式。我还认为直到问题解决了,苹果公司才会公开Swift源码。这一切问题在Swift 2.0中全被扫清了。 
 
Swift 2.0中的错误处理

在Swift 2.0中,如果想要抛出错误,那么抛出的对象必须符合ErrorType协议。可能正如你所愿,NSError就符合该协议。枚举在这里用来给错误进行分类。
enum AwfulError: ErrorType {
2. case Bad
3. case Worse
4. case Terrible
5.}
然后如果一个可能抛出一个或多个错误的函数或方法会被throws关键字标记:
func doDangerousStuff() throws -> SomeObject {
2. // If something bad happens throw the error:
3. throw AwfulError.Bad
4.
5. // If something worse happens, throw another error:
6. throw AwfulError.Worse
7.
8. // If something terrible happens, you know what to do:
9. throw AwfulError.Terrible
10.
11. // If you made it here, you can return:
12. return SomeObject()
13.}
为了捕获错误,新型的do-catch语句出现了:
do {
2. let theResult = try obj.doDangerousStuff()
3.}
4.catch AwfulError.Bad {
5. // Deal with badness.
6.}
7.catch AwfulError.Worse {
8. // Deal with worseness.
9.}
10.catch AwfulError.Terrible {
11. // Deal with terribleness.
12.}
13.catch ErrorType {
14. // Unexpected error!
15.}
这个do-catch语句和switch语句有一些相似之处,被捕获的错误详尽无遗,因此你可以使用这种样式来捕获抛出的错误。还要注意关键字try的使用。它是为了明确地标示抛出的代码行,因此当阅读代码的时候,你能够立刻找到错误在哪里。

关键字try的变体是“try!”。这个关键字大概也适用于那些程序员导致的错误。如果使用“try!”标记一个被调用的抛出对象中的方法,你等于告诉编译器这个错误永远不会发生,并且你也不需要捕获它。如果该语句本身产生了错误(error),应用程序会停止执行,那么你就要开始调试了。
let theResult = try! obj.doDangerousStuff() 与Cocoa和Cocoa Touch框架间的交互

现在的问题是,你如何在Swift 2.0中处理爷爷级的NSError API呢?苹果公司已经在Swift 2.0中为统一代码行为作了大量工作,并且已经为未来写入Swift的框架准备方法。Cocoa和Cocoa Touch中可以产生NSError实例的方法和函数有苹果公司的签名( signature),可以自动转换为Swift新的错误处理方式。

例如,这个NSString的构造器( initializer)在Swift 1.x中就有以下签名:
convenience init?(contentsOfFile path: String,
2. encoding enc: UInt,
3. error error: NSErrorPointer)
注意:在Swift 2.0中,构造器不再被标记为failable,它并不需要NSErrorPointer来做参数,而是使用抛出异常的方式显式地指示潜在的失败。

下面的例子使用了这种新的签名:
do {
2. let str = try NSString(contentsOfFile: "Foo.bar",
3. encoding: NSUTF8StringEncoding)
4.}
5.catch let error as NSError {
6. print(error.localizedDescription)
7.}
注意错误是如何被捕获的,并且如何被转换成了一个NSError实例,这样你就可以获取与其相似API的信息了。事实上,任何ErrorType类型的实例都可以转换成NSError类型。

最后说说@finally

细心的读者可能已经注意到,Swift 2.0引入了一个新的do-catch语句,而不是do-catch-finally。不管是否捕捉到错误的情况下,你如何指定必须运行的代码呢?为此,现在可以使用defer语句,用来推迟代码块的执行直到当前的作用域结束。
// Some scope:
2.{
3. // Get some resource.
4.
5. defer {
6. // Release resource.
7. }
8.
9. // Do things with the resource.
10. // Possibly return early if an error occurs.
11.
12.} // Deferred code is executed at the end of the scope.
Swift 2.0将Cocoa和Cocoa Touch的错误处理机制凝聚为具有现代风格的用法,这是一项伟大的工作,也会使许多程序员倍感亲切。统一行为是不错的定位,会使Swift语言和其所继承的框架逐步发展。
 
文章来源:Big Nerd Ranch 查看全部
苹果公司在今年的全球开发者大会(Worldwide Developers Conference, WWDC)上宣布推出Swift2.0,该语言的首席架构师Chris Lattner表示,Swift 2.0主要在语言基本语法、安全性和格式美观度这三方面进行了改进。除了这些新的功能特性,还有对语法的优化、修饰及美化,最后是Swift 1.x中最具影响力的错误处理机制。
 
历史一瞬:不起眼的开端

我们都知道,Swift语言作为Objective-C当前替代语言被推出,是OS X和iOS应用程序开发的“通用语”。在最初的版本中,Objective-C没有原生的异常处理机制。后来通过添加NSException类,还有 NS_DURING, NS_HANDLER和 NS_ENDHANDLER宏才有了异常处理。这种方案现在被称为“经典的异常处理”,还有这些宏都是基于setjmp()和longjmp()这两个C语言函数的。

异常捕获(exception-catching)看起来如下所示,在NS_DURING和NS_HANDLER宏之间抛出的任何异常都将会导致在NS_HANDLER和NS_ENDHANDLER宏之间执行相应的代码。
NS_DURING  
2. // Call a dangerous method or function that raises an exception:
3. [obj someRiskyMethod];
4.NS_HANDLER
5. NSLog(@"Oh no!");
6. [anotherObj makeItRight];
7.NS_ENDHANDLER
下面是立刻能触发抛出异常的方法(现在仍然可用):

[cpp] view plaincopy
1.- (void)someRiskyMethod
2.{
3. [NSException raise:@"Kablam"
4. format:@"This method is not implemented yet. Do not call!"];
5.}
可以想象,这种手工处理异常的方式戏弄的是早期Cocoa框架程序开发人员。但是这些程序员还不至于到这份儿上,因为他们很少使用这种方式。无论在Cocoa还是Cocoa Touch框架下,异常通常都被归为灾难性的,不可恢复的错误,比如程序员造成的错误。上面的-someRiskyMethod就是很好的例子,由于实现部分没有准备好而引发了异常。在Cocoa和Cocoa Touch框架中,可恢复的错误由稍后讨论的NSError类来处理。

原生的异常处理

我想由于Objective-C中的经典异常处理机制对应的手工处理方式让人感觉闹心,于是苹果公司在Mac OS X 10.3(2003年10月)中发布了原生的异常处理机制,彼时还没有iOS系统。这本质上是将C++的异常处理嫁接到了Objective-C。异常处理的结构目前看起来是这样的:
@try {  
2. [obj someRiskyMethod];
3.}
4.@catch (SomeClass *exception) {
5. // Handle the error.
6. // Can use the exception object to gather information.
7.}
8.@catch (SomeOtherClass *exception) {
9. // ...
10.}
11.@catch (id allTheRest) {
12. // ...
13.}
14.@finally {
15. // Code that is executed whether an exception is thrown or not.
16. // Use for cleanup.
17.}
原生的异常处理使你有机会为每个异常类型指定不同@catch部分。无论@try结果如何,@finally都要执行其对应的代码。

尽管原生的异常处理如所预期的那样抛出一个NSException异常,但是最明确的方法还是“@throw <expression>;”语句。通常你抛出的是NSException实例,但说不定什么对象会被抛出。

NSError

尽管Objective-C原生与经典的异常处理有许多优点,但Cocoa和Cocoa Touch框架应用程序开发人员仍然很少使用异常,而是限制程序出现程序员所导致的不可恢复的错误。使用NSError类处理可恢复的错误,这种方法早于使用异常处理。Swift 1.x也继承了NSError的样式。

在Swift 1.x中,Cocoa和Cocoa Touch的方法和函数可能不会返回一个布尔类型的false或者nil来表示一个失败(failure)的对象。另外,NSErrorPointer对象会被当作一个参数返回特定的失败信息。下面是个典型的例子:

cpp] view plaincopy
1.// A local variable to store an error object if one comes back:
2.var error: NSError?
3.// success is a Bool:
4.let success = someString.writeToURL(someURL,
5. atomically: true,
6. encoding: NSUTF8StringEncoding,
7. error: &error)
8.if !success {
9. // Log information about the error:
10. println("Error writing to URL: \(error!)")
11.}
程序员所导致的错误可以用Swift标准库(Swift Standard Library)函数fatalError("Error message”)来标记,将其在控制台记录为错误消息并无条件中止执行。还可以使用assert(), assertionFailure(), precondition()和preconditionFailure()这些函数。

Swift第一次发布时,一些非苹果平台开发人员已经准备好了火把和干草叉。他们声称Swift不能算是“真正的语言”,因为它缺乏异常处理。但是,Cocoa和Cocoa Touch社区对此不予理睬,我们知道NSError和NSException那个时候就存在了。就我个人而言,我相信苹果公司仍然在思考实现错误和异常处理的正确方式。我还认为直到问题解决了,苹果公司才会公开Swift源码。这一切问题在Swift 2.0中全被扫清了。 
 
Swift 2.0中的错误处理

在Swift 2.0中,如果想要抛出错误,那么抛出的对象必须符合ErrorType协议。可能正如你所愿,NSError就符合该协议。枚举在这里用来给错误进行分类。
enum AwfulError: ErrorType {  
2. case Bad
3. case Worse
4. case Terrible
5.}
然后如果一个可能抛出一个或多个错误的函数或方法会被throws关键字标记:
func doDangerousStuff() throws -> SomeObject {  
2. // If something bad happens throw the error:
3. throw AwfulError.Bad
4.
5. // If something worse happens, throw another error:
6. throw AwfulError.Worse
7.
8. // If something terrible happens, you know what to do:
9. throw AwfulError.Terrible
10.
11. // If you made it here, you can return:
12. return SomeObject()
13.}
为了捕获错误,新型的do-catch语句出现了:
do {  
2. let theResult = try obj.doDangerousStuff()
3.}
4.catch AwfulError.Bad {
5. // Deal with badness.
6.}
7.catch AwfulError.Worse {
8. // Deal with worseness.
9.}
10.catch AwfulError.Terrible {
11. // Deal with terribleness.
12.}
13.catch ErrorType {
14. // Unexpected error!
15.}
这个do-catch语句和switch语句有一些相似之处,被捕获的错误详尽无遗,因此你可以使用这种样式来捕获抛出的错误。还要注意关键字try的使用。它是为了明确地标示抛出的代码行,因此当阅读代码的时候,你能够立刻找到错误在哪里。

关键字try的变体是“try!”。这个关键字大概也适用于那些程序员导致的错误。如果使用“try!”标记一个被调用的抛出对象中的方法,你等于告诉编译器这个错误永远不会发生,并且你也不需要捕获它。如果该语句本身产生了错误(error),应用程序会停止执行,那么你就要开始调试了。
let theResult = try! obj.doDangerousStuff()  
与Cocoa和Cocoa Touch框架间的交互

现在的问题是,你如何在Swift 2.0中处理爷爷级的NSError API呢?苹果公司已经在Swift 2.0中为统一代码行为作了大量工作,并且已经为未来写入Swift的框架准备方法。Cocoa和Cocoa Touch中可以产生NSError实例的方法和函数有苹果公司的签名( signature),可以自动转换为Swift新的错误处理方式。

例如,这个NSString的构造器( initializer)在Swift 1.x中就有以下签名:
convenience init?(contentsOfFile path: String,  
2. encoding enc: UInt,
3. error error: NSErrorPointer)
注意:在Swift 2.0中,构造器不再被标记为failable,它并不需要NSErrorPointer来做参数,而是使用抛出异常的方式显式地指示潜在的失败。

下面的例子使用了这种新的签名:
do {  
2. let str = try NSString(contentsOfFile: "Foo.bar",
3. encoding: NSUTF8StringEncoding)
4.}
5.catch let error as NSError {
6. print(error.localizedDescription)
7.}
注意错误是如何被捕获的,并且如何被转换成了一个NSError实例,这样你就可以获取与其相似API的信息了。事实上,任何ErrorType类型的实例都可以转换成NSError类型。

最后说说@finally

细心的读者可能已经注意到,Swift 2.0引入了一个新的do-catch语句,而不是do-catch-finally。不管是否捕捉到错误的情况下,你如何指定必须运行的代码呢?为此,现在可以使用defer语句,用来推迟代码块的执行直到当前的作用域结束。
// Some scope:  
2.{
3. // Get some resource.
4.
5. defer {
6. // Release resource.
7. }
8.
9. // Do things with the resource.
10. // Possibly return early if an error occurs.
11.
12.} // Deferred code is executed at the end of the scope.
Swift 2.0将Cocoa和Cocoa Touch的错误处理机制凝聚为具有现代风格的用法,这是一项伟大的工作,也会使许多程序员倍感亲切。统一行为是不错的定位,会使Swift语言和其所继承的框架逐步发展。
 
文章来源:Big Nerd Ranch
0
评论

全球扫货指南集成环信移动客服:订单量客单价双丰收 环信移动客服 环信 移动开发

admin 发表了文章 • 1472 次浏览 • 2015-07-14 16:27 • 来自相关话题

移动互联网时代,同时迎来了全民创业的时代,虽然这两者不能划上等号,但不能否认,移动互联网的普及,给全民创业提供了更多的创新灵感,也赋予了电商更多活力。笔者了解的一些电商,已完全摒弃PC端接入口,而只从移动端进行接入。





在传统大型平台电商的窗口已经被逐渐关闭的时候,新入场的玩家必须借助移动端和社交实现弯道超车,移动电子商务公司“全球扫货指南”便是中国移动互联网发展的其中一家受益企业,其市场总监左小禛便认为:电子商务的未来是移动电商,而移动电商必须重视移动客服。

移动电商的三个关键点

的确,百度无线数据报告显示,移动互联网创业者开发经验不足1年的人数比例为38.3%,个人开发者比例明显上升,同时11—20人团队开发比例下降,移动开发者生态从量变向质变迁移。此外,移动互联网创业者对商业模式的探索和创新尚无特定模式可以借鉴。上述状况下,移动电商创业者如何实现弯道超车?笔者认为,以下三个关键点需要重点把握:

1、转变思维,认清客户在哪?

移动互联网时代用户数的迅猛增长,已是必然趋势。用户数的急速增长,意味着巨大的机会,同时也意味着巨大的挑战,终端的小型化、多样化,接入方式的多样化都意味着我们处在全新的互联网生态环境中。

Gartner预测,到2017年年底,超过70%的交易将来自于移动端。2014年阿里双十一的现场监控显示,总成交额571亿其中移动端贡献了243亿,移动端交易量比例将有超过PC端的趋势。同时,京东2014年第四季度财报显示移动端的订单量占比接近40%。

因此,移动互联网时代,电商行业应转变思维,认清客户来源趋势,应在移动端的各个接口做好整体布局,无论是营销、服务还是流程,应进行相应梳理。

2、移动互联网的营销,社交为王!

但在移动互联时代,营销渠道越来越多。过去的营销是通过电视、报纸等渠道跟消费者沟通,但移动互联网时代则是分享的时代,免费思维已成为主流,为了让用户喜欢,愿意分享,消费者和商家会直接面对面进行免费试用与体验,通过各种活动进行赠予、使用,增强体验。这也使移动互联网时代的电商营销成本非常巨大。

移动互联网时代的营销除了普通的宣传、引导、试用、免费等传统方式外,更多的具有社交化属性,用户体验变得如此重要,即时通讯所具有的实时性、互动社交性让移动电商更具活力。甚至很多商家都搭建了基于兴趣社交的板块辅助自身电商平台,通过社区导购来降低用户的购买决策成本,在非标品等方面与传统大电商平台竞争获取优势实现弯道超车。

3、移动互联网的客户服务,体验为王!

营销的成功,只能带来一定的流量,但真正的交易与再次销售,则一定是产品本身具有的价值及客户服务所带给客户的体验。我们经常说,客户在哪,客户服务就要跟到哪。客户在移动端,移动端的客户服务如果不到位,不但订单丢失,客户丢失,甚至公司也可能被那些更重视移动端的用户服务体验的公司,更能迅速把握时代大趋势的公司所颠覆。一项研究报告指出,如果做不好客服,辛辛苦苦通过各种渠道引流到自己App、网站、平台、账号的客户,95%都会流失掉。

因此,电商已从PC端转战到了移动端,移动端有其特定的消费属性,无论是营销与服务,应从移动端的消费属性来研究。

移动电商的客服趋势

如果说电商的移动性趋势已得到行业认可,各个大、中型电子商务公司正在奋力奔跑在移动端,正在全力争夺消费者手机上不多的APP安装上。但笔者需要提醒大家的是:太多企业过于重视营销,而对客户服务有所忽视。

客户服务的重要性已不需要赘述,笔者认为移动电商客服有几个趋势将带动电商企业的发展:

1、 多渠道融合,尤其以移动端为主的客服请求将占主导

客户服务请求来源包括传统呼叫中心的语音、基于网页的实时在线聊天系统、工单系统、微博、微信等等。客户来源的多样性,让多渠道融合客服成为必须。另一方面,正如上文所述,如今的消费者正在远离PC和电话,消费者都去了移动端,所以客户服务将以移动端客服请求为主导。

2、 即时通讯(IM)将是最适合移动设备的客服服务形式

微信已成为我们最重要的日常沟通形式,界面简单易操作,不需要任何培训,人人都会使用,最重要的是,这是最适合移动设备的沟通方式。互联网女皇发布的《2015互联网趋势报告》也认为: IM不仅是世界上标准化程度最高的互联网产品,而且是世界上下载和使用量最大的互联网产品,也是用户交流体验最好的产品。异步又实时、个性化又主流、表达能力很强但又迅速等等。

传统400电话虽然也方便迅速,但笔者也经常因为400电话的无尽等待而挂机。虽然对12306这样的订票刚需企业影响不大,但如是电商企业,那客户流失率就太高了。因此,即时通讯式的客服形式非常适合移动设备,一个发送就能即时接送信息,按一个按钮就得到服务,可以秒级接通,并且可以得到7X24小时随时随地的解答。不用去填写工单,也不用在APP中遇到问题的时还要跳出APP外通过电话,邮件,微信,QQ等方式才能后被解决。

3、智能客服技术将得到大量应用

上文提到了即时通讯式的客服形式非常适合移动设备,移动互联网时代,客户手机24 小时随身携带的属性决定了传统5 X8小时的服务形式早已满足不了客户需求。客户需要实现一个发送就能即时接送信息,可以秒级接通,并且可以得到7X24小时随时随地的解答。我们可以想象的是,这个7X24小时随时随地的服务并不是企业派了足够多的人工座席在为客户提供服务,而是智能客服技术的一项应用。

智能客服技术是实时聊天的一种技术应用,因为即时通讯沟通方式最大的优势是可以一对多,即一个客服坐席可以同时和多个人聊天,使用自动菜单导航,语义分析,机器人智能应答,智能知识库等技术的大面积应用,“智能机器人+知识库”可以帮助回答80%的常见问题,可大量减少传统座席人员数。

移动电商客服的三大难点透析

通过笔者对移动电商客服的几个趋势的梳理,我们看到,移动电商的消费群体的特定性,让移动客服与传统客服具有很多的不一致性,移动客服如需要做精做透,以下流程是难点:
 1、 集中的质检系统

传统语音客服因为可以通过录音、检索等方式进行客户服务质量检测,移动客服的即时通讯性、多渠道接入等属性,使客服的质量把控具有一定的难度。

2、 交易行业的大数据积累与分析

大量的移动端客服数据与传统来自于呼叫中心、Web端、微博、微信的客服数据,如何进行统一接入、积累与分析,进行数据挖掘实现商业转化,这是较大的难点也是最重要的商机,客户趋动才是需求的起点,是创新的动力。

3、 即时客服需要即时的信息管理

移动互联网时代,服务的即时性也对管理的即时性提出了很高的要求。移动电子商务公司全球扫货指南市场总监左小禛便深有体会:“移动电商经常会定期或者不定期举行一些活动,活动举办期间,服务请求较平常可能会有十倍甚至更多倍的增长,这样的环境下,如何去调配座席人员?如果知道何种渠道来源的增长比例?服务过程中出现了哪些问题?哪些是共性问题等等。移动环境下,即时客服要求有即时的信息管理。我们采用了环信移动客服,解决了我们客服过程中的很多难题。“

全球扫货指南的移动客服初体验

全球扫货指南是全球首家时尚买手制购物平台。平台上有各类买手推荐的奢侈单品,产品的价格搜索引擎可以帮助用户一键比价,比完之后觉得划算就可以找靠谱买手下单购买。全球扫货指南作为交易平台,实行第三方担保机制,若买卖双方发生纠纷,提供先行赔付。在CEO肖宇眼里,随着这几年电商的蓬勃发展,用户线上消费习惯正在快速被培养。目前客单价千元以上的电商玩家并不多,另一方面用户的消费升级不断加速,奢侈品购买呈年轻化,因此在手机上消费的客单价越来越高,将会给轻奢市场带来巨大的机会。
 
据左小禛介绍,全球扫货指南接入了这种智能移动客服产品后,可以实现快速注册、根据体验指南一两分钟内即可对接商家完成会话体验,同时实现了跨平台多渠道接入:支持 App、微信公众账号、微博、网页等,均可以快速统一接入客户服务后台管理。

其次,满足了开放性与自定义信息:这种新型的移动客服实现了代码开源、UI开源,还提供多套UI模版,这样便于与全球扫货指南自身的APP快速集成,平滑接入。同时第三方集成功能也很强大,可与第三方工单、知识库、CRM 系统等进行扩展集成。

第三,富媒体消息交互体验:移动客服平台提供了基于IM技术的类似微信体验的友好富媒体消息交互,不仅可以实时收发文字、表情,还可以即时收发图片、位置、实时语音、还可自定义消息,大大方便了与客户的沟通交流。

第四,精准客户画像功能:移动客服的IM沟通帮助全球扫货指南辅助判断客户需求与诉求,通过自定义客户分类标签,客户再次访问时可获知客户的类型。并且还支持自定义会话小结,根据会话小结统计会话的分类,通过会话小结追踪客户诉求。通过轨迹分析功能,即通过发送客户访问页面的轨迹,判断客户意图,获取客户个性化细节,了解客户基础信息,分析客户行为,可以极大提高订单效率。

第五,“智能机器人+智能知识库”:作为一套智能化的客服系统,全球扫货指南建立了基于业务的智能知识库,智能辅助归结业务信息和应答客户信息,历史常见问题系统梳理,提高客服效率。“智能机器人+智能知识库”组合目前可自动回复80%常见问题,随着智能知识库的不断训练,这一比例能够提高到90%。

第六、真正实现不丢订单:环信基于IM长连接技术,帮助全球扫货指南实现超线拉取排队会话,让等待时间过长或有订单需求的客户得到优先服务,提升客服效率,即使客户关闭会话,退出App,甚至关闭手机,基于IM长连接技术依然能找回客户会话,提升客服效率,不丢客户订单。同时,基于IM长连接技术,即使在断网或复杂网络切换时也依然能找回客户会话,不丢客户订单。

第七、实现了质检系统透明管理:移动客服自带实时监控系统,可实时监控当前所有会话,管理员在线质检,在线查看会话信息,还提供了历史会话查询、质检考核。通过实时与历史查看,可以统计出客服代表的接入量、在线时间及应答等待时间。

通过销售部和技术部返回的数据报告显示,左小禛判断,通过部署这种新型智能移动云客服,较于传统客服产品节省成本约60%,省电省流量高达80%,同时留住了70%会话客户,订单量和客单价均获得了不同幅度提升。目前全球扫货指南覆盖全球100个顶级奢侈品品牌,超过10万个热门单品。根据贝恩咨询的数据,中国人去年一年消费奢侈品3800亿元,其中70%在海外消费,仅代购市场就超过750亿元,奢侈品的海淘电商无疑是块很诱人的蛋糕。

移动客服的魅力,从上述数据的发布可看出,已超出了大家的想象!原因在于:传统客服体系下,客服只是成本中心,辅助部门;而在移动互联网时候下,客服俨然已成为核心流程之一,竞争力关键要素之一。

一位客服领域大佬曾这样总结这个时代:“伴随着客户互动的革命,从呼叫中心演变到的客户中心作为不断扩展的客户交互平台概念一直经历着深刻的变革。运营日益规模化,精准化、多通路化、智能化和普适化。作为集语音和非语音渠道为一体,人工与智能服务共协同,物理与数字的通路大融合,随着以客户理念,人文为中心时代的来临,客户服务中心正从企业价值链的一测走向价值传递的中央,与惊艳的产品研发一起发挥着客户体验创造的核心角色。”

移动客服,你已不能再等待! 查看全部
移动互联网时代,同时迎来了全民创业的时代,虽然这两者不能划上等号,但不能否认,移动互联网的普及,给全民创业提供了更多的创新灵感,也赋予了电商更多活力。笔者了解的一些电商,已完全摒弃PC端接入口,而只从移动端进行接入。

1.jpg

在传统大型平台电商的窗口已经被逐渐关闭的时候,新入场的玩家必须借助移动端和社交实现弯道超车,移动电子商务公司“全球扫货指南”便是中国移动互联网发展的其中一家受益企业,其市场总监左小禛便认为:电子商务的未来是移动电商,而移动电商必须重视移动客服。

移动电商的三个关键点

的确,百度无线数据报告显示,移动互联网创业者开发经验不足1年的人数比例为38.3%,个人开发者比例明显上升,同时11—20人团队开发比例下降,移动开发者生态从量变向质变迁移。此外,移动互联网创业者对商业模式的探索和创新尚无特定模式可以借鉴。上述状况下,移动电商创业者如何实现弯道超车?笔者认为,以下三个关键点需要重点把握:

1、转变思维,认清客户在哪?

移动互联网时代用户数的迅猛增长,已是必然趋势。用户数的急速增长,意味着巨大的机会,同时也意味着巨大的挑战,终端的小型化、多样化,接入方式的多样化都意味着我们处在全新的互联网生态环境中。

Gartner预测,到2017年年底,超过70%的交易将来自于移动端。2014年阿里双十一的现场监控显示,总成交额571亿其中移动端贡献了243亿,移动端交易量比例将有超过PC端的趋势。同时,京东2014年第四季度财报显示移动端的订单量占比接近40%。

因此,移动互联网时代,电商行业应转变思维,认清客户来源趋势,应在移动端的各个接口做好整体布局,无论是营销、服务还是流程,应进行相应梳理。

2、移动互联网的营销,社交为王!

但在移动互联时代,营销渠道越来越多。过去的营销是通过电视、报纸等渠道跟消费者沟通,但移动互联网时代则是分享的时代,免费思维已成为主流,为了让用户喜欢,愿意分享,消费者和商家会直接面对面进行免费试用与体验,通过各种活动进行赠予、使用,增强体验。这也使移动互联网时代的电商营销成本非常巨大。

移动互联网时代的营销除了普通的宣传、引导、试用、免费等传统方式外,更多的具有社交化属性,用户体验变得如此重要,即时通讯所具有的实时性、互动社交性让移动电商更具活力。甚至很多商家都搭建了基于兴趣社交的板块辅助自身电商平台,通过社区导购来降低用户的购买决策成本,在非标品等方面与传统大电商平台竞争获取优势实现弯道超车。

3、移动互联网的客户服务,体验为王!

营销的成功,只能带来一定的流量,但真正的交易与再次销售,则一定是产品本身具有的价值及客户服务所带给客户的体验。我们经常说,客户在哪,客户服务就要跟到哪。客户在移动端,移动端的客户服务如果不到位,不但订单丢失,客户丢失,甚至公司也可能被那些更重视移动端的用户服务体验的公司,更能迅速把握时代大趋势的公司所颠覆。一项研究报告指出,如果做不好客服,辛辛苦苦通过各种渠道引流到自己App、网站、平台、账号的客户,95%都会流失掉。

因此,电商已从PC端转战到了移动端,移动端有其特定的消费属性,无论是营销与服务,应从移动端的消费属性来研究。

移动电商的客服趋势

如果说电商的移动性趋势已得到行业认可,各个大、中型电子商务公司正在奋力奔跑在移动端,正在全力争夺消费者手机上不多的APP安装上。但笔者需要提醒大家的是:太多企业过于重视营销,而对客户服务有所忽视。

客户服务的重要性已不需要赘述,笔者认为移动电商客服有几个趋势将带动电商企业的发展:

1、 多渠道融合,尤其以移动端为主的客服请求将占主导

客户服务请求来源包括传统呼叫中心的语音、基于网页的实时在线聊天系统、工单系统、微博、微信等等。客户来源的多样性,让多渠道融合客服成为必须。另一方面,正如上文所述,如今的消费者正在远离PC和电话,消费者都去了移动端,所以客户服务将以移动端客服请求为主导。

2、 即时通讯(IM)将是最适合移动设备的客服服务形式

微信已成为我们最重要的日常沟通形式,界面简单易操作,不需要任何培训,人人都会使用,最重要的是,这是最适合移动设备的沟通方式。互联网女皇发布的《2015互联网趋势报告》也认为: IM不仅是世界上标准化程度最高的互联网产品,而且是世界上下载和使用量最大的互联网产品,也是用户交流体验最好的产品。异步又实时、个性化又主流、表达能力很强但又迅速等等。

传统400电话虽然也方便迅速,但笔者也经常因为400电话的无尽等待而挂机。虽然对12306这样的订票刚需企业影响不大,但如是电商企业,那客户流失率就太高了。因此,即时通讯式的客服形式非常适合移动设备,一个发送就能即时接送信息,按一个按钮就得到服务,可以秒级接通,并且可以得到7X24小时随时随地的解答。不用去填写工单,也不用在APP中遇到问题的时还要跳出APP外通过电话,邮件,微信,QQ等方式才能后被解决。

3、智能客服技术将得到大量应用

上文提到了即时通讯式的客服形式非常适合移动设备,移动互联网时代,客户手机24 小时随身携带的属性决定了传统5 X8小时的服务形式早已满足不了客户需求。客户需要实现一个发送就能即时接送信息,可以秒级接通,并且可以得到7X24小时随时随地的解答。我们可以想象的是,这个7X24小时随时随地的服务并不是企业派了足够多的人工座席在为客户提供服务,而是智能客服技术的一项应用。

智能客服技术是实时聊天的一种技术应用,因为即时通讯沟通方式最大的优势是可以一对多,即一个客服坐席可以同时和多个人聊天,使用自动菜单导航,语义分析,机器人智能应答,智能知识库等技术的大面积应用,“智能机器人+知识库”可以帮助回答80%的常见问题,可大量减少传统座席人员数。

移动电商客服的三大难点透析

通过笔者对移动电商客服的几个趋势的梳理,我们看到,移动电商的消费群体的特定性,让移动客服与传统客服具有很多的不一致性,移动客服如需要做精做透,以下流程是难点:
 1、 集中的质检系统

传统语音客服因为可以通过录音、检索等方式进行客户服务质量检测,移动客服的即时通讯性、多渠道接入等属性,使客服的质量把控具有一定的难度。

2、 交易行业的大数据积累与分析

大量的移动端客服数据与传统来自于呼叫中心、Web端、微博、微信的客服数据,如何进行统一接入、积累与分析,进行数据挖掘实现商业转化,这是较大的难点也是最重要的商机,客户趋动才是需求的起点,是创新的动力。

3、 即时客服需要即时的信息管理

移动互联网时代,服务的即时性也对管理的即时性提出了很高的要求。移动电子商务公司全球扫货指南市场总监左小禛便深有体会:“移动电商经常会定期或者不定期举行一些活动,活动举办期间,服务请求较平常可能会有十倍甚至更多倍的增长,这样的环境下,如何去调配座席人员?如果知道何种渠道来源的增长比例?服务过程中出现了哪些问题?哪些是共性问题等等。移动环境下,即时客服要求有即时的信息管理。我们采用了环信移动客服,解决了我们客服过程中的很多难题。“

全球扫货指南的移动客服初体验

全球扫货指南是全球首家时尚买手制购物平台。平台上有各类买手推荐的奢侈单品,产品的价格搜索引擎可以帮助用户一键比价,比完之后觉得划算就可以找靠谱买手下单购买。全球扫货指南作为交易平台,实行第三方担保机制,若买卖双方发生纠纷,提供先行赔付。在CEO肖宇眼里,随着这几年电商的蓬勃发展,用户线上消费习惯正在快速被培养。目前客单价千元以上的电商玩家并不多,另一方面用户的消费升级不断加速,奢侈品购买呈年轻化,因此在手机上消费的客单价越来越高,将会给轻奢市场带来巨大的机会。
 
据左小禛介绍,全球扫货指南接入了这种智能移动客服产品后,可以实现快速注册、根据体验指南一两分钟内即可对接商家完成会话体验,同时实现了跨平台多渠道接入:支持 App、微信公众账号、微博、网页等,均可以快速统一接入客户服务后台管理。

其次,满足了开放性与自定义信息:这种新型的移动客服实现了代码开源、UI开源,还提供多套UI模版,这样便于与全球扫货指南自身的APP快速集成,平滑接入。同时第三方集成功能也很强大,可与第三方工单、知识库、CRM 系统等进行扩展集成。

第三,富媒体消息交互体验:移动客服平台提供了基于IM技术的类似微信体验的友好富媒体消息交互,不仅可以实时收发文字、表情,还可以即时收发图片、位置、实时语音、还可自定义消息,大大方便了与客户的沟通交流。

第四,精准客户画像功能:移动客服的IM沟通帮助全球扫货指南辅助判断客户需求与诉求,通过自定义客户分类标签,客户再次访问时可获知客户的类型。并且还支持自定义会话小结,根据会话小结统计会话的分类,通过会话小结追踪客户诉求。通过轨迹分析功能,即通过发送客户访问页面的轨迹,判断客户意图,获取客户个性化细节,了解客户基础信息,分析客户行为,可以极大提高订单效率。

第五,“智能机器人+智能知识库”:作为一套智能化的客服系统,全球扫货指南建立了基于业务的智能知识库,智能辅助归结业务信息和应答客户信息,历史常见问题系统梳理,提高客服效率。“智能机器人+智能知识库”组合目前可自动回复80%常见问题,随着智能知识库的不断训练,这一比例能够提高到90%。

第六、真正实现不丢订单:环信基于IM长连接技术,帮助全球扫货指南实现超线拉取排队会话,让等待时间过长或有订单需求的客户得到优先服务,提升客服效率,即使客户关闭会话,退出App,甚至关闭手机,基于IM长连接技术依然能找回客户会话,提升客服效率,不丢客户订单。同时,基于IM长连接技术,即使在断网或复杂网络切换时也依然能找回客户会话,不丢客户订单。

第七、实现了质检系统透明管理:移动客服自带实时监控系统,可实时监控当前所有会话,管理员在线质检,在线查看会话信息,还提供了历史会话查询、质检考核。通过实时与历史查看,可以统计出客服代表的接入量、在线时间及应答等待时间。

通过销售部和技术部返回的数据报告显示,左小禛判断,通过部署这种新型智能移动云客服,较于传统客服产品节省成本约60%,省电省流量高达80%,同时留住了70%会话客户,订单量和客单价均获得了不同幅度提升。目前全球扫货指南覆盖全球100个顶级奢侈品品牌,超过10万个热门单品。根据贝恩咨询的数据,中国人去年一年消费奢侈品3800亿元,其中70%在海外消费,仅代购市场就超过750亿元,奢侈品的海淘电商无疑是块很诱人的蛋糕。

移动客服的魅力,从上述数据的发布可看出,已超出了大家的想象!原因在于:传统客服体系下,客服只是成本中心,辅助部门;而在移动互联网时候下,客服俨然已成为核心流程之一,竞争力关键要素之一。

一位客服领域大佬曾这样总结这个时代:“伴随着客户互动的革命,从呼叫中心演变到的客户中心作为不断扩展的客户交互平台概念一直经历着深刻的变革。运营日益规模化,精准化、多通路化、智能化和普适化。作为集语音和非语音渠道为一体,人工与智能服务共协同,物理与数字的通路大融合,随着以客户理念,人文为中心时代的来临,客户服务中心正从企业价值链的一测走向价值传递的中央,与惊艳的产品研发一起发挥着客户体验创造的核心角色。”

移动客服,你已不能再等待!
0
评论

环信CEO:环信移动客服技术全解析 移动开发 环信

admin 发表了文章 • 2791 次浏览 • 2015-07-14 16:20 • 来自相关话题

摘要:《近匠》第92期,在专注于为开发者提供移动端即时通讯解决方案的同时,环信也开始了在连接人与商业、物与物版块的IM生态布局。环信CEO刘俊彦深剖环信移动客服的核心技术,以及对开源与未来无所不在的客服场景畅想。上线一年多的时间,环信的团队已经扩大到一百多人,在专注于为开发者提供移动端即时通讯解决方案的同时,环信开始了在连接人与商业、物与物版块的IM生态布局。并于近期推出专为移动端打造的客服平台,与环信IM SDK共享核心代码。本期《近匠》专访环信CEO 刘俊彦,听他讲述打造环信移动客服的核心技术与挑战,以及环信对开源与未来无所不在的客服场景畅想。





图:环信CEO 刘俊彦

CSDN:最初决定打造这样一个移动客服平台有着哪些初衷和考虑?

刘俊彦:首先从现实说起,从去年上线之后,就不断地有海淘、生活O2O等领域的开发者表示,使用环信IM SDK来做手机App的内置客服通道还是很好用的,但希望环信同时还能够提供一个具备客服工作台、工单分配、KPI考核等功能的客服平台。其实我的第一反应是拒绝的,因为这好像与即时通讯本身并没有太大关系,但随着这方面用户需求的增长,我们便开始思考这个问题。

其次,与战略方面也有所契合,我们所希望的是能够通过环信将所有人、物都连接起来,但之前却只拘泥于连接人与人的社交,在环信的版图中缺少着连接人与商业、人和客户的版块。因此,我们决定开发移动客服系统,让用户和商家可以直接在应用中聊起来,打造出一个完整的IM生态蓝图。

CSDN:在环信的产品线中,移动客服平台有着什么样的定位?

刘俊彦:移动客服平台是一个在IM基础上的行业应用,在IM已经覆盖几亿用户之后,我们就在思考下一步做什么?如果一款产品或某项功能能够真真切切地帮助到我们的IM用户,体验更爽,更有粘性,我们都会进行尝试。其实我们做了很多类似的工作,比如最近上线的关键字检测功能,就是为用户提供IM之上的最后一公里的额外的服务。移动客服同样如此,移动客服的核心还是IM,但我们同时还提供全套的完整的客服工作后台,有客户服务支持需求的用户不需要任何开发就可以直接使用,因此,我们将移动客服定位为IM在客户服务行业的垂直应用。

CSDN:云客服模式其实早有应用,相比其他服务提供商,环信移动客服平台有着哪些特色及技术优势?

刘俊彦:当下的客服软件市场分为两部分,一是传统电话呼叫中心的客服,他们的沟通方式以语音沟通为主,第二类是非语音类的客服,一般归纳为新媒体客服。新媒体客服包含微信公众号、微博、网页、App等渠道来源。对网页端的客服渠道来说,其对客服服务器的并发技术要求并不高,因为通常是使用基于轮询的短连接技术。比如每天有十万人找客服咨询聊天,每人聊五分钟,那么平均到每秒钟也就最多2-3个人同时在聊天,服务器只需要支持每秒钟2到3个请求的并发,对服务器压力很小。但手机App客服就不一样了。从技术上来讲,好用的手机App客服技术要求手机与客服服务器之间保持着7x24的长连接。任何时候,只要用户不卸载你的App,客服就永远可以主动的去找到消费者,向他主动发送消息。举个例子,我们有的用户用这个技术做外呼营销。他先在自己的CRM系统里对他的用户挖掘打上标签,比如找到所有的2-4岁小孩的妈妈用户群体。然后向这类妈妈群体群发消息。发出去的促销消息在消费者的App端看来是一条推送过来的聊天消息,首先这个消息不会被错过。然后点击这个推送后就会进入到客服的一对一聊天页面。这样的促销消息发送方式因为是和真人客服之间一对一的双向交互,所以效果比那种单向的广告推送好很多,转化率非常高。类似这样的外呼营销方式,让客服部门从以前的成本中心变成了现在的营收中心。而这些营销方式,如果没有手机APP和客服服务器之间的IM长连接,是不可能做到的。

当然,IM长连接技术对服务器的技术能力以及成本压力也增大许多,因为哪怕一个用户从来没找过客服聊天,我们也要为这个用户在他的手机和服务器端之间维护一个长连接,这个长连接会7X24小时的运行着。通常有100万的月活,就意味着要维护100万的长连接。但这却是环信的优势所在。环信移动客服平台与其他客服提供商最大的区别就是在移动端的IM长连接技术。在这点上,环信基本是垄断地位。

CSDN:可否详解环信移动客服平台的智能应答系统在面对海量请求时,如何做到真正智能地屏蔽与提炼?

刘俊彦:全球有100亿设备24小时连在网上,他们随时随地都能通过移动设备内置的客服通道找到客服,所以移动端的客服要应对的请求可能是海量的。对客服部门来说,利用原本的人工客服团队再加上新型的智能机器人客服系统,可以让问题解决效率呈指数性增长。传统的聊天机器人技术是基于搜索的问答匹配,而环信的智能客服是最新的基于深度机器学习的技术,不仅可以根据上下文进行推理,还能对人工座席和客户的交流进行实时学习和训练,极大降低知识库的维护成本。

目前,智能聊天机器人技术最实际的应用场景是基于文字交互的客服系统,包括短信、微信公众号、App内置客服、网页在线客服等,不仅降低了原本一年四季24小时在线的客服中心成本,更让拥有极致用户体验的新一代客服中心成为可能。

但是,相比之下,人工服务永远是最智能、最好的服务,在产品设计上,应实现人工与智能服务的无缝切换,当智能客服回答比较勉为其难的时候,就直接切换到人工服务,这样才能为客户提供更好的体验。所以客服系统中的聊天机器人技术最重要的是做好人工座席和机器人座席之间的无缝高效的切换,而不用刻意追求智能机器人技术的智能程度。客服系统中的智能聊天机器人只需解决特定领域的知识问题,无需像微软小冰那样陪用户聊人生聊理想。

CSDN:在移动客服平台开发的过程中,遇到过哪些难点与挑战?如何解决的?

刘俊彦:对移动客服来说,有两个技术难点。首当其冲便是在手机上为客户提供服务,IM技术是最适合用来在手机上连接客户和商家的。IM长连接技术能保障客服随时随地主动联系到客户、断网或复杂网络切换时不丢客户,并对电量流量进行优化。同时,也必须让客服人员、商家使用起来非常爽,即客服工作台好不好用、能不能提高客服效率、是否能进行全方位的KPI考核等。

对客服而言,即时通讯可谓是重中之重,在纯社交领域,消息丢失或晚到可能不是太大问题,但客服不一样,如果一条消息丢失或延迟,可能就意味着会发生丢单、客户流失情况,商业损失会非常大。所以对于选购移动客服的商家来说,他们希望移动端的IM技术和支撑客服工作人员的客服后台技术能够由一个厂商来统一提供。而不是说需要客服后台用这家,即时通讯买那家,这样在使用移动客服产品过程中遇到任何问题,都可以通过一个厂商一次性地及时解决。

CSDN:在移动网络环境下,弱网络、丢消息、丢订单等问题天然存在,环信采取了哪些技术手段来解决这一难题?通过哪些机制确保做到真正的不丢消息、不丢客户订单,还能省电省流量?

刘俊彦:这是环信过去一年多一直在做的事情,其实大多数IM厂商也能保证做到,但这的确还存在一些技术难点。首先,如何保证不丢消息?就必须通过一个好的协议来实现,必须保证协议本身是完全可靠,一定不会丢消息的,而在电量、流量的节约方面则包含协议、实现等诸多层面的优化。当然,无论是电量、流量的节约还是保证消息及时到达,除了最根本的协议、架构等,还包括许多细节方面的长时间打磨,才能不断地进步。
举个例子,环信在去年针对用户需求进行了许多优化,其中有一点便是针对来自三四线城市使用2G网络的用户,在弱网络环境下发送图片速度非常慢的问题,进行了切片上传的优化,将一个50K大小的图片切成10片,开10个线程,同时上传,极大地提高了传送的成功率。

CSDN:将UI模板开源让开发者100%自定制是环信一直以来的做法,之前也上线了“更极客 更开源”的IM Geek开发者社区,并将SDK开源,请问环信在开源方面有着哪些具体的计划和措施?

刘俊彦:环信的创始成员都是做开源出身,现在有些人对开源软件存在误解,而我们从不认为开源软件就意味着不好、不安全、低质量,这点从Linux就可以显而易见。我曾在Redhat担任高级开发工程师的工作,现在,许多公司都在使用Linux,也没有人会给予Linux不安全、不好用等差评。我们所希望的,不是自己重新去发明轮子,而是站在前人的肩膀上,取其精华去其糟粕,来进行自己的开发,比如最初在设计环信的通讯协议时,我们就借鉴了一部分XMPP的核心模块精华。

但XMPP协议并非为移动端设计,XMPP出现时还没有移动设备。在PC时代,用户不需要考虑电量、流量等问题,并且也不存在弱网络导致消息丢失的问题。这也就表明,我们必须将其中不好的部分推倒,进行重新设计或重写,开发出适用于移动端的IM协议。当然,XMPP也拥有很多优点,它存在十年,有许多插件,并充分考虑到协议的扩展,它是经过许多人不断摸索制定出来的协议,拥有着非常高的价值。

在使用开源软件的同时,我们也会反哺回馈开源社区,环信公司内的技术团队现在至少有十多个人都是一些知名的开源软件的committer,一直都在为开源软件贡献力量。现在有些公司可能会担心用开源软件出了问题后不可控制,这说明他们并没有用真正开源人的精神去使用开源软件,对于存在瑕疵的地方,就应该去改写代码,让它变得更好,而不是直接弃之如敝履。在开发过程中,如果使用到存在问题的开源软件,我们要做的事情就是去进行修改完善,然后将代码提交回去,让整个开源社区都能收益,这是环信对每个工程师的要求。

无论是将UI模板100%开源还是上线IM Geek开发者社区,我们的真正目的就是为开源社区做贡献,而不只是环信的产品。其实在当下的国内外开源社区方面,IM和移动社交还是空白的存在。现在,很多人都在做朋友圈、附近的人、聊天、匿名聊天或群组等功能,但归纳起来大概只有二三十种模块,剩下的工作便是各种模块的组合及编组。所以我们的想法就是开发者不用自己再去劳心劳力地重新开发一些基础和常见模块,而是通过社区的力量将这些模块都开发并开源出来,甚至包括基于这些模块的完整的应用,统统开源。这样不仅能节省创业团队大量的时间精力,也能降低开发成本,将资金投入到更好的用户体验、设计及运营上。

要经营好开源社区就必须以身作则,环信自身也在不断地贡献开源模块。当然,开源社区光靠一时的热情是远远不够的,未来,环信会为乐于开源的committer提供经济上的资助,只要开源软件做得好,并将其回馈给社区,提供开放下载。我们非常欢迎有开源情怀的开发者投身到开源事业中。

CSDN:环信移动客服在安全及保护用户隐私数据等方面有着哪些具体措施?

刘俊彦:隐私一直是很多公司一直在意的问题,会担心商业数据、用户信息会不会被窃取?环信移动客服对这方面是非常注意的,不会以任何形式碰触用户的聊天记录,用户可以100%随时导出或删除。而在系统保障方面,环信到目前已经趟过了许多雷点,并且内部还有一个每月演习的硬性规定,以此来保障即使发生系统挂掉的情况,核心功能依然可用。此外,环信正在着手“异地多活”,以此来提供更可靠、安全的服务。

CSDN:移动客服系统如何收费?

刘俊彦:IM已成红海,而移动客服则是商业化的企业级服务,需要为企业出现丢单等情况负责。环信移动客服系统的收费标准分为免费和收费用户数量级,2个座席以内可免费使用,超过2个座席的公司,需按每年每座席1500元进行收费。





图:环信移动客服收费标准

CSDN:现在大部分客服请求均来自于移动端,环信对于未来的移动客户服务还有着哪些畅想?

刘俊彦:当下,客户服务软件行业正在经历一场变革,用户获得服务的渠道和行为在发生巨变。随着环信移动客服这样的产品的普及,用户的服务体验将有极大的提升,而依托于技术进步,商家为此投入的人力成本却呈下降趋势。环信已经实现了人与人、人与商业的连接,但其生态布局依然缺少一块,就是人与物、物与物的连接。物联网正在临近,客户服务更将呈现完全不同的场景。我们需要做什么?首先就是物与物之间实现通讯功能的实时数据交换,其次,人如何控制设备?第三,在物与物之上,人和人之间需要沟通。

比如,一个物联网冰箱发生故障后,用户肯定不会再打400电话了。用户只需直接点击冰箱内嵌的客服按钮,即可一键接通,不仅可以和客服视频聊天得到帮助,还可以将冰箱的相关参数发送给客服,快速解决问题。同时,未来的客服一定是内嵌型的,将无处不在,无论是App、智能家居还是车联网,一个按钮所有问题都能搞定。目前,环信已经在着手物联网IM产品研发。 查看全部
摘要:《近匠》第92期,在专注于为开发者提供移动端即时通讯解决方案的同时,环信也开始了在连接人与商业、物与物版块的IM生态布局。环信CEO刘俊彦深剖环信移动客服的核心技术,以及对开源与未来无所不在的客服场景畅想。上线一年多的时间,环信的团队已经扩大到一百多人,在专注于为开发者提供移动端即时通讯解决方案的同时,环信开始了在连接人与商业、物与物版块的IM生态布局。并于近期推出专为移动端打造的客服平台,与环信IM SDK共享核心代码。本期《近匠》专访环信CEO 刘俊彦,听他讲述打造环信移动客服的核心技术与挑战,以及环信对开源与未来无所不在的客服场景畅想。

1.jpg

图:环信CEO 刘俊彦

CSDN:最初决定打造这样一个移动客服平台有着哪些初衷和考虑?

刘俊彦:首先从现实说起,从去年上线之后,就不断地有海淘、生活O2O等领域的开发者表示,使用环信IM SDK来做手机App的内置客服通道还是很好用的,但希望环信同时还能够提供一个具备客服工作台、工单分配、KPI考核等功能的客服平台。其实我的第一反应是拒绝的,因为这好像与即时通讯本身并没有太大关系,但随着这方面用户需求的增长,我们便开始思考这个问题。

其次,与战略方面也有所契合,我们所希望的是能够通过环信将所有人、物都连接起来,但之前却只拘泥于连接人与人的社交,在环信的版图中缺少着连接人与商业、人和客户的版块。因此,我们决定开发移动客服系统,让用户和商家可以直接在应用中聊起来,打造出一个完整的IM生态蓝图。

CSDN:在环信的产品线中,移动客服平台有着什么样的定位?

刘俊彦:移动客服平台是一个在IM基础上的行业应用,在IM已经覆盖几亿用户之后,我们就在思考下一步做什么?如果一款产品或某项功能能够真真切切地帮助到我们的IM用户,体验更爽,更有粘性,我们都会进行尝试。其实我们做了很多类似的工作,比如最近上线的关键字检测功能,就是为用户提供IM之上的最后一公里的额外的服务。移动客服同样如此,移动客服的核心还是IM,但我们同时还提供全套的完整的客服工作后台,有客户服务支持需求的用户不需要任何开发就可以直接使用,因此,我们将移动客服定位为IM在客户服务行业的垂直应用。

CSDN:云客服模式其实早有应用,相比其他服务提供商,环信移动客服平台有着哪些特色及技术优势?

刘俊彦:当下的客服软件市场分为两部分,一是传统电话呼叫中心的客服,他们的沟通方式以语音沟通为主,第二类是非语音类的客服,一般归纳为新媒体客服。新媒体客服包含微信公众号、微博、网页、App等渠道来源。对网页端的客服渠道来说,其对客服服务器的并发技术要求并不高,因为通常是使用基于轮询的短连接技术。比如每天有十万人找客服咨询聊天,每人聊五分钟,那么平均到每秒钟也就最多2-3个人同时在聊天,服务器只需要支持每秒钟2到3个请求的并发,对服务器压力很小。但手机App客服就不一样了。从技术上来讲,好用的手机App客服技术要求手机与客服服务器之间保持着7x24的长连接。任何时候,只要用户不卸载你的App,客服就永远可以主动的去找到消费者,向他主动发送消息。举个例子,我们有的用户用这个技术做外呼营销。他先在自己的CRM系统里对他的用户挖掘打上标签,比如找到所有的2-4岁小孩的妈妈用户群体。然后向这类妈妈群体群发消息。发出去的促销消息在消费者的App端看来是一条推送过来的聊天消息,首先这个消息不会被错过。然后点击这个推送后就会进入到客服的一对一聊天页面。这样的促销消息发送方式因为是和真人客服之间一对一的双向交互,所以效果比那种单向的广告推送好很多,转化率非常高。类似这样的外呼营销方式,让客服部门从以前的成本中心变成了现在的营收中心。而这些营销方式,如果没有手机APP和客服服务器之间的IM长连接,是不可能做到的。

当然,IM长连接技术对服务器的技术能力以及成本压力也增大许多,因为哪怕一个用户从来没找过客服聊天,我们也要为这个用户在他的手机和服务器端之间维护一个长连接,这个长连接会7X24小时的运行着。通常有100万的月活,就意味着要维护100万的长连接。但这却是环信的优势所在。环信移动客服平台与其他客服提供商最大的区别就是在移动端的IM长连接技术。在这点上,环信基本是垄断地位。

CSDN:可否详解环信移动客服平台的智能应答系统在面对海量请求时,如何做到真正智能地屏蔽与提炼?

刘俊彦:全球有100亿设备24小时连在网上,他们随时随地都能通过移动设备内置的客服通道找到客服,所以移动端的客服要应对的请求可能是海量的。对客服部门来说,利用原本的人工客服团队再加上新型的智能机器人客服系统,可以让问题解决效率呈指数性增长。传统的聊天机器人技术是基于搜索的问答匹配,而环信的智能客服是最新的基于深度机器学习的技术,不仅可以根据上下文进行推理,还能对人工座席和客户的交流进行实时学习和训练,极大降低知识库的维护成本。

目前,智能聊天机器人技术最实际的应用场景是基于文字交互的客服系统,包括短信、微信公众号、App内置客服、网页在线客服等,不仅降低了原本一年四季24小时在线的客服中心成本,更让拥有极致用户体验的新一代客服中心成为可能。

但是,相比之下,人工服务永远是最智能、最好的服务,在产品设计上,应实现人工与智能服务的无缝切换,当智能客服回答比较勉为其难的时候,就直接切换到人工服务,这样才能为客户提供更好的体验。所以客服系统中的聊天机器人技术最重要的是做好人工座席和机器人座席之间的无缝高效的切换,而不用刻意追求智能机器人技术的智能程度。客服系统中的智能聊天机器人只需解决特定领域的知识问题,无需像微软小冰那样陪用户聊人生聊理想。

CSDN:在移动客服平台开发的过程中,遇到过哪些难点与挑战?如何解决的?

刘俊彦:对移动客服来说,有两个技术难点。首当其冲便是在手机上为客户提供服务,IM技术是最适合用来在手机上连接客户和商家的。IM长连接技术能保障客服随时随地主动联系到客户、断网或复杂网络切换时不丢客户,并对电量流量进行优化。同时,也必须让客服人员、商家使用起来非常爽,即客服工作台好不好用、能不能提高客服效率、是否能进行全方位的KPI考核等。

对客服而言,即时通讯可谓是重中之重,在纯社交领域,消息丢失或晚到可能不是太大问题,但客服不一样,如果一条消息丢失或延迟,可能就意味着会发生丢单、客户流失情况,商业损失会非常大。所以对于选购移动客服的商家来说,他们希望移动端的IM技术和支撑客服工作人员的客服后台技术能够由一个厂商来统一提供。而不是说需要客服后台用这家,即时通讯买那家,这样在使用移动客服产品过程中遇到任何问题,都可以通过一个厂商一次性地及时解决。

CSDN:在移动网络环境下,弱网络、丢消息、丢订单等问题天然存在,环信采取了哪些技术手段来解决这一难题?通过哪些机制确保做到真正的不丢消息、不丢客户订单,还能省电省流量?

刘俊彦:这是环信过去一年多一直在做的事情,其实大多数IM厂商也能保证做到,但这的确还存在一些技术难点。首先,如何保证不丢消息?就必须通过一个好的协议来实现,必须保证协议本身是完全可靠,一定不会丢消息的,而在电量、流量的节约方面则包含协议、实现等诸多层面的优化。当然,无论是电量、流量的节约还是保证消息及时到达,除了最根本的协议、架构等,还包括许多细节方面的长时间打磨,才能不断地进步。
举个例子,环信在去年针对用户需求进行了许多优化,其中有一点便是针对来自三四线城市使用2G网络的用户,在弱网络环境下发送图片速度非常慢的问题,进行了切片上传的优化,将一个50K大小的图片切成10片,开10个线程,同时上传,极大地提高了传送的成功率。

CSDN:将UI模板开源让开发者100%自定制是环信一直以来的做法,之前也上线了“更极客 更开源”的IM Geek开发者社区,并将SDK开源,请问环信在开源方面有着哪些具体的计划和措施?

刘俊彦:环信的创始成员都是做开源出身,现在有些人对开源软件存在误解,而我们从不认为开源软件就意味着不好、不安全、低质量,这点从Linux就可以显而易见。我曾在Redhat担任高级开发工程师的工作,现在,许多公司都在使用Linux,也没有人会给予Linux不安全、不好用等差评。我们所希望的,不是自己重新去发明轮子,而是站在前人的肩膀上,取其精华去其糟粕,来进行自己的开发,比如最初在设计环信的通讯协议时,我们就借鉴了一部分XMPP的核心模块精华。

但XMPP协议并非为移动端设计,XMPP出现时还没有移动设备。在PC时代,用户不需要考虑电量、流量等问题,并且也不存在弱网络导致消息丢失的问题。这也就表明,我们必须将其中不好的部分推倒,进行重新设计或重写,开发出适用于移动端的IM协议。当然,XMPP也拥有很多优点,它存在十年,有许多插件,并充分考虑到协议的扩展,它是经过许多人不断摸索制定出来的协议,拥有着非常高的价值。

在使用开源软件的同时,我们也会反哺回馈开源社区,环信公司内的技术团队现在至少有十多个人都是一些知名的开源软件的committer,一直都在为开源软件贡献力量。现在有些公司可能会担心用开源软件出了问题后不可控制,这说明他们并没有用真正开源人的精神去使用开源软件,对于存在瑕疵的地方,就应该去改写代码,让它变得更好,而不是直接弃之如敝履。在开发过程中,如果使用到存在问题的开源软件,我们要做的事情就是去进行修改完善,然后将代码提交回去,让整个开源社区都能收益,这是环信对每个工程师的要求。

无论是将UI模板100%开源还是上线IM Geek开发者社区,我们的真正目的就是为开源社区做贡献,而不只是环信的产品。其实在当下的国内外开源社区方面,IM和移动社交还是空白的存在。现在,很多人都在做朋友圈、附近的人、聊天、匿名聊天或群组等功能,但归纳起来大概只有二三十种模块,剩下的工作便是各种模块的组合及编组。所以我们的想法就是开发者不用自己再去劳心劳力地重新开发一些基础和常见模块,而是通过社区的力量将这些模块都开发并开源出来,甚至包括基于这些模块的完整的应用,统统开源。这样不仅能节省创业团队大量的时间精力,也能降低开发成本,将资金投入到更好的用户体验、设计及运营上。

要经营好开源社区就必须以身作则,环信自身也在不断地贡献开源模块。当然,开源社区光靠一时的热情是远远不够的,未来,环信会为乐于开源的committer提供经济上的资助,只要开源软件做得好,并将其回馈给社区,提供开放下载。我们非常欢迎有开源情怀的开发者投身到开源事业中。

CSDN:环信移动客服在安全及保护用户隐私数据等方面有着哪些具体措施?

刘俊彦:隐私一直是很多公司一直在意的问题,会担心商业数据、用户信息会不会被窃取?环信移动客服对这方面是非常注意的,不会以任何形式碰触用户的聊天记录,用户可以100%随时导出或删除。而在系统保障方面,环信到目前已经趟过了许多雷点,并且内部还有一个每月演习的硬性规定,以此来保障即使发生系统挂掉的情况,核心功能依然可用。此外,环信正在着手“异地多活”,以此来提供更可靠、安全的服务。

CSDN:移动客服系统如何收费?

刘俊彦:IM已成红海,而移动客服则是商业化的企业级服务,需要为企业出现丢单等情况负责。环信移动客服系统的收费标准分为免费和收费用户数量级,2个座席以内可免费使用,超过2个座席的公司,需按每年每座席1500元进行收费。

2.jpg

图:环信移动客服收费标准

CSDN:现在大部分客服请求均来自于移动端,环信对于未来的移动客户服务还有着哪些畅想?

刘俊彦:当下,客户服务软件行业正在经历一场变革,用户获得服务的渠道和行为在发生巨变。随着环信移动客服这样的产品的普及,用户的服务体验将有极大的提升,而依托于技术进步,商家为此投入的人力成本却呈下降趋势。环信已经实现了人与人、人与商业的连接,但其生态布局依然缺少一块,就是人与物、物与物的连接。物联网正在临近,客户服务更将呈现完全不同的场景。我们需要做什么?首先就是物与物之间实现通讯功能的实时数据交换,其次,人如何控制设备?第三,在物与物之上,人和人之间需要沟通。

比如,一个物联网冰箱发生故障后,用户肯定不会再打400电话了。用户只需直接点击冰箱内嵌的客服按钮,即可一键接通,不仅可以和客服视频聊天得到帮助,还可以将冰箱的相关参数发送给客服,快速解决问题。同时,未来的客服一定是内嵌型的,将无处不在,无论是App、智能家居还是车联网,一个按钮所有问题都能搞定。目前,环信已经在着手物联网IM产品研发。
0
评论

App崩溃分析:如何监控http请求并做出优化? 移动开发

oscar1212 发表了文章 • 2193 次浏览 • 2015-07-14 16:09 • 来自相关话题

移动互联网时代,移动App与服务器之间的交互越来越频繁,数据量也越来越大,伴随而来的各种网络连接问题也在影响着各App的留存率。如何保证http请求的质量成为开发者们需要解决的一大问题。本文着重讲述http请求遇到的问题以及该如何监控和优化。

http请求遇到的问题

在App开发过程中,通常是用无线网络去做测试,这样网络的连通率、速度以及响应时间都是处在一个相对理想的情况下,但是在App发布后,用户使用场景往往是2G、3G,以及一些网络水平初级的地区,网速和连通率都在一个不稳定甚至极低的水平,这时,一系列的问题随之而来,其中我们主要讨论两点:
响应时间:由于网络速度的下降, 响应时间开始变长,同一个url的访问时间可能会成倍增长,增加用户的等待时间;错误率:由于网络质量的下降,丢包错包概率成倍增长,由于请求的错误也会导致服务器端处理错误率的提高,可能会造成返回数据为空或者错误,致使用户增加使用成本。

如何去优化?

应用向服务器发送http请求,一般都是调用的系统接口或者第三方接口(比如OKHttp):    




这个时候,我们可以在应用调用接口时,加一个收集模块来采集http信息,如图:





Collection module可以用不同的实现方式:iOS利用Runtime通过代码注入的方式去获取相关信息;Android通过自定义URLStreamHandler去获取http信息,之后通过一些统计工具可以直观地去分析和优化应用的网络模块。

如何利用网络监控去做优化?

那么,究竟该如何利用好网络监控来进行应用优化?开发者可以从http响应时间、http错误率、请求量(rpm)和Data I/O四个维度监控http请求,并监测每个url的运营商、终端设备、错误码。同时,地理定位功能可以提供每个地区网络状况的平均值,方便开发者去分析和优化。
http响应时间

通过响应时间的长短,可以判断哪个url去优化,如果响应时间长,是不是后台查询过慢?还是因为运营商基站建的少网络信号差?
http错误率

通过错误率,可以知道访问某个url时最多的错误码是多少,根据错误码去确定是请求错误还是服务器错误,从而缩小问题的查找范围。
请求量(rpm)

通过查看url的请求量,可以去推断用户的喜好,从而做一些定制化的服务,也可以通过这个指标去确定App端发请求频率是否正常。
Data I/O

通过Data I/O,可以知道某个url的请求数据大小是否正常,是否流量过大可以进行压缩从而节省用户的费用。





当然,每个指标不是独立的,而是应该综合来判断。举一个例子,做一个在线图库的应用,用户反映一直刷不出图,那就可以这样推断一下:看http响应时间,如果正常,有可能是App收到数据后显示有问题,如果过长,那么可能是服务器端问题;再看错误率,如果很高,那么有可能是服务器返回结果有问题,如果不高,那么有可能是因为网络信号差导致的。

这个时候,再看一下请求量和Data I/O,如果请求量很小,但是Data I/O很高,那么是否可以优化http请求策略?如果改成每次请求一屏的数据,根据用户的翻页情况发送多次请求,而不是一次去请求几页数据,那么这样数据总量没变,但是用户看到的效果却是每翻一页,只要很少的时间就可以显示出图片,这样就可以提升用户体验。

简单论述了网络问题对于移动App产生的影响,以及如何去监控http请求并做出优化。当然,实现监控的方式有很多,也可以有很多技术上的玩法,但无论技术实现得有多好,如何优化App?提升用户体验和留存率,才是开发者最该关心的问题。
  查看全部
移动互联网时代,移动App与服务器之间的交互越来越频繁,数据量也越来越大,伴随而来的各种网络连接问题也在影响着各App的留存率。如何保证http请求的质量成为开发者们需要解决的一大问题。本文着重讲述http请求遇到的问题以及该如何监控和优化。

http请求遇到的问题

在App开发过程中,通常是用无线网络去做测试,这样网络的连通率、速度以及响应时间都是处在一个相对理想的情况下,但是在App发布后,用户使用场景往往是2G、3G,以及一些网络水平初级的地区,网速和连通率都在一个不稳定甚至极低的水平,这时,一系列的问题随之而来,其中我们主要讨论两点:
  • 响应时间:由于网络速度的下降, 响应时间开始变长,同一个url的访问时间可能会成倍增长,增加用户的等待时间;
  • 错误率:由于网络质量的下降,丢包错包概率成倍增长,由于请求的错误也会导致服务器端处理错误率的提高,可能会造成返回数据为空或者错误,致使用户增加使用成本。


如何去优化?

应用向服务器发送http请求,一般都是调用的系统接口或者第三方接口(比如OKHttp):    
1.jpg

这个时候,我们可以在应用调用接口时,加一个收集模块来采集http信息,如图:

2.jpg

Collection module可以用不同的实现方式:iOS利用Runtime通过代码注入的方式去获取相关信息;Android通过自定义URLStreamHandler去获取http信息,之后通过一些统计工具可以直观地去分析和优化应用的网络模块。

如何利用网络监控去做优化?

那么,究竟该如何利用好网络监控来进行应用优化?开发者可以从http响应时间、http错误率、请求量(rpm)和Data I/O四个维度监控http请求,并监测每个url的运营商、终端设备、错误码。同时,地理定位功能可以提供每个地区网络状况的平均值,方便开发者去分析和优化。
  • http响应时间


通过响应时间的长短,可以判断哪个url去优化,如果响应时间长,是不是后台查询过慢?还是因为运营商基站建的少网络信号差?
  • http错误率


通过错误率,可以知道访问某个url时最多的错误码是多少,根据错误码去确定是请求错误还是服务器错误,从而缩小问题的查找范围。
  • 请求量(rpm)


通过查看url的请求量,可以去推断用户的喜好,从而做一些定制化的服务,也可以通过这个指标去确定App端发请求频率是否正常。
  • Data I/O


通过Data I/O,可以知道某个url的请求数据大小是否正常,是否流量过大可以进行压缩从而节省用户的费用。

3.jpg

当然,每个指标不是独立的,而是应该综合来判断。举一个例子,做一个在线图库的应用,用户反映一直刷不出图,那就可以这样推断一下:看http响应时间,如果正常,有可能是App收到数据后显示有问题,如果过长,那么可能是服务器端问题;再看错误率,如果很高,那么有可能是服务器返回结果有问题,如果不高,那么有可能是因为网络信号差导致的。

这个时候,再看一下请求量和Data I/O,如果请求量很小,但是Data I/O很高,那么是否可以优化http请求策略?如果改成每次请求一屏的数据,根据用户的翻页情况发送多次请求,而不是一次去请求几页数据,那么这样数据总量没变,但是用户看到的效果却是每翻一页,只要很少的时间就可以显示出图片,这样就可以提升用户体验。

简单论述了网络问题对于移动App产生的影响,以及如何去监控http请求并做出优化。当然,实现监控的方式有很多,也可以有很多技术上的玩法,但无论技术实现得有多好,如何优化App?提升用户体验和留存率,才是开发者最该关心的问题。
 
0
评论

一个社交App是如何构建高伸缩性的交互式系统 移动开发

oscar1212 发表了文章 • 3122 次浏览 • 2015-07-13 12:15 • 来自相关话题

一个社交App需实现的功能

用户关注的常规社交功能、活动、地理位置、探索功能、新鲜事、视频照片分享等等,需要提供的功能不胜枚举,所以从技术角度来说,开发者需要解决的问题也是异常复杂的。

当一款社交App发布之初,用户访问量比较小,使用一台服务器就能够支撑全部的访问压力和数据存储需求,但是互联网应用具有病毒式的传播特点。一款App很可能会面临一夜爆红的现象,访问量和数据量在短时间内呈现爆发式增长,这时候会面临的局面是每天上亿PV、数百万新增用户和活跃用户、流量飙升至每秒数百兆。这些对于一个只部署了简单后端架构的应用来讲是无法支撑的,会直接导致服务器响应缓慢甚至超时,以及在高峰期时服务呈现瘫痪状态,使得后端的服务完全无法使用,用户体验急剧下降。本文将会通过一个真实的案例来分享一个社交应用如何构建一个具备高伸缩性的后端系统。

社交App最初部署的后端架构解析

社交App在最初的时候,后端架构相对比较简单,最初是部署在基础网络之上。最前面放置一台绑定了公网IP的nginx服务器作负载均衡,后面放置3台应用服务器来负责处理所有业务上的请求,最后面搭建一台MySQL Database数据库。





 
构建私有网络

随着产品的不断迭代、用户数的持续增长、数据量的积累,App就需要改进自己的后端架构,即开始构建私有网络。用户可以使用私有网络构建自己的网络拓扑——创建路由器和私有网络,将后续加入的用于运行内部服务的主机放置在私用网络中,可以有效地和云平台其他用户主机,在网络上实现100%二层隔离。主机对外开放的仅仅只有80端口,这样系统安全性上多了一层保障。






在上面的架构图中,最前面的是防火墙,后面接负载均衡器,然后接路由器和私有网络,很多互联网应用都存在读多写少的情况,这个比例有时可以达到8:2,所以我们首先通过引入缓存分摊数据库读压力。其次,引入负载均衡器,替换最初架构中的nginx proxy,负责均衡器在这里其主要用于分发请求到后端多台应用服务器,,当其中一台应用服务器挂掉,负载均衡器可以进行自动隔离。

业务分区与扩展

App随着并发访问量和数据量不断增大,首先想到横向扩容Web服务。水平扩容业务服务器的前提是要保证每台服务器都是无状态的,将session信息下放到缓存或数据库中存储,保证请求被负载到任何一台服务器可以正常处理。






从上图中看到,在前一步「构建私有网络」之后,增加了一个新的私有网络来扩展网络层,这里可以利用自有映像功能,将原有的应用服务器制作成模板,后续就可以基于这个模板快速启动新的主机。另外可以利用Auto-scaling(自动横向扩展)功能,根据后端服务器的负载请求,动态调整服务器的数量。

一个社交应用的后端会提供很多服务请求接口,比如添加好友、刷新新鲜事、浏览页面等,可以通过日志分析每一个接口的耗时,将耗时长但非重要业务的请求分到单独的Web服务器上进行处理,从而给主Web服务器留出更多资源去处理关键业务的请求。

面向服务的架构

随着产品功能的不断迭代,业务代码会越来越复杂,出现故障的可能性也在加大,当一个局部功能出现问题时,都会影响整个服务的可用性。此时可以构建面向服务的架构,将一个完整且庞大的服务拆分为一个个的子服务,服务之间通过接口交互。如下图所示:






社交App的服务被拆分成了四个子服务——新鲜事(News Feed)、用户资料(Profile)、广告(Ads)和探索(Explore),不同的服务之间通过消息通信框架(例如ZeroMQ)来进行交互。把一个大服务拆分为几个小的子服务的好处不言而喻,主要是:
故障隔离:子服务出现故障不会影响全局,比如广告业务出现问题并不会让整个App不能使用,依然可以查看新鲜事等;独立扩展:每一个被拆分出的子服务有着不同的访问压力,比如新鲜事的调用相比一些二级页面的用户资料要高很多,所以前者会被分配更多的Web 服务器;独立部署:一个大服务的配置因功能过多会异常复杂,一旦被拆分就可根据不同的特性需求定制配置项,从而提高可管理性;团队协作开发:开发者都有着自己精通的方向,从而提高开发效率;抽象出数据访问:在后续进行数据层面(数据库、缓存)扩展时,可通过修改子服务的Data Service,实现对下层数据的透明。

数据库Replication

业务增长也会给数据库带来诸多问题,当最初架构中单台数据库(数据库同时提供读和写)不足已支撑起App访问压力时,首先需要做数据副本Replication。市面上常见的MySQL、MongoDB等数据库都提供Replication功能,以MySQL为例,从高层来看,Replication可分成三步:
Master将改变记录到二进制日志(binary log)中(这些记录叫做二进制日志事件,binary log events);Slave将Master的binary log events拷贝到它的中继日志(relay log);Slave重做中继日志中的事件,将改变反映它自己的数据。

具体实现该过程的第一部分就是Master记录二进制日志。在每个事务更新数据完成之前,Master在二进制日志记录这些改变。MySQL将事务串行的写入二进制日志,即使事务中的语句都是交叉执行的。在事件写入二进制日志完成后,Master通知存储引擎提交事务。

下一步就是Slave将Master的binary log拷贝到它自己的中继日志。首先,Slave开始一个工作线程——I/O线程。I/O线程在Master上打开一个普通的连接,然后开始binlog dump process。Binlog dump process从Master的二进制日志中读取事件,如果已经跟上Master,它会睡眠并等待Master产生新的事件。I/O线程将这些事件写入中继日志。

SQL slave thread处理该过程的最后一步。SQL线程从中继日志读取事件,更新Slave的数据,使其与Master中的数据一致。只要该线程与I/O线程保持一致,中继日志通常会位于OS的缓存中,所以中继日志的开销很小。

此外,在Master中也有一个工作线程:和其它MySQL的连接一样,Slave在Master中打开一个连接也会使得Master开始一个线程。复制过程有一个很重要的限制——复制在Slave上是串行化的,也就是说Master上的并行更新操作不能在Slave上并行操作。

对于云计算使用者来说,只需要知道数据库的IP和端口即可进行使用。具体实现见下图:





第一步要做的是扩充Slave,将单机Master变成Master+3台Slave的架构,而在其中的Slave上搭建一个内网的负载均衡器(Load Balancer),对于最上层的Data Service来说,只要配置一个MySQL Master节点和一个LB节点即可,今后因业务变化进行增减Slave对上层来说完全是透明的。

此做法可以带来两个好处,第一是提高可用性,若是一台Master出现错误,则可以提升某一台的Slave作为Master继续提供服务,从而保证数据可用性;第二个是分摊读压力,对于一个社交App来说,读写分离是在数据层优化第一步要做的事情,利用上面的架构可以很轻易地做到将读的请求分担到MySQL Slave上进行查询,而写留给Master。但是读写分离时会有数据库一致性的问题,即在数据写至Master之后同步到Slave有一个延迟的时间,对于社交应用来说,这是可以接受的,只要保证数据的最终一致性即可。

在上图的最下面有一个Snapshot,即定期对数据进行冷备份,这不同于单纯对MySQL Master进行复制的Slave,因为线上bug或误操作会删除Master上的数据,这时会立即同步到slave上造成数据丢失这时冷备份Snapshot就会起到数据保护作用。

运行过程中肯定需要监控,用户可以利用Linux上的工具进行统计分析top / iotop / df / free / netstat等工具去监控系统里的各个服务和组件是否正常运行,以及通过日志的信息(http access log / application log / database slow log )分析各个服务的性能瓶颈。

数据分区与扩容

下一步业务的调整要进行数据库的分区和扩容。第一,构建缓存集群,在开始的架构中引用了Memcached缓存,是单机数据库缓存。当数据量增长,,需要把数据分散到多台缓存服务器上,常用的是HashRing算法,好处在于不管是添加结点还是删除结点时,只会使得少部分数据失效。还可以引用NoSQL数据库,这里用到了Redis把社交数据里对于关系要求不强但对查询效率要求很高的数据从MySQL里拿到Redis里存。Redis尤其适合存储列表类数据,比如好友关系列表、排行榜数据等。





除此以外可以考虑做数据分区对于MySQL第一步是垂直拆分,把原来单独的数据库按照功能模块分别拆分成:好友新鲜事、用户资料、广告数据以及探索数据。对于Redis也同样,将原来的单台Redis按照功能模块拆成四个,分别为:排行榜数据、好友、广告数据、探索数据。

接下来会遇到的瓶颈是单表过大的问题,这时候我们需要做水平拆分——把一个表拆分成多个表,需要选取一个分区Key,比如对用户表做拆分时,通常选取User ID。分区key的选择主要是看所有的查询语句频繁使用哪个查询字段,就选择那个字段作为分区key这样能保证大部分的查询可以落在单个数据表上,少量没有带分区Key的查询语句,可能要遍历一遍所有切分后的数据表。

构建完整的测试环境

构建完整测试服务器时需要创建新的路由器和私有网络、独立的网络环境和带宽资源、内网GRE隧道打通路由器、VPN拨入网络和SSH密钥管理。





这个过程你可以创建一个包含所有系统服务的all-in-one的环境,将其制作成自有映像。如果后续你的团队来新的人,需要独立的完整开发环境,只需基于自有镜像快速创建主机即可;还可以利用User Data定制化功能,在主机启动执行一段你上传的脚本,来初始化环境。你可以将这两个功能结合起来用,把所有你所需要用的服务全部安装部署完毕后做成映像,并用User Data脚本从代码库里更新代码。因为代码的变动相对于环境的更新更加频繁,不可能每次代码的更新都要构建一个新的自有镜像。通过这种方式构建起一个完整的测试服务器,让每个工程师都可以有自己独立的测试服务器。

在App发布上线时需要连到线上环境怎么办?这两个网络本身完全100%隔离,可利用GRE隧道的功能,把两个路由器打通,实现测试环境网络和线上生产环境网络的完全连通。

多机房部署与混合组网

为了让后端架构更可靠和业务更稳定,就需要实施多机房部署和混合组网。具体原因有以下三点:
异地容灾:在复杂的网络环境下,机房可能会出现网络状况,导致一些比较关键性的业务的可用性降低,备份机房后可保证服务不会出现明显的长时间中断;负载分摊:单独一个机房可能不足以支撑全部的请求,这时可以把一部分的请求压力分担到另一个机房;加速区域访问:在国内网络环境下,南方和北方相互之间网络访问时有较高的延迟。通过做多机房部署实现加速区域用户的访问。






如上所示,有三个机房,中间是QingCloud北京1区机房,负责主营业务。左边是亚太1区机房,主要服务亚太和海外的客户。这两个机房都使用了QingCloud私有网络部署,利用路由器,通过GRE隧道或者IPsec加密隧道的方式进行互通。如果对数据传输过程的安全性要求较高,可以用IPsec的方式把两个机房相互打通,这时的访问只能通过内网IP进行访问。右边是办公室机房,工程师在这个环境下进行开发。

在实现混合组网时,只要机房路由器或者网宽设备支持标准的GRE隧道协议、IP隧道协议,就可以将传统物理世界的机房与路由器连通,并最终打通公有云环境。多机房部署通常见的方案有这些:
异地冷备份

把主机房全套业务在异地重新构建一遍,且不需要提供线上服务,只有在主机房出现故障的时候才切换到备用机房,部署相对要简单一些。但有两方面缺点,一是成本比较高,需要双倍的费用且只是用来做冷备份,平时完全用不上;另外,当主机房突然挂掉时,备用机房再起动起来提供服务,数据需要预热,这是非常缓慢的过程,可能会出现服务响应慢,甚至不能正常提供服务。
异地多活

从易到难有三阶段:第一,反向代理,用户请求到第二个机房,但不做任何处理被转向第一个机房这样会对两地的延时有一定的要求。第二,在第二个机房部署应用服务器和缓存,大部分的数据请求可以从缓存中读取,不用进行跨机房请求,但当缓存失效时,依然落到第一个机房的数据库去查询。所以,这个方式不太彻底;第三,全套服务的部署,包括HTTP服务器、业务服务器、缓存和数据库的 slave。此方式使得进入第二个机房的请求,只需要在机房内就可以完成请求处理,速度更快,但会遇到数据一致性和缓存一致性的问题,针对这点也会有一些解决方法。除了数据同步过程中的不一致问题,还需要面对缓存。

好的系统架构不是设计出来的,而是进化而来的

构建稳定可靠的业务系统需要注意以下这些:
分析用户行为,理解你的业务,如社交、电商、视频;

不同的业务有不同的行业属性和特点,对于社交来讲,比较典型的特点是数据量庞大、数据查询维度多,比如查询6月11日-7月15日在xx咖啡厅我所有好友里拍过照片的人,查询条件包括好友维度、照片维度、地点维度、隐私状态维度等,这时就需要合理的做数据层面的扩展。
电商的特点是定期举办大促销活动,届时会需要大量的计算资源、应用服务器来扛流量峰值,此时可利用云计算平台的弹性实现快速扩展业务,而在自己业务压力、促销来临时调用API接口,及AutoScaling扩展后端计算资源。视频业务有非常明显的流量高峰期和低峰期,流量高峰期通常是白天或者大家晚上下班回家那段时间,晚上2点到早上6点是流量非常低的时候,可利用云计算弹性优势,来调用API方式调整业务带宽资源,从而达到节省成本目的。合理规划系统,预估系统容量,如 10w / 100w / 1000w PV(DAU):不同的系统容量有可能对应不同架构的部署方式,找到最适合自己的那一个;系统是可横向扩展的 scalable;不遗余力地解决单点问题;为出错而设计design for failure:App的后端架构在开发支出就要为可能出现的各种问题进行准备,比如异地备份等;设计面向服务的架构,拆分子系统,API交互,异步处理;构建无处不在的缓存:页面缓存、接口缓存、对象缓存、数据库缓存;避免过度设计,好的系统架构不是设计出来的,而是进化而来的。
 来源:csdn 查看全部
一个社交App需实现的功能

用户关注的常规社交功能、活动、地理位置、探索功能、新鲜事、视频照片分享等等,需要提供的功能不胜枚举,所以从技术角度来说,开发者需要解决的问题也是异常复杂的。

当一款社交App发布之初,用户访问量比较小,使用一台服务器就能够支撑全部的访问压力和数据存储需求,但是互联网应用具有病毒式的传播特点。一款App很可能会面临一夜爆红的现象,访问量和数据量在短时间内呈现爆发式增长,这时候会面临的局面是每天上亿PV、数百万新增用户和活跃用户、流量飙升至每秒数百兆。这些对于一个只部署了简单后端架构的应用来讲是无法支撑的,会直接导致服务器响应缓慢甚至超时,以及在高峰期时服务呈现瘫痪状态,使得后端的服务完全无法使用,用户体验急剧下降。本文将会通过一个真实的案例来分享一个社交应用如何构建一个具备高伸缩性的后端系统。

社交App最初部署的后端架构解析

社交App在最初的时候,后端架构相对比较简单,最初是部署在基础网络之上。最前面放置一台绑定了公网IP的nginx服务器作负载均衡,后面放置3台应用服务器来负责处理所有业务上的请求,最后面搭建一台MySQL Database数据库。

1.jpg

 
构建私有网络

随着产品的不断迭代、用户数的持续增长、数据量的积累,App就需要改进自己的后端架构,即开始构建私有网络。用户可以使用私有网络构建自己的网络拓扑——创建路由器和私有网络,将后续加入的用于运行内部服务的主机放置在私用网络中,可以有效地和云平台其他用户主机,在网络上实现100%二层隔离。主机对外开放的仅仅只有80端口,这样系统安全性上多了一层保障。

2.jpg


在上面的架构图中,最前面的是防火墙,后面接负载均衡器,然后接路由器和私有网络,很多互联网应用都存在读多写少的情况,这个比例有时可以达到8:2,所以我们首先通过引入缓存分摊数据库读压力。其次,引入负载均衡器,替换最初架构中的nginx proxy,负责均衡器在这里其主要用于分发请求到后端多台应用服务器,,当其中一台应用服务器挂掉,负载均衡器可以进行自动隔离。

业务分区与扩展

App随着并发访问量和数据量不断增大,首先想到横向扩容Web服务。水平扩容业务服务器的前提是要保证每台服务器都是无状态的,将session信息下放到缓存或数据库中存储,保证请求被负载到任何一台服务器可以正常处理。

3.jpg


从上图中看到,在前一步「构建私有网络」之后,增加了一个新的私有网络来扩展网络层,这里可以利用自有映像功能,将原有的应用服务器制作成模板,后续就可以基于这个模板快速启动新的主机。另外可以利用Auto-scaling(自动横向扩展)功能,根据后端服务器的负载请求,动态调整服务器的数量。

一个社交应用的后端会提供很多服务请求接口,比如添加好友、刷新新鲜事、浏览页面等,可以通过日志分析每一个接口的耗时,将耗时长但非重要业务的请求分到单独的Web服务器上进行处理,从而给主Web服务器留出更多资源去处理关键业务的请求。

面向服务的架构

随着产品功能的不断迭代,业务代码会越来越复杂,出现故障的可能性也在加大,当一个局部功能出现问题时,都会影响整个服务的可用性。此时可以构建面向服务的架构,将一个完整且庞大的服务拆分为一个个的子服务,服务之间通过接口交互。如下图所示:

4.jpg


社交App的服务被拆分成了四个子服务——新鲜事(News Feed)、用户资料(Profile)、广告(Ads)和探索(Explore),不同的服务之间通过消息通信框架(例如ZeroMQ)来进行交互。把一个大服务拆分为几个小的子服务的好处不言而喻,主要是:
  • 故障隔离:子服务出现故障不会影响全局,比如广告业务出现问题并不会让整个App不能使用,依然可以查看新鲜事等;
  • 独立扩展:每一个被拆分出的子服务有着不同的访问压力,比如新鲜事的调用相比一些二级页面的用户资料要高很多,所以前者会被分配更多的Web 服务器;
  • 独立部署:一个大服务的配置因功能过多会异常复杂,一旦被拆分就可根据不同的特性需求定制配置项,从而提高可管理性;
  • 团队协作开发:开发者都有着自己精通的方向,从而提高开发效率;
  • 抽象出数据访问:在后续进行数据层面(数据库、缓存)扩展时,可通过修改子服务的Data Service,实现对下层数据的透明。


数据库Replication

业务增长也会给数据库带来诸多问题,当最初架构中单台数据库(数据库同时提供读和写)不足已支撑起App访问压力时,首先需要做数据副本Replication。市面上常见的MySQL、MongoDB等数据库都提供Replication功能,以MySQL为例,从高层来看,Replication可分成三步:
  • Master将改变记录到二进制日志(binary log)中(这些记录叫做二进制日志事件,binary log events);
  • Slave将Master的binary log events拷贝到它的中继日志(relay log);
  • Slave重做中继日志中的事件,将改变反映它自己的数据。


具体实现该过程的第一部分就是Master记录二进制日志。在每个事务更新数据完成之前,Master在二进制日志记录这些改变。MySQL将事务串行的写入二进制日志,即使事务中的语句都是交叉执行的。在事件写入二进制日志完成后,Master通知存储引擎提交事务。

下一步就是Slave将Master的binary log拷贝到它自己的中继日志。首先,Slave开始一个工作线程——I/O线程。I/O线程在Master上打开一个普通的连接,然后开始binlog dump process。Binlog dump process从Master的二进制日志中读取事件,如果已经跟上Master,它会睡眠并等待Master产生新的事件。I/O线程将这些事件写入中继日志。

SQL slave thread处理该过程的最后一步。SQL线程从中继日志读取事件,更新Slave的数据,使其与Master中的数据一致。只要该线程与I/O线程保持一致,中继日志通常会位于OS的缓存中,所以中继日志的开销很小。

此外,在Master中也有一个工作线程:和其它MySQL的连接一样,Slave在Master中打开一个连接也会使得Master开始一个线程。复制过程有一个很重要的限制——复制在Slave上是串行化的,也就是说Master上的并行更新操作不能在Slave上并行操作。

对于云计算使用者来说,只需要知道数据库的IP和端口即可进行使用。具体实现见下图:

5.jpg

第一步要做的是扩充Slave,将单机Master变成Master+3台Slave的架构,而在其中的Slave上搭建一个内网的负载均衡器(Load Balancer),对于最上层的Data Service来说,只要配置一个MySQL Master节点和一个LB节点即可,今后因业务变化进行增减Slave对上层来说完全是透明的。

此做法可以带来两个好处,第一是提高可用性,若是一台Master出现错误,则可以提升某一台的Slave作为Master继续提供服务,从而保证数据可用性;第二个是分摊读压力,对于一个社交App来说,读写分离是在数据层优化第一步要做的事情,利用上面的架构可以很轻易地做到将读的请求分担到MySQL Slave上进行查询,而写留给Master。但是读写分离时会有数据库一致性的问题,即在数据写至Master之后同步到Slave有一个延迟的时间,对于社交应用来说,这是可以接受的,只要保证数据的最终一致性即可。

在上图的最下面有一个Snapshot,即定期对数据进行冷备份,这不同于单纯对MySQL Master进行复制的Slave,因为线上bug或误操作会删除Master上的数据,这时会立即同步到slave上造成数据丢失这时冷备份Snapshot就会起到数据保护作用。

运行过程中肯定需要监控,用户可以利用Linux上的工具进行统计分析top / iotop / df / free / netstat等工具去监控系统里的各个服务和组件是否正常运行,以及通过日志的信息(http access log / application log / database slow log )分析各个服务的性能瓶颈。

数据分区与扩容

下一步业务的调整要进行数据库的分区和扩容。第一,构建缓存集群,在开始的架构中引用了Memcached缓存,是单机数据库缓存。当数据量增长,,需要把数据分散到多台缓存服务器上,常用的是HashRing算法,好处在于不管是添加结点还是删除结点时,只会使得少部分数据失效。还可以引用NoSQL数据库,这里用到了Redis把社交数据里对于关系要求不强但对查询效率要求很高的数据从MySQL里拿到Redis里存。Redis尤其适合存储列表类数据,比如好友关系列表、排行榜数据等。

6.jpg

除此以外可以考虑做数据分区对于MySQL第一步是垂直拆分,把原来单独的数据库按照功能模块分别拆分成:好友新鲜事、用户资料、广告数据以及探索数据。对于Redis也同样,将原来的单台Redis按照功能模块拆成四个,分别为:排行榜数据、好友、广告数据、探索数据。

接下来会遇到的瓶颈是单表过大的问题,这时候我们需要做水平拆分——把一个表拆分成多个表,需要选取一个分区Key,比如对用户表做拆分时,通常选取User ID。分区key的选择主要是看所有的查询语句频繁使用哪个查询字段,就选择那个字段作为分区key这样能保证大部分的查询可以落在单个数据表上,少量没有带分区Key的查询语句,可能要遍历一遍所有切分后的数据表。

构建完整的测试环境

构建完整测试服务器时需要创建新的路由器和私有网络、独立的网络环境和带宽资源、内网GRE隧道打通路由器、VPN拨入网络和SSH密钥管理。

8.jpg

这个过程你可以创建一个包含所有系统服务的all-in-one的环境,将其制作成自有映像。如果后续你的团队来新的人,需要独立的完整开发环境,只需基于自有镜像快速创建主机即可;还可以利用User Data定制化功能,在主机启动执行一段你上传的脚本,来初始化环境。你可以将这两个功能结合起来用,把所有你所需要用的服务全部安装部署完毕后做成映像,并用User Data脚本从代码库里更新代码。因为代码的变动相对于环境的更新更加频繁,不可能每次代码的更新都要构建一个新的自有镜像。通过这种方式构建起一个完整的测试服务器,让每个工程师都可以有自己独立的测试服务器。

在App发布上线时需要连到线上环境怎么办?这两个网络本身完全100%隔离,可利用GRE隧道的功能,把两个路由器打通,实现测试环境网络和线上生产环境网络的完全连通。

多机房部署与混合组网

为了让后端架构更可靠和业务更稳定,就需要实施多机房部署和混合组网。具体原因有以下三点:
  • 异地容灾:在复杂的网络环境下,机房可能会出现网络状况,导致一些比较关键性的业务的可用性降低,备份机房后可保证服务不会出现明显的长时间中断;
  • 负载分摊:单独一个机房可能不足以支撑全部的请求,这时可以把一部分的请求压力分担到另一个机房;
  • 加速区域访问:在国内网络环境下,南方和北方相互之间网络访问时有较高的延迟。通过做多机房部署实现加速区域用户的访问。


9.jpg


如上所示,有三个机房,中间是QingCloud北京1区机房,负责主营业务。左边是亚太1区机房,主要服务亚太和海外的客户。这两个机房都使用了QingCloud私有网络部署,利用路由器,通过GRE隧道或者IPsec加密隧道的方式进行互通。如果对数据传输过程的安全性要求较高,可以用IPsec的方式把两个机房相互打通,这时的访问只能通过内网IP进行访问。右边是办公室机房,工程师在这个环境下进行开发。

在实现混合组网时,只要机房路由器或者网宽设备支持标准的GRE隧道协议、IP隧道协议,就可以将传统物理世界的机房与路由器连通,并最终打通公有云环境。多机房部署通常见的方案有这些:
  • 异地冷备份


把主机房全套业务在异地重新构建一遍,且不需要提供线上服务,只有在主机房出现故障的时候才切换到备用机房,部署相对要简单一些。但有两方面缺点,一是成本比较高,需要双倍的费用且只是用来做冷备份,平时完全用不上;另外,当主机房突然挂掉时,备用机房再起动起来提供服务,数据需要预热,这是非常缓慢的过程,可能会出现服务响应慢,甚至不能正常提供服务。
  • 异地多活


从易到难有三阶段:第一,反向代理,用户请求到第二个机房,但不做任何处理被转向第一个机房这样会对两地的延时有一定的要求。第二,在第二个机房部署应用服务器和缓存,大部分的数据请求可以从缓存中读取,不用进行跨机房请求,但当缓存失效时,依然落到第一个机房的数据库去查询。所以,这个方式不太彻底;第三,全套服务的部署,包括HTTP服务器、业务服务器、缓存和数据库的 slave。此方式使得进入第二个机房的请求,只需要在机房内就可以完成请求处理,速度更快,但会遇到数据一致性和缓存一致性的问题,针对这点也会有一些解决方法。除了数据同步过程中的不一致问题,还需要面对缓存。

好的系统架构不是设计出来的,而是进化而来的

构建稳定可靠的业务系统需要注意以下这些:
  • 分析用户行为,理解你的业务,如社交、电商、视频;


不同的业务有不同的行业属性和特点,对于社交来讲,比较典型的特点是数据量庞大、数据查询维度多,比如查询6月11日-7月15日在xx咖啡厅我所有好友里拍过照片的人,查询条件包括好友维度、照片维度、地点维度、隐私状态维度等,这时就需要合理的做数据层面的扩展。
  • 电商的特点是定期举办大促销活动,届时会需要大量的计算资源、应用服务器来扛流量峰值,此时可利用云计算平台的弹性实现快速扩展业务,而在自己业务压力、促销来临时调用API接口,及AutoScaling扩展后端计算资源。视频业务有非常明显的流量高峰期和低峰期,流量高峰期通常是白天或者大家晚上下班回家那段时间,晚上2点到早上6点是流量非常低的时候,可利用云计算弹性优势,来调用API方式调整业务带宽资源,从而达到节省成本目的。
  • 合理规划系统,预估系统容量,如 10w / 100w / 1000w PV(DAU):不同的系统容量有可能对应不同架构的部署方式,找到最适合自己的那一个;
  • 系统是可横向扩展的 scalable;
  • 不遗余力地解决单点问题;
  • 为出错而设计design for failure:App的后端架构在开发支出就要为可能出现的各种问题进行准备,比如异地备份等;
  • 设计面向服务的架构,拆分子系统,API交互,异步处理;
  • 构建无处不在的缓存:页面缓存、接口缓存、对象缓存、数据库缓存;
  • 避免过度设计,好的系统架构不是设计出来的,而是进化而来的。

 来源:csdn
0
评论

Android M Developer Preview 2 发布 Android 移动开发

oscar 发表了文章 • 1188 次浏览 • 2015-07-10 14:49 • 来自相关话题

Google 更新 Android M 开发者预览版,相比 Lollipop 主要是安全和电池寿命方面的改进。此版本包括更多的授权设置改进,比如指纹验证,外部存储处理的授权方式改进。

Google 强烈建议大家升级到最新版本,最新版本包括最新的平台 APIs:更新了 Bluetooth Stylus APIs,为 Media API 添加了新的调用,一些类的重构等等。

此外还有一系列的 bug 修复。Google 温馨提示: Messenger 应用还不能很好的在 64 位模拟器上运行,还有些 YouTube 视频分享方面的问题,联系人同步方面的问题,Android M 在 Nexus Player 上的问题等等。
 
原文地址:http://www.oschina.net/news/64 ... pdate 查看全部
Google 更新 Android M 开发者预览版,相比 Lollipop 主要是安全和电池寿命方面的改进。此版本包括更多的授权设置改进,比如指纹验证,外部存储处理的授权方式改进。

Google 强烈建议大家升级到最新版本,最新版本包括最新的平台 APIs:更新了 Bluetooth Stylus APIs,为 Media API 添加了新的调用,一些类的重构等等。

此外还有一系列的 bug 修复。Google 温馨提示: Messenger 应用还不能很好的在 64 位模拟器上运行,还有些 YouTube 视频分享方面的问题,联系人同步方面的问题,Android M 在 Nexus Player 上的问题等等。
 
原文地址:http://www.oschina.net/news/64 ... pdate
0
评论

Go语言对Android原生应用开发的支持情况 Android Go 移动开发

oscar 发表了文章 • 1446 次浏览 • 2015-07-08 16:43 • 来自相关话题

Google工程师和独立开发人员提出了几份不同的提案,旨在让Go语言支持开发原生的Android应用。这项工作无法让Go语言编写的应用使用Android NDK的全部接口,但有可能使用其中的一个子集。
David Crawshaw是Google的工程师,他写了一份提案,旨在让Go语言部分支持编写Android应用。根据他的说法,“用Go语言来实现整个Android平台非常困难。Android平台是用Java写的,并拥有庞大的API层。”
但是,Crawshaw说,一部分Android应用——比如游戏——使用了精简得多的C语言API编写代码,这些API由Android NDK提供。这样,使用Go语言来开发和NDK一样的功能,提供对Android的支持是有可能实现的。
Crawshaw建议在Go 1.4的开发周期中,Go语言的代码库引入一个叫GOOS=android的选项,这个选项可以提供以下功能:
为Android NDK中导出的OpenGL、OpenSL和OpenMAX接口,提供Go语言的绑定(binding)。从Java语言到Go语言的绑定生成器(binding generator)。如果我们有一个Go语言编写的软件包,那么这个生成器可以帮助Java代码调用它,所以游戏菜单界面就可以直接使用标准的SDK来编写了。集成到Android Studio的编译系统中。
不止Crawshaw一个人提出了把Go语言和Android结合起来的想法。Elias Naur建议扩展Go语言的工具链来支持创建动态库。这样我们就可以在Android应用中使用Go语言编写的库,它们被Android应用加载和运行,并打包在apk中发行。要把这个想法变为现实,有一个重要的前提条件:加入对交叉编译的支持,而Go 1.3已经实现了它。交叉编译是必需的,因为NDK本身并不能在Android上运行,只有使用NDK编译和(或)链接的可执行程序和动态库才能在Android设备上运行。
上面这个提案基于已有的开源项目goandroid,作者就是Elias Naur。Goandroid修改了Go语言的工具链和运行时库,使之能编写动态库,在原生的Android应用中运行,而Google官方并不支持这个功能。
最后,还有一个叫Mandala的项目,它是一个更全面的框架,它的目标是使Go语言能编写Android原生应用。Mandala利用了Goandroid的工具链,它的作者Andrea Fazzi说,感谢Goandroid,“你可以在桌面环境中开发、测试和运行你的应用,然后再把它部署到Android设备上。它鼓励大家以Go语言独特的方式来编写Android应用:使用通道(channels)来实现通讯,而不是回调函数(callbacks)”
在功能方面,Mandala项目跟Crawshaw的提案很接近,它的目标也主要是为游戏提供解决方案:“我们不应该把Mandala框架看作是一个上层的游戏引擎,而是应该在它基础之上构建游戏引擎,或者把已有的游戏引擎移植到它上面。” Fazzi 提醒道,Google并不支持用Go语言来开发原生的Android应用,但他也表达了他的期望“当前这些工作可以起到某种激励作用,促使Go语言开发团队从官方层面支持Android。”
来源:infoq
参考原文链接:The State of Go Language for Android Native Development 查看全部
Google工程师和独立开发人员提出了几份不同的提案,旨在让Go语言支持开发原生的Android应用。这项工作无法让Go语言编写的应用使用Android NDK的全部接口,但有可能使用其中的一个子集。
David Crawshaw是Google的工程师,他写了一份提案,旨在让Go语言部分支持编写Android应用。根据他的说法,“用Go语言来实现整个Android平台非常困难。Android平台是用Java写的,并拥有庞大的API层。”
但是,Crawshaw说,一部分Android应用——比如游戏——使用了精简得多的C语言API编写代码,这些API由Android NDK提供。这样,使用Go语言来开发和NDK一样的功能,提供对Android的支持是有可能实现的。
Crawshaw建议在Go 1.4的开发周期中,Go语言的代码库引入一个叫GOOS=android的选项,这个选项可以提供以下功能:
  • 为Android NDK中导出的OpenGL、OpenSL和OpenMAX接口,提供Go语言的绑定(binding)。
  • 从Java语言到Go语言的绑定生成器(binding generator)。如果我们有一个Go语言编写的软件包,那么这个生成器可以帮助Java代码调用它,所以游戏菜单界面就可以直接使用标准的SDK来编写了。
  • 集成到Android Studio的编译系统中。

不止Crawshaw一个人提出了把Go语言和Android结合起来的想法。Elias Naur建议扩展Go语言的工具链来支持创建动态库。这样我们就可以在Android应用中使用Go语言编写的库,它们被Android应用加载和运行,并打包在apk中发行。要把这个想法变为现实,有一个重要的前提条件:加入对交叉编译的支持,而Go 1.3已经实现了它。交叉编译是必需的,因为NDK本身并不能在Android上运行,只有使用NDK编译和(或)链接的可执行程序和动态库才能在Android设备上运行。
上面这个提案基于已有的开源项目goandroid,作者就是Elias Naur。Goandroid修改了Go语言的工具链和运行时库,使之能编写动态库,在原生的Android应用中运行,而Google官方并不支持这个功能。
最后,还有一个叫Mandala的项目,它是一个更全面的框架,它的目标是使Go语言能编写Android原生应用。Mandala利用了Goandroid的工具链,它的作者Andrea Fazzi说,感谢Goandroid,“你可以在桌面环境中开发、测试和运行你的应用,然后再把它部署到Android设备上。它鼓励大家以Go语言独特的方式来编写Android应用:使用通道(channels)来实现通讯,而不是回调函数(callbacks)”
在功能方面,Mandala项目跟Crawshaw的提案很接近,它的目标也主要是为游戏提供解决方案:“我们不应该把Mandala框架看作是一个上层的游戏引擎,而是应该在它基础之上构建游戏引擎,或者把已有的游戏引擎移植到它上面。” Fazzi 提醒道,Google并不支持用Go语言来开发原生的Android应用,但他也表达了他的期望“当前这些工作可以起到某种激励作用,促使Go语言开发团队从官方层面支持Android。”
来源:infoq
参考原文链接:The State of Go Language for Android Native Development
0
评论

干货:Nginx/LVS/HAProxy 负载均衡软件的优缺点详解 移动开发

oscar 发表了文章 • 3588 次浏览 • 2015-07-08 10:56 • 来自相关话题

Nginx/LVS/HAProxy是目前使用最广泛的三种负载均衡软件,一般对负载均衡的使用是随着网站规模的提升根据不同的阶段来使用不同的技术,具体的应用需求还得具体分析。
如果是中小型的Web应用,比如日PV小于1000万,用Nginx就完全可以了;如果机器不少,可以用DNS轮询,LVS所耗费的机器还是比较多的;大型网站或重要的服务,且服务器比较多时,可以考虑用LVS。
目前关于网站架构一般比较合理流行的架构方案:Web前端采用Nginx/HAProxy+Keepalived作负载均衡器;后端采用MySQL数据库一主多从和读写分离,采用LVS+Keepalived的架构。当然要根据项目具体需求制定方案,下面说说各自的特点和适用场合。
Nginx
Nginx的优点:
工作在网络的7层之上,可以针对http应用做一些分流的策略,比如针对域名、目录结构,它的正则规则比HAProxy更为强大和灵活,这也是它目前广泛流行的主要原因之一,Nginx单凭这点可利用的场合就远多于LVS了。Nginx对网络稳定性的依赖非常小,理论上能ping通就就能进行负载功能,这个也是它的优势之一;相反LVS对网络稳定性依赖比较大,这点用过Nginx的人都深有体会;Nginx安装和配置比较简单,测试起来比较方便,它基本能把错误用日志打印出来。LVS的配置、测试就要花比较长的时间了,LVS对网络依赖比较大。可以承担高负载压力且稳定,在硬件不差的情况下一般能支撑几万次的并发量,负载度比LVS相对小些。Nginx可以通过端口检测到服务器内部的故障,比如根据服务器处理网页返回的状态码、超时等等,并且会把返回错误的请求重新提交到另一个节点,不过其中缺点就是不支持url来检测。比如用户正在上传一个文件,而处理该上传的节点刚好在上传过程中出现故障,Nginx会把上传切到另一台服务器重新处理,而LVS就直接断掉了,如果是上传一个很大的文件或者很重要的文件的话,用户可能会因此而不满。Nginx不仅仅是一款优秀的负载均衡器/反向代理软件,它同时也是功能强大的Web应用服务器。LNMP也是近几年非常流行的web架构,在高流量的环境中稳定性也很好。Nginx现在作为Web反向加速缓存越来越成熟了,速度比传统的Squid服务器更快,可以考虑用其作为反向代理加速器。Nginx可作为中层反向代理使用,这一层面Nginx基本上无对手,唯一可以对比Nginx的就只有lighttpd了,不过lighttpd目前还没有做到Nginx完全的功能,配置也不那么清晰易读,社区资料也远远没Nginx活跃。Nginx也可作为静态网页和图片服务器,这方面的性能也无对手。还有Nginx社区非常活跃,第三方模块也很多。
Nginx的缺点:
Nginx仅能支持http、https和Email协议,这样就在适用范围上面小些,这个是它的缺点。对后端服务器的健康检查,只支持通过端口来检测,不支持通过url来检测。不支持Session的直接保持,但能通过ip_hash来解决。
LVS
LVS是使用Linux内核集群实现的一个高性能、高可用的负载均衡服务器,它具有很好的可伸缩性(Scalability)、可靠性(Reliability)和可管理性(Manageability)。
LVS的优点:
抗负载能力强,工作在网络4层之上,仅作分发之用,没有流量的产生,这个特点也决定了它在负载均衡软件里的性能最强的,对内存和cpu资源消耗比较低。配置性比较低,这是一个缺点也是一个优点,因为没有可太多配置的东西,所以并不需要太多接触,大大减少了人为出错的几率。工作稳定,因为其本身抗负载能力很强,自身有完整的双机热备方案,如LVS+Keepalived,不过我们在项目实施中用得最多的还是LVS/DR+Keepalived。无流量,LVS只分发请求,而流量并不从它本身出去,这点保证了均衡器IO的性能不会收到大流量的影响。应用范围比较广,因为LVS工作在4层,所以它几乎可以对所有应用做负载均衡,包括http、数据库、在线聊天室等等。
LVS的缺点:
软件本身不支持正则表达式处理,不能做动静分离;而现在许多网站在这方面都有较强的需求,这个是Nginx/HAProxy+Keepalived的优势所在。如果是网站应用比较庞大的话,LVS/DR+Keepalived实施起来就比较复杂了,特别后面有Windows Server的机器的话,如果实施及配置还有维护过程就比较复杂了,相对而言,Nginx/HAProxy+Keepalived就简单多了。
HAProxy
HAProxy的特点:
HAProxy也是支持虚拟主机的。HAProxy的优点能够补充Nginx的一些缺点,比如支持Session的保持,Cookie的引导;同时支持通过获取指定的url来检测后端服务器的状态。HAProxy跟LVS类似,本身就只是一款负载均衡软件;单纯从效率上来讲HAProxy会比Nginx有更出色的负载均衡速度,在并发处理上也是优于Nginx的。HAProxy支持TCP协议的负载均衡转发,可以对MySQL读进行负载均衡,对后端的MySQL节点进行检测和负载均衡,大家可以用LVS+Keepalived对MySQL主从做负载均衡。5、HAProxy负载均衡策略非常多,HAProxy的负载均衡算法现在具体有如下8种:
roundrobin:表示简单的轮询,这个不多说,这个是负载均衡基本都具备的;
static-rr:表示根据权重,建议关注;
leastconn:表示最少连接者先处理,建议关注;
source:表示根据请求源IP,这个跟Nginx的IP_hash机制类似,我们用其作为解决session问题的一种方法,建议关注;
ri:表示根据请求的URI;
rl_param:表示根据请求的URl参数’balance url_param’ requires an URL parameter name;
hdr(name):表示根据HTTP请求头来锁定每一次HTTP请求;
rdp-cookie(name):表示根据据cookie(name)来锁定并哈希每一次TCP请求。
Nginx和LVS对比总结:
Nginx工作在网络的7层,所以它可以针对http应用本身来做分流策略,比如针对域名、目录结构等,相比之下LVS并不具备这样的功能,所以Nginx单凭这点可利用的场合就远多于LVS了;但Nginx有用的这些功能使其可调整度要高于LVS,所以经常要去触碰触碰,触碰多了,人为出问题的几率也就会大。
Nginx对网络稳定性的依赖较小,理论上只要ping得通,网页访问正常,Nginx就能连得通,这是Nginx的一大优势!Nginx同时还能区分内外网,如果是同时拥有内外网的节点,就相当于单机拥有了备份线路;LVS就比较依赖于网络环境,目前来看服务器在同一网段内并且LVS使用direct方式分流,效果较能得到保证。
另外注意,LVS需要向托管商至少申请多一个ip来做Visual IP,貌似是不能用本身的IP来做VIP的。要做好LVS管理员,确实得跟进学习很多有关网络通信方面的知识,就不再是一个HTTP那么简单了。
Nginx安装和配置比较简单,测试起来也很方便,因为它基本能把错误用日志打印出来。LVS的安装和配置、测试就要花比较长的时间了;LVS对网络依赖比较大,很多时候不能配置成功都是因为网络问题而不是配置问题,出了问题要解决也相应的会麻烦得多。
Nginx也同样能承受很高负载且稳定,但负载度和稳定度差LVS还有几个等级:Nginx处理所有流量所以受限于机器IO和配置;本身的bug也还是难以避免的。
Nginx可以检测到服务器内部的故障,比如根据服务器处理网页返回的状态码、超时等等,并且会把返回错误的请求重新提交到另一个节点。目前LVS中 ldirectd也能支持针对服务器内部的情况来监控,但LVS的原理使其不能重发请求。
比如用户正在上传一个文件,而处理该上传的节点刚好在上传过程中出现故障,Nginx会把上传切到另一台服务器重新处理,而LVS就直接断掉了,如果是上传一个很大的文件或者很重要的文件的话,用户可能会因此而恼火。
Nginx对请求的异步处理可以帮助节点服务器减轻负载,假如使用apache直接对外服务,那么出现很多的窄带链接时apache服务器将会占用大 量内存而不能释放,使用多一个Nginx做apache代理的话,这些窄带链接会被Nginx挡住,apache上就不会堆积过多的请求,这样就减少了相当多的资源占用。这点使用squid也有相同的作用,即使squid本身配置为不缓存,对apache还是有很大帮助的。
Nginx能支持http、https和email(email的功能比较少用),LVS所支持的应用在这点上会比Nginx更多。在使用上,一般最前端所采取的策略应是LVS,也就是DNS的指向应为LVS均衡器,LVS的优点令它非常适合做这个任务。
重要的ip地址,最好交由LVS托管,比如数据库的 ip、webservice服务器的ip等等,这些ip地址随着时间推移,使用面会越来越大,如果更换ip则故障会接踵而至。所以将这些重要ip交给 LVS托管是最为稳妥的,这样做的唯一缺点是需要的VIP数量会比较多。
Nginx可作为LVS节点机器使用,一是可以利用Nginx的功能,二是可以利用Nginx的性能。当然这一层面也可以直接使用squid,squid的功能方面就比Nginx弱不少了,性能上也有所逊色于Nginx。Nginx也可作为中层代理使用,这一层面Nginx基本上无对手,唯一可以撼动Nginx的就只有lighttpd了,不过lighttpd目前还没有能做到 Nginx完全的功能,配置也不那么清晰易读。
另外,中层代理的IP也是重要的,所以中层代理也拥有一个VIP和LVS是最完美的方案了。具体的应用还得具体分析,如果是比较小的网站(日PV小于1000万),用Nginx就完全可以了,如果机器也不少,可以用DNS轮询,LVS所耗费的机器还是比较多的;大型网站或者重要的服务,机器不发愁的时候,要多多考虑利用LVS。
现在对网络负载均衡的使用是随着网站规模的提升根据不同的阶段来使用不同的技术:
第一阶段:利用Nginx或HAProxy进行单点的负载均衡,这一阶段服务器规模刚脱离开单服务器、单数据库的模式,需要一定的负载均衡,但是仍然规模较小没有专业的维护团队来进行维护,也没有需要进行大规模的网站部署。这样利用Nginx或HAproxy就是第一选择,此时这些东西上手快, 配置容易,在七层之上利用HTTP协议就可以。这时是第一选择。第二阶段:随着网络服务进一步扩大,这时单点的Nginx已经不能满足,这时使用LVS或者商用Array就是首要选择,Nginx此时就作为LVS或者Array的节点来使用,具体LVS或Array的是选择是根据公司规模和预算来选择,Array的应用交付功能非常强大,本人在某项目中使用过,性价比也远高于F5,商用首选!但是一般来说这阶段相关人才跟不上业务的提升,所以购买商业负载均衡已经成为了必经之路。关人才的能力以及数量也随之提升,这时无论从开发适合自身产品的定制,以及降低成本来讲开源的LVS,已经成为首选,这时LVS会成为主流。第三阶段:这时网络服务已经成为主流产品,此时随着公司知名度也进一步扩展,相关人才的能力以及数量也随之提升,这时无论从开发适合自身产品的定制,以及降低成本来讲开源的LVS,已经成为首选,这时LVS会成为主流。最终形成比较理想的基本架构为:Array/LVS — Nginx/Haproxy — Squid/Varnish — AppServer。
 来源:linux中国 查看全部
Nginx/LVS/HAProxy是目前使用最广泛的三种负载均衡软件,一般对负载均衡的使用是随着网站规模的提升根据不同的阶段来使用不同的技术,具体的应用需求还得具体分析。
如果是中小型的Web应用,比如日PV小于1000万,用Nginx就完全可以了;如果机器不少,可以用DNS轮询,LVS所耗费的机器还是比较多的;大型网站或重要的服务,且服务器比较多时,可以考虑用LVS。
目前关于网站架构一般比较合理流行的架构方案:Web前端采用Nginx/HAProxy+Keepalived作负载均衡器;后端采用MySQL数据库一主多从和读写分离,采用LVS+Keepalived的架构。当然要根据项目具体需求制定方案,下面说说各自的特点和适用场合。
Nginx
Nginx的优点:
  • 工作在网络的7层之上,可以针对http应用做一些分流的策略,比如针对域名、目录结构,它的正则规则比HAProxy更为强大和灵活,这也是它目前广泛流行的主要原因之一,Nginx单凭这点可利用的场合就远多于LVS了。
  • Nginx对网络稳定性的依赖非常小,理论上能ping通就就能进行负载功能,这个也是它的优势之一;相反LVS对网络稳定性依赖比较大,这点用过Nginx的人都深有体会;
  • Nginx安装和配置比较简单,测试起来比较方便,它基本能把错误用日志打印出来。LVS的配置、测试就要花比较长的时间了,LVS对网络依赖比较大。
  • 可以承担高负载压力且稳定,在硬件不差的情况下一般能支撑几万次的并发量,负载度比LVS相对小些。
  • Nginx可以通过端口检测到服务器内部的故障,比如根据服务器处理网页返回的状态码、超时等等,并且会把返回错误的请求重新提交到另一个节点,不过其中缺点就是不支持url来检测。比如用户正在上传一个文件,而处理该上传的节点刚好在上传过程中出现故障,Nginx会把上传切到另一台服务器重新处理,而LVS就直接断掉了,如果是上传一个很大的文件或者很重要的文件的话,用户可能会因此而不满。
  • Nginx不仅仅是一款优秀的负载均衡器/反向代理软件,它同时也是功能强大的Web应用服务器。LNMP也是近几年非常流行的web架构,在高流量的环境中稳定性也很好。
  • Nginx现在作为Web反向加速缓存越来越成熟了,速度比传统的Squid服务器更快,可以考虑用其作为反向代理加速器。
  • Nginx可作为中层反向代理使用,这一层面Nginx基本上无对手,唯一可以对比Nginx的就只有lighttpd了,不过lighttpd目前还没有做到Nginx完全的功能,配置也不那么清晰易读,社区资料也远远没Nginx活跃。
  • Nginx也可作为静态网页和图片服务器,这方面的性能也无对手。还有Nginx社区非常活跃,第三方模块也很多。

Nginx的缺点:
  • Nginx仅能支持http、https和Email协议,这样就在适用范围上面小些,这个是它的缺点。
  • 对后端服务器的健康检查,只支持通过端口来检测,不支持通过url来检测。不支持Session的直接保持,但能通过ip_hash来解决。

LVS
LVS是使用Linux内核集群实现的一个高性能、高可用的负载均衡服务器,它具有很好的可伸缩性(Scalability)、可靠性(Reliability)和可管理性(Manageability)。
LVS的优点:
  • 抗负载能力强,工作在网络4层之上,仅作分发之用,没有流量的产生,这个特点也决定了它在负载均衡软件里的性能最强的,对内存和cpu资源消耗比较低。
  • 配置性比较低,这是一个缺点也是一个优点,因为没有可太多配置的东西,所以并不需要太多接触,大大减少了人为出错的几率。
  • 工作稳定,因为其本身抗负载能力很强,自身有完整的双机热备方案,如LVS+Keepalived,不过我们在项目实施中用得最多的还是LVS/DR+Keepalived。
  • 无流量,LVS只分发请求,而流量并不从它本身出去,这点保证了均衡器IO的性能不会收到大流量的影响。
  • 应用范围比较广,因为LVS工作在4层,所以它几乎可以对所有应用做负载均衡,包括http、数据库、在线聊天室等等。

LVS的缺点:
  • 软件本身不支持正则表达式处理,不能做动静分离;而现在许多网站在这方面都有较强的需求,这个是Nginx/HAProxy+Keepalived的优势所在。
  • 如果是网站应用比较庞大的话,LVS/DR+Keepalived实施起来就比较复杂了,特别后面有Windows Server的机器的话,如果实施及配置还有维护过程就比较复杂了,相对而言,Nginx/HAProxy+Keepalived就简单多了。

HAProxy
HAProxy的特点:
  • HAProxy也是支持虚拟主机的。
  • HAProxy的优点能够补充Nginx的一些缺点,比如支持Session的保持,Cookie的引导;同时支持通过获取指定的url来检测后端服务器的状态。
  • HAProxy跟LVS类似,本身就只是一款负载均衡软件;单纯从效率上来讲HAProxy会比Nginx有更出色的负载均衡速度,在并发处理上也是优于Nginx的。
  • HAProxy支持TCP协议的负载均衡转发,可以对MySQL读进行负载均衡,对后端的MySQL节点进行检测和负载均衡,大家可以用LVS+Keepalived对MySQL主从做负载均衡。
  • 5、HAProxy负载均衡策略非常多,HAProxy的负载均衡算法现在具体有如下8种:

roundrobin:表示简单的轮询,这个不多说,这个是负载均衡基本都具备的;
static-rr:表示根据权重,建议关注;
leastconn:表示最少连接者先处理,建议关注;
source:表示根据请求源IP,这个跟Nginx的IP_hash机制类似,我们用其作为解决session问题的一种方法,建议关注;
ri:表示根据请求的URI;
rl_param:表示根据请求的URl参数’balance url_param’ requires an URL parameter name;
hdr(name):表示根据HTTP请求头来锁定每一次HTTP请求;
rdp-cookie(name):表示根据据cookie(name)来锁定并哈希每一次TCP请求。
Nginx和LVS对比总结:
Nginx工作在网络的7层,所以它可以针对http应用本身来做分流策略,比如针对域名、目录结构等,相比之下LVS并不具备这样的功能,所以Nginx单凭这点可利用的场合就远多于LVS了;但Nginx有用的这些功能使其可调整度要高于LVS,所以经常要去触碰触碰,触碰多了,人为出问题的几率也就会大。
Nginx对网络稳定性的依赖较小,理论上只要ping得通,网页访问正常,Nginx就能连得通,这是Nginx的一大优势!Nginx同时还能区分内外网,如果是同时拥有内外网的节点,就相当于单机拥有了备份线路;LVS就比较依赖于网络环境,目前来看服务器在同一网段内并且LVS使用direct方式分流,效果较能得到保证。
另外注意,LVS需要向托管商至少申请多一个ip来做Visual IP,貌似是不能用本身的IP来做VIP的。要做好LVS管理员,确实得跟进学习很多有关网络通信方面的知识,就不再是一个HTTP那么简单了。
Nginx安装和配置比较简单,测试起来也很方便,因为它基本能把错误用日志打印出来。LVS的安装和配置、测试就要花比较长的时间了;LVS对网络依赖比较大,很多时候不能配置成功都是因为网络问题而不是配置问题,出了问题要解决也相应的会麻烦得多。
Nginx也同样能承受很高负载且稳定,但负载度和稳定度差LVS还有几个等级:Nginx处理所有流量所以受限于机器IO和配置;本身的bug也还是难以避免的。
Nginx可以检测到服务器内部的故障,比如根据服务器处理网页返回的状态码、超时等等,并且会把返回错误的请求重新提交到另一个节点。目前LVS中 ldirectd也能支持针对服务器内部的情况来监控,但LVS的原理使其不能重发请求。
比如用户正在上传一个文件,而处理该上传的节点刚好在上传过程中出现故障,Nginx会把上传切到另一台服务器重新处理,而LVS就直接断掉了,如果是上传一个很大的文件或者很重要的文件的话,用户可能会因此而恼火。
Nginx对请求的异步处理可以帮助节点服务器减轻负载,假如使用apache直接对外服务,那么出现很多的窄带链接时apache服务器将会占用大 量内存而不能释放,使用多一个Nginx做apache代理的话,这些窄带链接会被Nginx挡住,apache上就不会堆积过多的请求,这样就减少了相当多的资源占用。这点使用squid也有相同的作用,即使squid本身配置为不缓存,对apache还是有很大帮助的。
Nginx能支持http、https和email(email的功能比较少用),LVS所支持的应用在这点上会比Nginx更多。在使用上,一般最前端所采取的策略应是LVS,也就是DNS的指向应为LVS均衡器,LVS的优点令它非常适合做这个任务。
重要的ip地址,最好交由LVS托管,比如数据库的 ip、webservice服务器的ip等等,这些ip地址随着时间推移,使用面会越来越大,如果更换ip则故障会接踵而至。所以将这些重要ip交给 LVS托管是最为稳妥的,这样做的唯一缺点是需要的VIP数量会比较多。
Nginx可作为LVS节点机器使用,一是可以利用Nginx的功能,二是可以利用Nginx的性能。当然这一层面也可以直接使用squid,squid的功能方面就比Nginx弱不少了,性能上也有所逊色于Nginx。Nginx也可作为中层代理使用,这一层面Nginx基本上无对手,唯一可以撼动Nginx的就只有lighttpd了,不过lighttpd目前还没有能做到 Nginx完全的功能,配置也不那么清晰易读。
另外,中层代理的IP也是重要的,所以中层代理也拥有一个VIP和LVS是最完美的方案了。具体的应用还得具体分析,如果是比较小的网站(日PV小于1000万),用Nginx就完全可以了,如果机器也不少,可以用DNS轮询,LVS所耗费的机器还是比较多的;大型网站或者重要的服务,机器不发愁的时候,要多多考虑利用LVS。
现在对网络负载均衡的使用是随着网站规模的提升根据不同的阶段来使用不同的技术:
  • 第一阶段:利用Nginx或HAProxy进行单点的负载均衡,这一阶段服务器规模刚脱离开单服务器、单数据库的模式,需要一定的负载均衡,但是仍然规模较小没有专业的维护团队来进行维护,也没有需要进行大规模的网站部署。这样利用Nginx或HAproxy就是第一选择,此时这些东西上手快, 配置容易,在七层之上利用HTTP协议就可以。这时是第一选择。
  • 第二阶段:随着网络服务进一步扩大,这时单点的Nginx已经不能满足,这时使用LVS或者商用Array就是首要选择,Nginx此时就作为LVS或者Array的节点来使用,具体LVS或Array的是选择是根据公司规模和预算来选择,Array的应用交付功能非常强大,本人在某项目中使用过,性价比也远高于F5,商用首选!但是一般来说这阶段相关人才跟不上业务的提升,所以购买商业负载均衡已经成为了必经之路。关人才的能力以及数量也随之提升,这时无论从开发适合自身产品的定制,以及降低成本来讲开源的LVS,已经成为首选,这时LVS会成为主流。
  • 第三阶段:这时网络服务已经成为主流产品,此时随着公司知名度也进一步扩展,相关人才的能力以及数量也随之提升,这时无论从开发适合自身产品的定制,以及降低成本来讲开源的LVS,已经成为首选,这时LVS会成为主流。最终形成比较理想的基本架构为:Array/LVS — Nginx/Haproxy — Squid/Varnish — AppServer。

 来源:linux中国
0
评论

移动5年 Android生态系统的演进 移动开发

oscar 发表了文章 • 984 次浏览 • 2015-07-07 15:15 • 来自相关话题

由Google、HTC、Qualcomm联手打造的第一部Android手机G1,开启了移动时代的Andr​​oid纪元(如图1所示),直到现在Android也是唯一能在移动市场上与iOS相抗衡的平台。简单地说,Android与iOS占尽了移动时代的先机(这个故事要从2007年的iPhone和2008年的Andr​​oid G1开始说起,甚至是更早之前的开发史及并购史),App开发者已在Android及iOS上扎下了深厚的根基,因此再也无力也没有必要去为第三个平台开发或移植自己的App,原因很简单,因为受众太少,支出与收入不成正比。






一开始Android生态系统很简单,就是拉拢App开发者,并且寻求与更多芯片制造商及手机厂商的合作,共同推广Android这个开放平台。但随着Android市场占有率逐步攀升,Google开始一步步地收紧及控制生态系的发展,以期自己能在Android平台上获得更多的利益(简单地说,就是收入,Google希望Android能够为自己带来更多的收益),而不再满足于只是打造及提供Android平台的角色。

随着Android一路开疆辟土,出现在越来越多的移动设备上,再加上Google对Android策略的转变,现今的Andr​​oid生态系统已变得较以往复杂了许多,系统中的角色较以往多了电信运营商、汽车制造商、串流内容及媒体提供商等。Google在全球移动市场的策略也已从“移动优先”转变至“攻占所有屏幕(装置)”,而Android也企图往这个目标上不断迈进(如图2所示)。






时至今日,欧洲、美国、日本的手机制造商节节败退,摩托罗拉、诺基亚、索尼等老牌制造商相继裁员(甚至出售手机及移动业务),而中国手机制造商却不断崛起,中兴、华为、联想、酷派、OPPO、小米等相继杀入手机市场后,如今中国已成为全球最大的智能机生产及销售国,智能机用户数早已超越美国。而新兴的国外市场,如印度、南美、东南亚正刮起一阵低价智能机风暴,Android正是这波低价智能机的推手(如采用MTK芯片的Andr​​oid One)。低价智能机席卷着新兴国家的市场,而新兴国家的市场也俨然成为智能机的一个重要主战场,Android的野心当然不止于此,Android企图发力于高、中、低阶的智能机市场,而这些细微的变化正一点点地牵动着Android生态系统的转变。

Android的开放与制约

Android一开始由Andy Rubin领军,从一开始的全面开放,到像选妃似的,每次释放出新版Android软件的同时,选择与特定的手机制造商合作开发Android原生机,例如HTC、三星等。这一举动令各家手机制造商对Android仰望备至,都想抱上Android的大腿。因为手机制造商一旦获得与Android合作开发新版原生机的机会,就等于能提早得到新版Android软件代码,进而取得先机来开发其他自家的产品(如三星的Galaxy系列),早对手一步将自家产品推向市场销售,从而取得市场先机。这种方式无疑令部分手机制造商对Android产生反感。

2013年3月,Android从Andy Rubin转由原领导Chrome的Sundar Pichai接手负责,而Android也由工程导向转为营利导向,例如减少手机制造商与Google分成Google Play和Google Search的收入。Android更强烈地主导其UI显示的一致性,并与各家手机制造商签订约束性的协议,强加Google的相关应用服务于Android系统上,甚至将应用摆放在Android桌面上的位置都强加限制,大幅度收紧了各家Android设备制造商分散且碎片化的UI风格,以期用户在汽车、电视、可穿戴设备、手机等所有Android设备上都能得到相同的用户体验,Google此举也造成了部分手机制造商及开发者的反感。

归根结底,Google还是希望自己的角色能像苹果一样介于用户和运营商之间,由目前的“用户/手机品牌商→运营商”,转变为“用户/手机品牌商→Google→运营商”,以期收紧分散且碎片化的Andr​​oid生态圈,并获取更大的潜在利益。这一点,我们可以在最新发布的Android L版本的软件中看到,Google加入了更多特定运营商所需的功能。

移动互联网时代,Android已然成为Google的一个标准平台,而非过去传闻的与Chrome整合成一个新的平台,或是将Android整合进Chrome中。这种情况下,Android设备制造商如何应对Google的策略调整及Android版本的快速演进,并调整自己迅速定位市场,从而避免自己成为只是帮Google打工的打工仔是至关重要的。Android设备制造商必须打造出自己独特的生态系统(例如跨手机、平板、电视等),而非只是一个设备制造商。这样一来,我们可以清晰地看到,目前纯手机制造商已越发难以生存。

Android系统与架构演进

从Android 1.0至今(更甚至是1.0之前的m*至今),Android系统每一版都有不少的改动(如图3所示),例如HAL有过两次的版本改进、Camera HAL已迭代至第三版、多媒体核心由一开始的OpenCore直到现在的Stagefright。而一开始的WebView至今则完全被Chrome取代,Android也从ARM一路拓展到x86及MIPS平台。版本演进的过程及内容实在太多,如果真的要巨细靡遗地写,可能三天三夜也写不完,所以我想仅对每一版本的改动给予一句代表性的描述​​,并在最后针对Android的最新版(代号L),做一些基本介绍。






Android 1.0:第一部Android手机以及Google Apps的诞生;

Android 1.5 Cupcake:支持软件键盘;

Android 1.6 Donut:支持CDMA;

Android 2.0 Éclair:GPS大放异彩,GoogleNexus One手机诞生;

Android 2.2 Froyo:加入语音识别功能;

Android 2.3 Gingerbread:Nexus S;

Android 3.0 Honeycomb:第一次专给平板设备设计UI;

Android 4.0 Ice Cream Sandwich:一个新的UI界面Holo与内嵌字体Roboto,并支持人脸解锁;

Android 4.1 Jelly Bean:Nexus 7:Google官方第一台Android平板设备;

Android 4.3 Jelly Bean:引入对可穿​​戴设备的支持;

Android 4.4 KitKat:支持更少内存的移动设备。

接下来是Android L,它的预设虚拟机为ART,支持64位,所需要的系统空间较以往的Andr​​oid版本更大,因为ART有一个转换档案格式的动作,其缺点就是会占用更多的系统空间,但之后软件的执行速度可能有一定的提升。另外,Android L可能会加入部分地区及运营商的特殊需求,例如multi-SIM、NFC、Wi-Fi等;此外​​,Android L也更强调系统安全,它可以预设为强制性安全模式,即一般应用启动时需要多道的身分及权限确认才能执行。

时至今日,Android身影几乎无处不在,回顾以往,Android系统的演进总是先求有、再求好,智能移动时代发展至今,全球正迈向下一个里程碑,希望Android此时能不忘初心,做一个平衡生态系统的维护者及领导者,而非仅是利益上的掮客,不要为了利益而让这个生态圈走向封闭。

作为开发者,此时更应该思考自己拥有如此巨大的市场优势、健全的物流体系及现金流系统,以及众多的手机及移动设备制造商,如果能积极培养系统级的软件人才,有条件打造出一个来自中国的自主生态系统,以期将来与Android分庭抗礼。
 
作者:钟文昌 查看全部
由Google、HTC、Qualcomm联手打造的第一部Android手机G1,开启了移动时代的Andr​​oid纪元(如图1所示),直到现在Android也是唯一能在移动市场上与iOS相抗衡的平台。简单地说,Android与iOS占尽了移动时代的先机(这个故事要从2007年的iPhone和2008年的Andr​​oid G1开始说起,甚至是更早之前的开发史及并购史),App开发者已在Android及iOS上扎下了深厚的根基,因此再也无力也没有必要去为第三个平台开发或移植自己的App,原因很简单,因为受众太少,支出与收入不成正比。

1.jpg


一开始Android生态系统很简单,就是拉拢App开发者,并且寻求与更多芯片制造商及手机厂商的合作,共同推广Android这个开放平台。但随着Android市场占有率逐步攀升,Google开始一步步地收紧及控制生态系的发展,以期自己能在Android平台上获得更多的利益(简单地说,就是收入,Google希望Android能够为自己带来更多的收益),而不再满足于只是打造及提供Android平台的角色。

随着Android一路开疆辟土,出现在越来越多的移动设备上,再加上Google对Android策略的转变,现今的Andr​​oid生态系统已变得较以往复杂了许多,系统中的角色较以往多了电信运营商、汽车制造商、串流内容及媒体提供商等。Google在全球移动市场的策略也已从“移动优先”转变至“攻占所有屏幕(装置)”,而Android也企图往这个目标上不断迈进(如图2所示)。

2.jpg


时至今日,欧洲、美国、日本的手机制造商节节败退,摩托罗拉、诺基亚、索尼等老牌制造商相继裁员(甚至出售手机及移动业务),而中国手机制造商却不断崛起,中兴、华为、联想、酷派、OPPO、小米等相继杀入手机市场后,如今中国已成为全球最大的智能机生产及销售国,智能机用户数早已超越美国。而新兴的国外市场,如印度、南美、东南亚正刮起一阵低价智能机风暴,Android正是这波低价智能机的推手(如采用MTK芯片的Andr​​oid One)。低价智能机席卷着新兴国家的市场,而新兴国家的市场也俨然成为智能机的一个重要主战场,Android的野心当然不止于此,Android企图发力于高、中、低阶的智能机市场,而这些细微的变化正一点点地牵动着Android生态系统的转变。

Android的开放与制约

Android一开始由Andy Rubin领军,从一开始的全面开放,到像选妃似的,每次释放出新版Android软件的同时,选择与特定的手机制造商合作开发Android原生机,例如HTC、三星等。这一举动令各家手机制造商对Android仰望备至,都想抱上Android的大腿。因为手机制造商一旦获得与Android合作开发新版原生机的机会,就等于能提早得到新版Android软件代码,进而取得先机来开发其他自家的产品(如三星的Galaxy系列),早对手一步将自家产品推向市场销售,从而取得市场先机。这种方式无疑令部分手机制造商对Android产生反感。

2013年3月,Android从Andy Rubin转由原领导Chrome的Sundar Pichai接手负责,而Android也由工程导向转为营利导向,例如减少手机制造商与Google分成Google Play和Google Search的收入。Android更强烈地主导其UI显示的一致性,并与各家手机制造商签订约束性的协议,强加Google的相关应用服务于Android系统上,甚至将应用摆放在Android桌面上的位置都强加限制,大幅度收紧了各家Android设备制造商分散且碎片化的UI风格,以期用户在汽车、电视、可穿戴设备、手机等所有Android设备上都能得到相同的用户体验,Google此举也造成了部分手机制造商及开发者的反感。

归根结底,Google还是希望自己的角色能像苹果一样介于用户和运营商之间,由目前的“用户/手机品牌商→运营商”,转变为“用户/手机品牌商→Google→运营商”,以期收紧分散且碎片化的Andr​​oid生态圈,并获取更大的潜在利益。这一点,我们可以在最新发布的Android L版本的软件中看到,Google加入了更多特定运营商所需的功能。

移动互联网时代,Android已然成为Google的一个标准平台,而非过去传闻的与Chrome整合成一个新的平台,或是将Android整合进Chrome中。这种情况下,Android设备制造商如何应对Google的策略调整及Android版本的快速演进,并调整自己迅速定位市场,从而避免自己成为只是帮Google打工的打工仔是至关重要的。Android设备制造商必须打造出自己独特的生态系统(例如跨手机、平板、电视等),而非只是一个设备制造商。这样一来,我们可以清晰地看到,目前纯手机制造商已越发难以生存。

Android系统与架构演进

从Android 1.0至今(更甚至是1.0之前的m*至今),Android系统每一版都有不少的改动(如图3所示),例如HAL有过两次的版本改进、Camera HAL已迭代至第三版、多媒体核心由一开始的OpenCore直到现在的Stagefright。而一开始的WebView至今则完全被Chrome取代,Android也从ARM一路拓展到x86及MIPS平台。版本演进的过程及内容实在太多,如果真的要巨细靡遗地写,可能三天三夜也写不完,所以我想仅对每一版本的改动给予一句代表性的描述​​,并在最后针对Android的最新版(代号L),做一些基本介绍。

3.JPG


Android 1.0:第一部Android手机以及Google Apps的诞生;

Android 1.5 Cupcake:支持软件键盘;

Android 1.6 Donut:支持CDMA;

Android 2.0 Éclair:GPS大放异彩,GoogleNexus One手机诞生;

Android 2.2 Froyo:加入语音识别功能;

Android 2.3 Gingerbread:Nexus S;

Android 3.0 Honeycomb:第一次专给平板设备设计UI;

Android 4.0 Ice Cream Sandwich:一个新的UI界面Holo与内嵌字体Roboto,并支持人脸解锁;

Android 4.1 Jelly Bean:Nexus 7:Google官方第一台Android平板设备;

Android 4.3 Jelly Bean:引入对可穿​​戴设备的支持;

Android 4.4 KitKat:支持更少内存的移动设备。

接下来是Android L,它的预设虚拟机为ART,支持64位,所需要的系统空间较以往的Andr​​oid版本更大,因为ART有一个转换档案格式的动作,其缺点就是会占用更多的系统空间,但之后软件的执行速度可能有一定的提升。另外,Android L可能会加入部分地区及运营商的特殊需求,例如multi-SIM、NFC、Wi-Fi等;此外​​,Android L也更强调系统安全,它可以预设为强制性安全模式,即一般应用启动时需要多道的身分及权限确认才能执行。

时至今日,Android身影几乎无处不在,回顾以往,Android系统的演进总是先求有、再求好,智能移动时代发展至今,全球正迈向下一个里程碑,希望Android此时能不忘初心,做一个平衡生态系统的维护者及领导者,而非仅是利益上的掮客,不要为了利益而让这个生态圈走向封闭。

作为开发者,此时更应该思考自己拥有如此巨大的市场优势、健全的物流体系及现金流系统,以及众多的手机及移动设备制造商,如果能积极培养系统级的软件人才,有条件打造出一个来自中国的自主生态系统,以期将来与Android分庭抗礼。
 
作者:钟文昌
0
评论

技术干货:网络性能测试 移动开发

admin 发表了文章 • 2325 次浏览 • 2015-07-07 13:51 • 来自相关话题

实时音视频这种实时业务一般用udp传输数据,其对网络性能是非常敏感的,在实战中,经常需要测试当前端到端或端到云的网络性能。在这里我们讨论一下网络性能测试中所涉及到指标,技术和相关工具,以及如何编写自己的网络性能测试工具。
 
性能指标

先给出几个比较重要的指标的定义以及它们的意义。
 带宽(吞吐量)
单位时间内传输的数据量,单位通常是每秒比特数,记作bps;带宽反映了网络的传输能力,越大越好;
丢包
数据包丢失个数,等于“发送数据包数” - “接受数据包数”;丢包反映了网络可靠性,越小越好;
时延
数据包从发送开始到接收到该数据所耗费的时间,单位通常是毫秒;时延反映了网络的速度,越小越好;
抖动
指时延的变化,即两个数据包时延的差值;抖动反映了网络的稳定性,越小越好;
乱序
指接收到的数据包顺序和发送顺序不一致的次数;乱序反映了网络的稳定性,越小越好;当乱序比较严重时,丢包也会比较严重,所以一般都以丢包指标为主,忽略乱序指标;
 
测试工具

网上有很多测试网络性能的工具,如果它们能满足需求的话,就不用自己再造轮子了。

ping

ping是最常见的,几乎在所有的OS上都有它的存在。 其工作原理如图






Local发送的数据包,Remote收到数据包后原样发回来;
数据包里包含有序号和时间戳信息;
序号用于判断是否丢包;
时间戳用于计算来回时延(图中蓝色部分),它等于接收时间减去数据包时间戳;

不同OS的ping命令选项可能会略有差别,以Mac OSX的ping为例$ping -s 1024 192.168.1.100

PING www.microsoft.com (23.42.217.205): 1024 data bytes

1032 bytes from 23.42.217.205: icmp_seq=0 ttl=49 time=83.883 ms

1032 bytes from 23.42.217.205: icmp_seq=1 ttl=49 time=77.958 ms

1032 bytes from 23.42.217.205: icmp_seq=2 ttl=49 time=80.053 ms

1032 bytes from 23.42.217.205: icmp_seq=3 ttl=49 time=78.244 ms

1032 bytes from 23.42.217.205: icmp_seq=4 ttl=49 time=77.937 ms

...

^C

--- 192.168.1.100 ping statistics ---

30 packets transmitted, 29 packets received, 3.3% packet loss

round-trip min/avg/max/stddev = 77.843/95.375/141.314/19.167 ms

其中 -s 1024 指示包的大小为1024字节;从ping结果可以看出,发送了30个包,收到29个包,3.3%的丢包率,最小时延77.843毫秒,最大时延141.314毫秒,平均时延95.375毫秒,时延的标准差19.167。另外,ping用的是ICMP协议,网络对ICMP协议处理性能,可能跟UDP或TCP是不一样的,所以测试结果只能做为参考。
小结:ping的优点是简单便捷,可以测试时延和丢包,缺点是无法测试带宽。

iperf

iperf功能功能强一些,可以测带宽,丢包,抖动, 但是测不了时延。它的工作原理如图:






服务端:$iperf -u -s -p 12345 -i 1 -w 1000000
------------------------------------------------------------

Server listening on UDP port 12345

Receiving 1470 byte datagrams

UDP buffer size: 977 KByte

------------------------------------------------------------

客户端:$ iperf -u -c 127.0.0.1 -p 12345 -i 1 -t 5 -b 16K -l 62

------------------------------------------------------------

Client connecting to 127.0.0.1, UDP port 12345

Sending 62 byte datagrams

UDP buffer size: 9.00 KByte (default)

------------------------------------------------------------

[ 4] local 127.0.0.1 port 59805 connected with 127.0.0.1 port 12345

[ ID] Interval Transfer Bandwidth

[ 4] 0.0- 1.0 sec 2.00 KBytes 16.4 Kbits/sec

[ 4] 1.0- 2.0 sec 1.94 KBytes 15.9 Kbits/sec

[ 4] 2.0- 3.0 sec 1.94 KBytes 15.9 Kbits/sec

[ 4] 3.0- 4.0 sec 1.94 KBytes 15.9 Kbits/sec

[ 4] 4.0- 5.0 sec 2.00 KBytes 16.4 Kbits/sec

[ 4] 0.0- 5.1 sec 9.87 KBytes 16.0 Kbits/sec

[ 4] Sent 163 datagrams

[ 4] Server Report:

[ 4] 0.0- 5.1 sec 9.87 KBytes 16.0 Kbits/sec 0.046 ms 0/ 163 (0%)

其中 -b 16K 指定了带宽参数。测试结果为丢包0个,平均抖动为0.046毫秒。
 
自己开发or(unsigned second = 0; second < test_seconds; second++)

{

for(unsigned ui = 0; ui < 8; ui++)

{

sendto 1024 bytes;

}

msleep(1000);

}

从上面可以看出,ping和iperf各有优缺点,通常需要两者组合才能满足我们的需求。有时候现有工具不能满足实际应用的需求,比如说完全模拟实际业务环境或者在产品里集成测试功能,这时候就需要发挥“自己动手,丰衣足食”的精神,造出一个适合自己用的轮子来。我们这里只讨论关键点之一:如何匀速发送数据。
我们以设定发送包长为1024字节,带宽为64kbps为例子,讨论发送数据的实现方案。
发送数据最简单的方法就是,起一个线程,每秒直接发送完当前秒的数据,然后sleep一秒,再继续发送,如下:

这种方法比较简单,但是因为发送数据是需要花费时间的,假如发送64Kbit花费了5毫秒,实际发送码率(带宽)为64/1005≈63.68Kbps,比设定值低一些。把发送时间考虑在内,第2个改进后的代码版本如下:for(unsigned second = 0; second < test_seconds; second++)

{

unsigned ts_start = gettimestamp();

for(unsigned ui = 0; ui < 8; ui++)

{

sendto 1024 bytes;

}

unsigned elapsed = gettimestamp() - ts_start;

msleep(1000-elapsed);

}

从大尺度上看,这个版本确实会按设定带宽发送数据,但从小的的时间片上看,其瞬时发送速率是非常高的。假如发送64Kbit花费了5毫秒,则瞬时速率为 64*1000/5=12800Kbps,是设定值的20倍。这种瞬时高发送速率可能会导致网络中某些路由器或交换机来不及处理而大量丢包。所以我们继续改进,在每发送一个包时check是否发送太快,如果发送太快的话就sleep一下缓一缓。改进后的第三个版本如下:uint64_t sent_bytes = 0;

unsigned kick_time = gettimestamp();

for(unsigned second = 0; second < test_seconds; second++) { sendto 1024 bytes; sent_bytes += 1024; unsigned elapsed = gettimestamp() - kick_time; unsigned normal = sent_bytes * 1000 * 8 / (64*1000); if(normal > elapsed)

{

msleep(normal-elapsed);

}

}

这个版本基本能够按照设定值匀速发送数据了。当然,它还不是最完美的,当设定带宽很高而包长很小时,会导致太多的check,占用太多CPU。这里就不继续改进了,有兴趣的看官可以自己实现之。
 
作者:符宁 查看全部
实时音视频这种实时业务一般用udp传输数据,其对网络性能是非常敏感的,在实战中,经常需要测试当前端到端或端到云的网络性能。在这里我们讨论一下网络性能测试中所涉及到指标,技术和相关工具,以及如何编写自己的网络性能测试工具。
 
性能指标

先给出几个比较重要的指标的定义以及它们的意义。
 带宽(吞吐量)
  • 单位时间内传输的数据量,单位通常是每秒比特数,记作bps;
  • 带宽反映了网络的传输能力,越大越好;

丢包
  • 数据包丢失个数,等于“发送数据包数” - “接受数据包数”;
  • 丢包反映了网络可靠性,越小越好;

时延
  • 数据包从发送开始到接收到该数据所耗费的时间,单位通常是毫秒;
  • 时延反映了网络的速度,越小越好;

抖动
  • 指时延的变化,即两个数据包时延的差值;
  • 抖动反映了网络的稳定性,越小越好;

乱序
  • 指接收到的数据包顺序和发送顺序不一致的次数;
  • 乱序反映了网络的稳定性,越小越好;
  • 当乱序比较严重时,丢包也会比较严重,所以一般都以丢包指标为主,忽略乱序指标;

 
测试工具

网上有很多测试网络性能的工具,如果它们能满足需求的话,就不用自己再造轮子了。

ping

ping是最常见的,几乎在所有的OS上都有它的存在。 其工作原理如图

1.png


Local发送的数据包,Remote收到数据包后原样发回来;
数据包里包含有序号和时间戳信息;
序号用于判断是否丢包;
时间戳用于计算来回时延(图中蓝色部分),它等于接收时间减去数据包时间戳;

不同OS的ping命令选项可能会略有差别,以Mac OSX的ping为例
$ping -s 1024 192.168.1.100

PING www.microsoft.com (23.42.217.205): 1024 data bytes

1032 bytes from 23.42.217.205: icmp_seq=0 ttl=49 time=83.883 ms

1032 bytes from 23.42.217.205: icmp_seq=1 ttl=49 time=77.958 ms

1032 bytes from 23.42.217.205: icmp_seq=2 ttl=49 time=80.053 ms

1032 bytes from 23.42.217.205: icmp_seq=3 ttl=49 time=78.244 ms

1032 bytes from 23.42.217.205: icmp_seq=4 ttl=49 time=77.937 ms

...

^C

--- 192.168.1.100 ping statistics ---

30 packets transmitted, 29 packets received, 3.3% packet loss

round-trip min/avg/max/stddev = 77.843/95.375/141.314/19.167 ms

其中 -s 1024 指示包的大小为1024字节;从ping结果可以看出,发送了30个包,收到29个包,3.3%的丢包率,最小时延77.843毫秒,最大时延141.314毫秒,平均时延95.375毫秒,时延的标准差19.167。另外,ping用的是ICMP协议,网络对ICMP协议处理性能,可能跟UDP或TCP是不一样的,所以测试结果只能做为参考。
小结:ping的优点是简单便捷,可以测试时延和丢包,缺点是无法测试带宽。

iperf

iperf功能功能强一些,可以测带宽,丢包,抖动, 但是测不了时延。它的工作原理如图:

2.png


服务端:
$iperf -u -s -p 12345 -i 1 -w 1000000
------------------------------------------------------------

Server listening on UDP port 12345

Receiving 1470 byte datagrams

UDP buffer size: 977 KByte

------------------------------------------------------------

客户端:
$ iperf -u -c 127.0.0.1 -p 12345 -i 1 -t 5 -b 16K -l 62

------------------------------------------------------------

Client connecting to 127.0.0.1, UDP port 12345

Sending 62 byte datagrams

UDP buffer size: 9.00 KByte (default)

------------------------------------------------------------

[ 4] local 127.0.0.1 port 59805 connected with 127.0.0.1 port 12345

[ ID] Interval Transfer Bandwidth

[ 4] 0.0- 1.0 sec 2.00 KBytes 16.4 Kbits/sec

[ 4] 1.0- 2.0 sec 1.94 KBytes 15.9 Kbits/sec

[ 4] 2.0- 3.0 sec 1.94 KBytes 15.9 Kbits/sec

[ 4] 3.0- 4.0 sec 1.94 KBytes 15.9 Kbits/sec

[ 4] 4.0- 5.0 sec 2.00 KBytes 16.4 Kbits/sec

[ 4] 0.0- 5.1 sec 9.87 KBytes 16.0 Kbits/sec

[ 4] Sent 163 datagrams

[ 4] Server Report:

[ 4] 0.0- 5.1 sec 9.87 KBytes 16.0 Kbits/sec 0.046 ms 0/ 163 (0%)

其中 -b 16K 指定了带宽参数。测试结果为丢包0个,平均抖动为0.046毫秒。
 
自己开发
or(unsigned second = 0; second < test_seconds; second++)

{

for(unsigned ui = 0; ui < 8; ui++)

{

sendto 1024 bytes;

}

msleep(1000);

}

从上面可以看出,ping和iperf各有优缺点,通常需要两者组合才能满足我们的需求。有时候现有工具不能满足实际应用的需求,比如说完全模拟实际业务环境或者在产品里集成测试功能,这时候就需要发挥“自己动手,丰衣足食”的精神,造出一个适合自己用的轮子来。我们这里只讨论关键点之一:如何匀速发送数据。
我们以设定发送包长为1024字节,带宽为64kbps为例子,讨论发送数据的实现方案。
发送数据最简单的方法就是,起一个线程,每秒直接发送完当前秒的数据,然后sleep一秒,再继续发送,如下:

这种方法比较简单,但是因为发送数据是需要花费时间的,假如发送64Kbit花费了5毫秒,实际发送码率(带宽)为64/1005≈63.68Kbps,比设定值低一些。把发送时间考虑在内,第2个改进后的代码版本如下:
for(unsigned second = 0; second < test_seconds; second++)

{

unsigned ts_start = gettimestamp();

for(unsigned ui = 0; ui < 8; ui++)

{

sendto 1024 bytes;

}

unsigned elapsed = gettimestamp() - ts_start;

msleep(1000-elapsed);

}

从大尺度上看,这个版本确实会按设定带宽发送数据,但从小的的时间片上看,其瞬时发送速率是非常高的。假如发送64Kbit花费了5毫秒,则瞬时速率为 64*1000/5=12800Kbps,是设定值的20倍。这种瞬时高发送速率可能会导致网络中某些路由器或交换机来不及处理而大量丢包。所以我们继续改进,在每发送一个包时check是否发送太快,如果发送太快的话就sleep一下缓一缓。改进后的第三个版本如下:
uint64_t sent_bytes = 0;

unsigned kick_time = gettimestamp();

for(unsigned second = 0; second < test_seconds; second++) { sendto 1024 bytes; sent_bytes += 1024; unsigned elapsed = gettimestamp() - kick_time; unsigned normal = sent_bytes * 1000 * 8 / (64*1000); if(normal > elapsed)

{

msleep(normal-elapsed);

}

}

这个版本基本能够按照设定值匀速发送数据了。当然,它还不是最完美的,当设定带宽很高而包长很小时,会导致太多的check,占用太多CPU。这里就不继续改进了,有兴趣的看官可以自己实现之。
 
作者:符宁
0
评论

Airbnb开源的三个大数据神器 移动开发

oscar 发表了文章 • 2667 次浏览 • 2015-07-07 11:56 • 来自相关话题

7月5日 Airbnb召开了第一次开放技术大会OpenAir,重点是数据驱动在airbnb开发过程中的实践,在大会上,Airbnb开源了3个大数据神器

Airpal






第一个神器叫Airpal,是airbnb内部最炙手可热的数据分析工具,目前在github上面有900多个star。

Airpal是建立在Facebook的Prestodb上的一个可视化分布式SQL查询引擎。Airbnb现在大概有1.5PB的数据。传统上是可以用hive查询,但Hive有以下几个缺点。

第一是对于一些小规模的query,map reduce的overhead太大,比如我就想看一张表的前10行,select * from * limit 10 Hive会触发一个map reduce job,然后半分钟过去了还在map阶段。。。而Airpal背后采用的prestodb则没有这个问题,并且Airpal提供对一个表的数据预览。

Hive的第二个缺点是对于非技术人士不大友好,而airpal是图形界面,只要会sql就可以使用,结果直接生成一个csv文件。很多非技术部门,比如finance的分析员需要做大数据分析的时候,Airpal会非常方便。据我观察,在airbnb,数据科学家还是喜欢用命令行的hive,而非技术人士,或者需要做一些简单查询的工程师和产品经理,则多用airpal

Airpal还有个好处是可以直接和公司的LDAP相连,员工用LDAP登陆,可以直接设置相应的访问权限,使得全公司可以放心用一套数据分析系统

Aerosolve

Aerosolve是支撑Airbnb定价建议系统的机器学习引擎。

传统的机器学习引擎更像一个黑箱,很难知道是哪一个feature对最后的结果产生 了最大的影响。比如Airbnb上的房东设定价格后,我们不仅是希望提示这个价格是过高或过低(模型判断结果),而是希望给房东具体的原因,比如位置太偏,或者评价数不够多(feature的权重)。

比如下图就说明了评价数量以及三星评价数量对价格的影响。我们(惊奇)的发现,一个评价和15个评价的效果差不多,房东并不会因为有更多的评价而得到更多的订单,而3星评价甚至会起到副作用






Airflow

大数据的基础还是data pipeline。Airflow则是Airbnb内部发起、排序、监控data pipeline的工具。





来源:用友开发者 查看全部
7月5日 Airbnb召开了第一次开放技术大会OpenAir,重点是数据驱动在airbnb开发过程中的实践,在大会上,Airbnb开源了3个大数据神器

Airpal

1.jpg


第一个神器叫Airpal,是airbnb内部最炙手可热的数据分析工具,目前在github上面有900多个star。

Airpal是建立在Facebook的Prestodb上的一个可视化分布式SQL查询引擎。Airbnb现在大概有1.5PB的数据。传统上是可以用hive查询,但Hive有以下几个缺点。

第一是对于一些小规模的query,map reduce的overhead太大,比如我就想看一张表的前10行,select * from * limit 10 Hive会触发一个map reduce job,然后半分钟过去了还在map阶段。。。而Airpal背后采用的prestodb则没有这个问题,并且Airpal提供对一个表的数据预览。

Hive的第二个缺点是对于非技术人士不大友好,而airpal是图形界面,只要会sql就可以使用,结果直接生成一个csv文件。很多非技术部门,比如finance的分析员需要做大数据分析的时候,Airpal会非常方便。据我观察,在airbnb,数据科学家还是喜欢用命令行的hive,而非技术人士,或者需要做一些简单查询的工程师和产品经理,则多用airpal

Airpal还有个好处是可以直接和公司的LDAP相连,员工用LDAP登陆,可以直接设置相应的访问权限,使得全公司可以放心用一套数据分析系统

Aerosolve

Aerosolve是支撑Airbnb定价建议系统的机器学习引擎。

传统的机器学习引擎更像一个黑箱,很难知道是哪一个feature对最后的结果产生 了最大的影响。比如Airbnb上的房东设定价格后,我们不仅是希望提示这个价格是过高或过低(模型判断结果),而是希望给房东具体的原因,比如位置太偏,或者评价数不够多(feature的权重)。

比如下图就说明了评价数量以及三星评价数量对价格的影响。我们(惊奇)的发现,一个评价和15个评价的效果差不多,房东并不会因为有更多的评价而得到更多的订单,而3星评价甚至会起到副作用

2.jpg


Airflow

大数据的基础还是data pipeline。Airflow则是Airbnb内部发起、排序、监控data pipeline的工具。

3.gif

来源:用友开发者
0
评论

2015 年度开源项目新秀榜 移动开发 开源

oscar 发表了文章 • 1834 次浏览 • 2015-07-07 11:36 • 来自相关话题

黑鸭(Black Duck)软件公布了一份名叫“年度开源项目新秀”的报告,介绍了由全球开源协会发起的10个最有趣、最活跃的新项目。






年度开源项目新秀

每年都有上千新的开源项目问世,但只有少数能够真正的吸引我们的关注。一些项目因为利用了当前比较流行的技术而发展壮大,有一些则真正地开启了一个新的领域。很多开源项目建立的初衷是为了解决一些生产上的问题,还有一些项目则是世界各地志同道合的开发者们共同发起的一个宏伟项目。

从2009年起,开源软件管理公司黑鸭便发起了 年度开源项目新秀 这一活动,它的评选根据 Open Hub 网站(即以前的Ohloh)上的活跃度。今年,我们很荣幸能够报道2015年10大开源项目新秀的得主和2名荣誉奖得主,它们是从上千个开源项目中脱颖而出的。评选采用了加权评分系统,得分标准基于项目的活跃度,交付速度和几个其它因数。

开源俨然成为了产业创新的引擎,就拿今年来说,和Docker容器相关的开源项目在全球各地兴起,这也不恰巧反映了企业最感兴趣的技术领域吗?最后,我们接下来介绍的项目,将会让你了解到全球开源项目的开发者们的在思考什么,这很快将会成为一个指引我们发展的领头羊。

2015年度开源项目新秀: DebOps






DebOps 收集打包了一套 Ansible 方案和规则(Ansible是一种自动化运维工具),可以从1个容器扩展到一个完整的数据中心。它的创始人Maciej Delmanowski将DebOps开源来保证项目长久进行,从而更好的通过外部贡献者的帮助发展下去。

DebOps始创于波兰的一个不起眼大学校园里,他们运营自己的数据中心,一切工作都采用手工配置。有时系统崩溃而导致几天的宕机,这时Delmanowski意识到一个配置管理系统是很有必要的。以Debian作为基础开始,DebOps是一组配置一整个数据基础设施的Ansible方案。此项目已经在许多不同的工作环境下实现,而创始者们则打算继续支持和改进这个项目。

2015年度开源项目新秀: Code Combat






传统的纸笔学习方法已近不能满足技术学科了。然而游戏却有很多人都爱玩,这也就是为什么 CodeCombat 的创始人会去开发一款多人协同编程游戏来教人们如何编码。

刚开始CodeCombat是一个创业想法,但其创始人决定取而代之创建一个开源项目。此想法在社区传播开来,很快不少贡献者加入到项目中来。项目发起仅仅两个月后,这款游戏就被接纳到Google’s Summer of Code活动中。这款游戏吸引了大量玩家,并被翻译成45种语言。CodeCombat希望成为那些想要一边学习代码同时获得乐趣的同学的风向标。

2015年度开源项目新秀: Storj






Storj 是一个点对点的云存储网络,可实现端到端加密,保证用户不用依赖第三方即可传输和共享数据。基于比特币block chain技术和点对点协议,Storj提供安全、私密、加密的云存储。

云数据存储的反对者担心成本开销和漏洞攻击。针对这两个担忧,Storj提供了一个私有云存储市场,用户可以通过Storjcoin X(SJCX) 购买交易存储空间。上传到Storj的文件会被粉碎、加密和存储到整个社区。只有文件所有者拥有密钥加密的信息。

在2014年举办的Texas Bitcoin Conference Hackathon会议上,去中心化的云存储市场概念首次被提出并证明可行。在第一次赢得黑客马拉松活动后,项目创始人们和领导团队利用开放论坛、Reddit、比特币论坛和社交媒体增长成了一个活跃的社区,如今,它们已成为影响Storj发展方向的一个重要组成部分。

2015年度开源项目新秀: Neovim





 
自1991年出现以来,Vim已经成为数以百万计软件开发人员所钟爱的文本编辑器。 而 Neovim 就是它的下一个版本。

在过去的23年里,软件开发生态系统经历了无数增长和创新。Neovim创始人Thiago de Arruda认为Vim缺乏当代元素,跟不上时代的发展。在保留Vim的招牌功能的前提下,Neovim团队同样在寻求改进和发展这个最受欢迎的文本编辑器的技术。早期众筹让Thiago de Arruda可以连续6个月时间投入到此项目。他相信Neovim社区会支持这个项目,激励他继续开发Neovim。

2015年度开源项目新秀: CockroachDB






前谷歌员工开发了一个开源的大型企业数据存储项目 CockroachDB ,它是一个可扩展的、跨地域复制且支持事务的数据存储的解决方案。

为了保证在线的百万兆字节流量业务的质量,Google开发了Spanner系统,这是一个可扩展的,稳定的,支持事务的系统。许多参与开发CockroachDB的团队现在都服务于开源社区。就像真正的蟑螂(cockroach)一样,CockroachDB可以在没有数据头、任意节点失效的情况下正常运行。这个开源项目有很多富有经验的贡献者,创始人们通过社交媒体、Github、网络、会议和聚会结识他们并鼓励他们参与其中。
 
2015年度开源项目新秀: Kubernetes






在将容器化软件到引入开源社区发展时, Docker 是一匹黑马,它创新了一套技术和工具。去年6月谷歌推出了 Kubernetes ,这是一款开源的容器管理工具,用来加快开发和简化操作。

谷歌在它的内部运营上使用容器技术多年了。在2014年夏天的DockerCon上大会上,谷歌这个互联网巨头开源了Kubernetes,Kubernetes的开发是为了满足迅速增长的Docker生态系统的需要。通过和其它的组织、项目合作,比如Red Hat和CoreOS,Kubernetes项目的管理者们推动它登上了Docker Hub的工具下载榜榜首。Kubernetes的开发团队希望扩大这个项目,发展它的社区,这样的话软件开发者就能花更少的时间在管理基础设施上,而更多的去开发他们自己的APP。

2015年度开源项目新秀: Open Bazaar





OpenBazaar是一个使用比特币与其他人交易的去中心化的市场。OpenBazaar这一概念最早在编程马拉松(hackathon)活动中被提出,它的创始人结合了BitTorent、比特币和传统的金融服务方式,创造了一个不受审查的交易平台。OpenBazaar的开发团队在寻求新的成员,而且不久以后他们将极度扩大Open Bazaar社区。Open Bazaar的核心是透明度,其创始人和贡献者的共同目标是在商务交易中掀起一场革命,让他们向着一个真实的、一个无控制的,去中心化的市场奋进。

2015年度开源项目新秀: IPFS





 
IPFS 是一个面向全球的、点对点的分布式版本文件系统。它综合了Git,BitTorrent,HTTP的思想,开启了一个新的数据和数据结构传输协议。

人们所知的开源,它的本意用简单的方法解决复杂的问题,这样产生许多新颖的想法,但是那些强大的项目仅仅是开源社区的冰山一角。IFPS有一个非常激进的团队,这个概念的提出是大胆的,令人惊讶的,有点甚至高不可攀。看起来,一个点对点的分布式文件系统是在寻求将所有的计算设备连在一起。这个可能的 HTTP 替换品通过多种渠道维护着一个社区,包括Git社区和超过100名贡献者的IRC。这个疯狂的想法将在2015年进行软件内部测试。

2015年度开源项目新秀: cAdvisor






cAdvisor (Container Advisor) 是一个针对在运行中的容器进行收集,统计,处理和输出信息的工具,它可以给容器的使用者提供资源的使用情况和工作特性。对于每一个容器,cAdvisor记录着资源的隔离参数,资源使用历史,资源使用历史对比框图,网络状态。这些从容器输出的数据跨越主机传递。

cAdvisor可以在绝大多数的Linux发行版上运行,并且支持包括Docker在内的多种容器类型。事实上它成为了一种容器的代理,并被集成在了很多系统中。cAdvisor在DockerHub下载量也是位居前茅。cAdvisor的开发团队希望把cAdvisor改进到能够更深入地理解应用性能,并且集成到集群系统。

2015年度开源项目新秀: Terraform





Terraform 提供了一些常见设置来创建一个基础设施,从物理机到虚拟机,以及email服务器、DNS服务器等。这个想法包括从家庭个人机解决方案到公共云平台提供的服务。一旦建立好了以后,Terraform可以让运维人员安全又高效地改变你的基础设施,就如同配置一样。

Terraform.io的创始者工作在一个Devops模式的公司,他找到了一个窍门把建立一个完整的数据中心所需的知识结合在一起,可以从添加服务器到支持网络服务的功能齐备的数据中心。基础设施的描述采用高级的配置语法,允许你把数据中心的蓝图按版本管理,并且转换成多种代码。著名开源公司HashiCorp赞助开发这个项目。

荣誉奖: Docker Fig






Drone 是一个基于Docker的持续集成平台,而且它是用Go语言写的。Drone项目不满于现存的设置开发环境的技术和流程。

Drone提供了一个简单的自动测试和持续交付的方法:简单选择一个Docker镜像来满足你的需求,连接并提交至GitHub即可。Drone使用Docker容器来提供隔离的测试环境,让每个项目完全自主控制它的环境,没有传统的服务器管理的负担。Drone背后的100位社区贡献者强烈希望把这个项目带到企业和移动应用程序开发中。

开源新秀





 
作者: Black Duck Software
Linux中国|译者: sevenot 查看全部
黑鸭(Black Duck)软件公布了一份名叫“年度开源项目新秀”的报告,介绍了由全球开源协会发起的10个最有趣、最活跃的新项目。

1.jpg


年度开源项目新秀

每年都有上千新的开源项目问世,但只有少数能够真正的吸引我们的关注。一些项目因为利用了当前比较流行的技术而发展壮大,有一些则真正地开启了一个新的领域。很多开源项目建立的初衷是为了解决一些生产上的问题,还有一些项目则是世界各地志同道合的开发者们共同发起的一个宏伟项目。

从2009年起,开源软件管理公司黑鸭便发起了 年度开源项目新秀 这一活动,它的评选根据 Open Hub 网站(即以前的Ohloh)上的活跃度。今年,我们很荣幸能够报道2015年10大开源项目新秀的得主和2名荣誉奖得主,它们是从上千个开源项目中脱颖而出的。评选采用了加权评分系统,得分标准基于项目的活跃度,交付速度和几个其它因数。

开源俨然成为了产业创新的引擎,就拿今年来说,和Docker容器相关的开源项目在全球各地兴起,这也不恰巧反映了企业最感兴趣的技术领域吗?最后,我们接下来介绍的项目,将会让你了解到全球开源项目的开发者们的在思考什么,这很快将会成为一个指引我们发展的领头羊。

2015年度开源项目新秀: DebOps

2.jpg


DebOps 收集打包了一套 Ansible 方案和规则(Ansible是一种自动化运维工具),可以从1个容器扩展到一个完整的数据中心。它的创始人Maciej Delmanowski将DebOps开源来保证项目长久进行,从而更好的通过外部贡献者的帮助发展下去。

DebOps始创于波兰的一个不起眼大学校园里,他们运营自己的数据中心,一切工作都采用手工配置。有时系统崩溃而导致几天的宕机,这时Delmanowski意识到一个配置管理系统是很有必要的。以Debian作为基础开始,DebOps是一组配置一整个数据基础设施的Ansible方案。此项目已经在许多不同的工作环境下实现,而创始者们则打算继续支持和改进这个项目。

2015年度开源项目新秀: Code Combat

3.jpg


传统的纸笔学习方法已近不能满足技术学科了。然而游戏却有很多人都爱玩,这也就是为什么 CodeCombat 的创始人会去开发一款多人协同编程游戏来教人们如何编码。

刚开始CodeCombat是一个创业想法,但其创始人决定取而代之创建一个开源项目。此想法在社区传播开来,很快不少贡献者加入到项目中来。项目发起仅仅两个月后,这款游戏就被接纳到Google’s Summer of Code活动中。这款游戏吸引了大量玩家,并被翻译成45种语言。CodeCombat希望成为那些想要一边学习代码同时获得乐趣的同学的风向标。

2015年度开源项目新秀: Storj

4.jpg


Storj 是一个点对点的云存储网络,可实现端到端加密,保证用户不用依赖第三方即可传输和共享数据。基于比特币block chain技术和点对点协议,Storj提供安全、私密、加密的云存储。

云数据存储的反对者担心成本开销和漏洞攻击。针对这两个担忧,Storj提供了一个私有云存储市场,用户可以通过Storjcoin X(SJCX) 购买交易存储空间。上传到Storj的文件会被粉碎、加密和存储到整个社区。只有文件所有者拥有密钥加密的信息。

在2014年举办的Texas Bitcoin Conference Hackathon会议上,去中心化的云存储市场概念首次被提出并证明可行。在第一次赢得黑客马拉松活动后,项目创始人们和领导团队利用开放论坛、Reddit、比特币论坛和社交媒体增长成了一个活跃的社区,如今,它们已成为影响Storj发展方向的一个重要组成部分。

2015年度开源项目新秀: Neovim

5.jpg

 
自1991年出现以来,Vim已经成为数以百万计软件开发人员所钟爱的文本编辑器。 而 Neovim 就是它的下一个版本。

在过去的23年里,软件开发生态系统经历了无数增长和创新。Neovim创始人Thiago de Arruda认为Vim缺乏当代元素,跟不上时代的发展。在保留Vim的招牌功能的前提下,Neovim团队同样在寻求改进和发展这个最受欢迎的文本编辑器的技术。早期众筹让Thiago de Arruda可以连续6个月时间投入到此项目。他相信Neovim社区会支持这个项目,激励他继续开发Neovim。

2015年度开源项目新秀: CockroachDB

6.jpg


前谷歌员工开发了一个开源的大型企业数据存储项目 CockroachDB ,它是一个可扩展的、跨地域复制且支持事务的数据存储的解决方案。

为了保证在线的百万兆字节流量业务的质量,Google开发了Spanner系统,这是一个可扩展的,稳定的,支持事务的系统。许多参与开发CockroachDB的团队现在都服务于开源社区。就像真正的蟑螂(cockroach)一样,CockroachDB可以在没有数据头、任意节点失效的情况下正常运行。这个开源项目有很多富有经验的贡献者,创始人们通过社交媒体、Github、网络、会议和聚会结识他们并鼓励他们参与其中。
 
2015年度开源项目新秀: Kubernetes

7.jpg


在将容器化软件到引入开源社区发展时, Docker 是一匹黑马,它创新了一套技术和工具。去年6月谷歌推出了 Kubernetes ,这是一款开源的容器管理工具,用来加快开发和简化操作。

谷歌在它的内部运营上使用容器技术多年了。在2014年夏天的DockerCon上大会上,谷歌这个互联网巨头开源了Kubernetes,Kubernetes的开发是为了满足迅速增长的Docker生态系统的需要。通过和其它的组织、项目合作,比如Red Hat和CoreOS,Kubernetes项目的管理者们推动它登上了Docker Hub的工具下载榜榜首。Kubernetes的开发团队希望扩大这个项目,发展它的社区,这样的话软件开发者就能花更少的时间在管理基础设施上,而更多的去开发他们自己的APP。

2015年度开源项目新秀: Open Bazaar

8.jpg

OpenBazaar是一个使用比特币与其他人交易的去中心化的市场。OpenBazaar这一概念最早在编程马拉松(hackathon)活动中被提出,它的创始人结合了BitTorent、比特币和传统的金融服务方式,创造了一个不受审查的交易平台。OpenBazaar的开发团队在寻求新的成员,而且不久以后他们将极度扩大Open Bazaar社区。Open Bazaar的核心是透明度,其创始人和贡献者的共同目标是在商务交易中掀起一场革命,让他们向着一个真实的、一个无控制的,去中心化的市场奋进。

2015年度开源项目新秀: IPFS

9.jpg

 
IPFS 是一个面向全球的、点对点的分布式版本文件系统。它综合了Git,BitTorrent,HTTP的思想,开启了一个新的数据和数据结构传输协议。

人们所知的开源,它的本意用简单的方法解决复杂的问题,这样产生许多新颖的想法,但是那些强大的项目仅仅是开源社区的冰山一角。IFPS有一个非常激进的团队,这个概念的提出是大胆的,令人惊讶的,有点甚至高不可攀。看起来,一个点对点的分布式文件系统是在寻求将所有的计算设备连在一起。这个可能的 HTTP 替换品通过多种渠道维护着一个社区,包括Git社区和超过100名贡献者的IRC。这个疯狂的想法将在2015年进行软件内部测试。

2015年度开源项目新秀: cAdvisor

10.jpg


cAdvisor (Container Advisor) 是一个针对在运行中的容器进行收集,统计,处理和输出信息的工具,它可以给容器的使用者提供资源的使用情况和工作特性。对于每一个容器,cAdvisor记录着资源的隔离参数,资源使用历史,资源使用历史对比框图,网络状态。这些从容器输出的数据跨越主机传递。

cAdvisor可以在绝大多数的Linux发行版上运行,并且支持包括Docker在内的多种容器类型。事实上它成为了一种容器的代理,并被集成在了很多系统中。cAdvisor在DockerHub下载量也是位居前茅。cAdvisor的开发团队希望把cAdvisor改进到能够更深入地理解应用性能,并且集成到集群系统。

2015年度开源项目新秀: Terraform

11.jpg

Terraform 提供了一些常见设置来创建一个基础设施,从物理机到虚拟机,以及email服务器、DNS服务器等。这个想法包括从家庭个人机解决方案到公共云平台提供的服务。一旦建立好了以后,Terraform可以让运维人员安全又高效地改变你的基础设施,就如同配置一样。

Terraform.io的创始者工作在一个Devops模式的公司,他找到了一个窍门把建立一个完整的数据中心所需的知识结合在一起,可以从添加服务器到支持网络服务的功能齐备的数据中心。基础设施的描述采用高级的配置语法,允许你把数据中心的蓝图按版本管理,并且转换成多种代码。著名开源公司HashiCorp赞助开发这个项目。

荣誉奖: Docker Fig

12.jpg


Drone 是一个基于Docker的持续集成平台,而且它是用Go语言写的。Drone项目不满于现存的设置开发环境的技术和流程。

Drone提供了一个简单的自动测试和持续交付的方法:简单选择一个Docker镜像来满足你的需求,连接并提交至GitHub即可。Drone使用Docker容器来提供隔离的测试环境,让每个项目完全自主控制它的环境,没有传统的服务器管理的负担。Drone背后的100位社区贡献者强烈希望把这个项目带到企业和移动应用程序开发中。

开源新秀

13.jpg

 
作者: Black Duck Software
Linux中国|译者: sevenot
0
评论

环信CEO:“即时通讯云+移动客服”为App打造用户体验闭环 环信 移动开发 IM

oscar 发表了文章 • 1124 次浏览 • 2015-07-06 14:52 • 来自相关话题

 
随着移动互联网的发展,即时通讯、移动客服已经成为了很多移动应用的必备功能,环信作为新晋移动即时通讯PaaS平台服务商,凭借着近期刚刚上线的跨平台移动端客服产品吸引了大量应用开发者的关注。为了进一步了解移动客服产品的发展现状,InfoQ专门对环信联合创始人及CEO刘俊彦进行了专访。
 
InfoQ:环信成立已经有两年的时间,能聊一下这两年环信的整体发展吗?
 刘俊彦:环信在2013年4月成立,2014年6月第一个产品”环信即时通讯云”正式上线。然后在今年4月份上线了移动客服产品。在过去的一年里面,环信做了三轮融资,分别是去年5月份的天使轮,去年8月份的A轮,和去年10月份的A+轮。截止到今年5月底,一共有23000款APP在使用环信即时通讯云SDK。环信的SDK覆盖了2.5亿的终端用户,环信即时通讯平台日活是千万级别,每天处理将近两亿条消息。这就是环信过去两年大概的情况。InfoQ:移动客服可以算是现在移动应用通讯领域的一个刚性需求了,您能否谈一谈移动客服的形式都有哪些?刘俊彦:虽然移动客服是一种移动互联网时代的新产品,但其实也只是形式上的一个创新。基本上每一个APP的设置页面都会有一个“意见反馈”的功能。其实这个功能就是一个客服功能,只是受限于技术、资源等因素,需要以表单的形式来呈现,有的时候还需要用户选择类别、提交联系方式,很难做到实时更新。

最近这一年,随着移动电商、O2O,在线教育,在线旅游,互联网金融产品的发展,出现了很多形式的客服产品。比如:作为电商,做O2O一定要做售前、售中、售后。这个过程中就涉及到用户与商家的沟通。

常见的沟通形式有4种,第一种是在App里面提供一个按钮,用户点击该按钮直接跳转到QQ,然后通过QQ去完成与商家的交流。

第二种是通过链接跳转微信。第三种形式就是我们最开始提到的表单形式,这种形式是非实时的。

最新的一种形式是用即时通讯的方法来跟商家沟通。用户打开一个窗口,在该窗口可以发语音、图片、文字,可以跟商家进行实时互动,这种形式就类似与微信、旺旺。第四种形式是最受大家欢迎,受O2O的商家、电商、医疗、互联网金融认可度最高的的一种客服形式,这种形式非常有利于用户通过手机与商家进行沟通。

InfoQ:针对这种移动客服的形式,存在哪些技术难点?环信是怎样客服这些难点的?刘俊彦:用IM来做客服虽然很方便,但它的技术门槛比较高。第一需要你的服务器能够做到千万级、亿级的并发处理。移动客服是基于IM的长连接技术实现的。举个例子,如果某个App有100万日活用户,那么用户的手机和客服服务器之间就存在一百万条长连接。一些大型的App可能会有几百万、几千万的日活用户,那么提供服务的厂家就需要支持几百万、几千万的用户长连接。如果你的平台要支持上几百家厂商,那么平台就需要有支持几千万到几亿用户同时连接的能力。

第二需要做到不丢消息,并且每一条消息能够做到最实时的到达。即时通讯服务是帮助商家来进行销售的,用户可能是在三线城市,也可能是在四线城市,网络环境可能是2G、3G或4G。要做到任何情况下,只要有网络,消息一定能够即时到达是非常困难的。但如果你的平台做不到,就会给商家带来损失。拿电商来举例:一个消费者想买一样东西,发了一条咨询消息,但这个消息丢失了,那么就意味着这个单子丢了。这个用户可能是商家花了很多钱,从其它平台导流过来的,但是因为一条咨询没有即时收到,结果流失了,这样就给商家带来了损失。

环信对于移动客服的技术已经非常成熟,因为环信从去年6月1日正式上线,做的就是即时通讯云。我们在即时通讯云这一块已经做到了全国有2.3万家APP使用,有2.5亿用户,平台的日活用户是几千万。两年多的技术储备让我们敢保证绝对不丢消息,并且消息能够非常实时的到达。

InfoQ:因为领域的不同导致用户流量分布特点也不同,所以说即时通讯服务里面会经常产生波峰波谷。能不能谈一谈环信在这个弹性方面的具体措施呢?刘俊彦:解决该问题要从技术与非技术两方面着手。非技术其实就只能靠烧钱来解决。我们系统上大概有50%的余量,超过50%的压力之后,就开始加服务器。这样能保证系统在不到50%冗余的情况下运行。当然这也意味着有50%的容量浪费,其实这个“浪费”是应付一些不可预料的波峰和波谷。单个APP的用户行为基本是固定的。社交类APP,大概在晚上十点半会产生波峰。而有一些企业办公类、教育类App是在白天产生波峰。我们为两万多家APP提供服务,综合起来整个波峰和波谷就会比较平均一些。

我们也采取了一些技术手段来解决该问题。现在有一些云服务平台提供秒级计算API。当到半夜两点钟,所有APP都进入波谷后,我们就会调用API释放掉一批服务器。但这样带来的经济效益也不高,因为秒级API走的是另外一套收费体系。

InfoQ:环信开放了UI源码,现在用户可以深度定制应用的UI。环信还建立了自己的开源社区,能不能谈一谈环信在开源方面有什么样的规划?是否考虑给开发者开放更灵活的API,或者是直接开源一些核心技术?刘俊彦:环信的四位创始人有三位都是长期在开源社区工作的。而我从03年以后,基本上没有做过商业软件。所以开源精神已经深深植入到每一位创始人。

除了UI开源之外,我们还建了一个自己的开源社区。在过去的两年里,我们看到了一个很有意思的现象。很多人用环信来做社交,有单聊、群聊、匿名群聊等等各种玩法。但是归纳之后,大概可分为几十种。所以我们希望通过社区的力量,把这几十种常见的社交模块做出来,然后用开源的形式提供给大家。当用户想要做一款新的社交APP时,基于环信这样的底层云服务模块,有可能会节约几个月的时间。

有了上面的基础,我们就想走的更远一点。当你想做一款APP的时候,你可能用到一个朋友圈的功能,用到一个匿名的功能,我们希望这些功能也变成一个现成的模块,甚至整个APP都能够以开源的形式完整呈现。这样大家在开发一款APP的时候,就像是搭积木,选不同的积木模块,然后把他们拼起来。特别是对于创业者,可以把更多的时间用于提升用户体验。

最近这一个月我们开放了三个应用级别的模块:第一个是凡信,它是高仿微信的一款APP。凡信实现了单聊、群聊、朋友群等功能。这是我们社区里一个网友开发的,他完全无私的把服务器端和客服端代码开源出来。第二个是一个类似于陌陌的陌生人交友APP,功能主要是看附近的人,看到附近的人之后可以跟他聊天。第三个是我们面向企业的开源产品。上面提到的开源项目大家都可以到我们的社区下载,当然你也可以成为这些项目的贡献者,一起来推动这些产品往前走。

InfoQ:最近IT行业内数据中心机房出的问题也很多,环信在异地多活这方面有什么样的规划吗?刘俊彦:到现在为止,环信的云服务都托管在国内最一流的云服务平台上。按照他们的星级来说,都是最顶尖的机房,可靠性、安全性都是有保证的。但为了给大家提供更可靠、更放心的云服务,“异地多活”已经列入了我们的开发计划,未来的几个月环信的“异地多活”就会正式上线。InfoQ:最近有消息说环信要开始新一轮的融资,您能不能谈一谈环信在短期内的发展计划呢?刘俊彦:刚刚我提到过环信在过去一年里进行了三轮融资。我们目前其实正在做B轮融资,因为还在进行中,如果有更多的细节我会尽快告诉大家。

环信发展到现在已成规模,下一步我们会继续巩固环信在“即时通讯云”领域国内第一的位置,我们希望以最低的价格、最好的服务为做社交以及各种应用服务者提供即时通讯功能。其次我们在今年4月份上线了环信移动客服产品。移动客服是我们在即时通讯领域一个很大的扩展。在即时通讯领域有两种场景,一种是在APP里面用户和用户之间进行社交活动,另一种是用户与商家之间的聊天,也就是客服。我们一直认为任何一款APP,都需要即时通讯,那么要达到100%的覆盖,光做社交是无法实现的,所以我们要加上客服这一块。我们最终的愿景是用环信的力量和技术为每一款APP提供即时通讯功能。

  查看全部

ban9.png

 
随着移动互联网的发展,即时通讯、移动客服已经成为了很多移动应用的必备功能,环信作为新晋移动即时通讯PaaS平台服务商,凭借着近期刚刚上线的跨平台移动端客服产品吸引了大量应用开发者的关注。为了进一步了解移动客服产品的发展现状,InfoQ专门对环信联合创始人及CEO刘俊彦进行了专访。
 
InfoQ:环信成立已经有两年的时间,能聊一下这两年环信的整体发展吗?
 
刘俊彦:环信在2013年4月成立,2014年6月第一个产品”环信即时通讯云”正式上线。然后在今年4月份上线了移动客服产品。在过去的一年里面,环信做了三轮融资,分别是去年5月份的天使轮,去年8月份的A轮,和去年10月份的A+轮。截止到今年5月底,一共有23000款APP在使用环信即时通讯云SDK。环信的SDK覆盖了2.5亿的终端用户,环信即时通讯平台日活是千万级别,每天处理将近两亿条消息。这就是环信过去两年大概的情况。
InfoQ:移动客服可以算是现在移动应用通讯领域的一个刚性需求了,您能否谈一谈移动客服的形式都有哪些?
刘俊彦:虽然移动客服是一种移动互联网时代的新产品,但其实也只是形式上的一个创新。基本上每一个APP的设置页面都会有一个“意见反馈”的功能。其实这个功能就是一个客服功能,只是受限于技术、资源等因素,需要以表单的形式来呈现,有的时候还需要用户选择类别、提交联系方式,很难做到实时更新。

最近这一年,随着移动电商、O2O,在线教育,在线旅游,互联网金融产品的发展,出现了很多形式的客服产品。比如:作为电商,做O2O一定要做售前、售中、售后。这个过程中就涉及到用户与商家的沟通。

常见的沟通形式有4种,第一种是在App里面提供一个按钮,用户点击该按钮直接跳转到QQ,然后通过QQ去完成与商家的交流。

第二种是通过链接跳转微信。第三种形式就是我们最开始提到的表单形式,这种形式是非实时的。

最新的一种形式是用即时通讯的方法来跟商家沟通。用户打开一个窗口,在该窗口可以发语音、图片、文字,可以跟商家进行实时互动,这种形式就类似与微信、旺旺。第四种形式是最受大家欢迎,受O2O的商家、电商、医疗、互联网金融认可度最高的的一种客服形式,这种形式非常有利于用户通过手机与商家进行沟通。

InfoQ:针对这种移动客服的形式,存在哪些技术难点?环信是怎样客服这些难点的?
刘俊彦:用IM来做客服虽然很方便,但它的技术门槛比较高。第一需要你的服务器能够做到千万级、亿级的并发处理。移动客服是基于IM的长连接技术实现的。举个例子,如果某个App有100万日活用户,那么用户的手机和客服服务器之间就存在一百万条长连接。一些大型的App可能会有几百万、几千万的日活用户,那么提供服务的厂家就需要支持几百万、几千万的用户长连接。如果你的平台要支持上几百家厂商,那么平台就需要有支持几千万到几亿用户同时连接的能力。

第二需要做到不丢消息,并且每一条消息能够做到最实时的到达。即时通讯服务是帮助商家来进行销售的,用户可能是在三线城市,也可能是在四线城市,网络环境可能是2G、3G或4G。要做到任何情况下,只要有网络,消息一定能够即时到达是非常困难的。但如果你的平台做不到,就会给商家带来损失。拿电商来举例:一个消费者想买一样东西,发了一条咨询消息,但这个消息丢失了,那么就意味着这个单子丢了。这个用户可能是商家花了很多钱,从其它平台导流过来的,但是因为一条咨询没有即时收到,结果流失了,这样就给商家带来了损失。

环信对于移动客服的技术已经非常成熟,因为环信从去年6月1日正式上线,做的就是即时通讯云。我们在即时通讯云这一块已经做到了全国有2.3万家APP使用,有2.5亿用户,平台的日活用户是几千万。两年多的技术储备让我们敢保证绝对不丢消息,并且消息能够非常实时的到达。

InfoQ:因为领域的不同导致用户流量分布特点也不同,所以说即时通讯服务里面会经常产生波峰波谷。能不能谈一谈环信在这个弹性方面的具体措施呢?
刘俊彦:解决该问题要从技术与非技术两方面着手。非技术其实就只能靠烧钱来解决。我们系统上大概有50%的余量,超过50%的压力之后,就开始加服务器。这样能保证系统在不到50%冗余的情况下运行。当然这也意味着有50%的容量浪费,其实这个“浪费”是应付一些不可预料的波峰和波谷。单个APP的用户行为基本是固定的。社交类APP,大概在晚上十点半会产生波峰。而有一些企业办公类、教育类App是在白天产生波峰。我们为两万多家APP提供服务,综合起来整个波峰和波谷就会比较平均一些。

我们也采取了一些技术手段来解决该问题。现在有一些云服务平台提供秒级计算API。当到半夜两点钟,所有APP都进入波谷后,我们就会调用API释放掉一批服务器。但这样带来的经济效益也不高,因为秒级API走的是另外一套收费体系。

InfoQ:环信开放了UI源码,现在用户可以深度定制应用的UI。环信还建立了自己的开源社区,能不能谈一谈环信在开源方面有什么样的规划?是否考虑给开发者开放更灵活的API,或者是直接开源一些核心技术?
刘俊彦:环信的四位创始人有三位都是长期在开源社区工作的。而我从03年以后,基本上没有做过商业软件。所以开源精神已经深深植入到每一位创始人。

除了UI开源之外,我们还建了一个自己的开源社区。在过去的两年里,我们看到了一个很有意思的现象。很多人用环信来做社交,有单聊、群聊、匿名群聊等等各种玩法。但是归纳之后,大概可分为几十种。所以我们希望通过社区的力量,把这几十种常见的社交模块做出来,然后用开源的形式提供给大家。当用户想要做一款新的社交APP时,基于环信这样的底层云服务模块,有可能会节约几个月的时间。

有了上面的基础,我们就想走的更远一点。当你想做一款APP的时候,你可能用到一个朋友圈的功能,用到一个匿名的功能,我们希望这些功能也变成一个现成的模块,甚至整个APP都能够以开源的形式完整呈现。这样大家在开发一款APP的时候,就像是搭积木,选不同的积木模块,然后把他们拼起来。特别是对于创业者,可以把更多的时间用于提升用户体验。

最近这一个月我们开放了三个应用级别的模块:第一个是凡信,它是高仿微信的一款APP。凡信实现了单聊、群聊、朋友群等功能。这是我们社区里一个网友开发的,他完全无私的把服务器端和客服端代码开源出来。第二个是一个类似于陌陌的陌生人交友APP,功能主要是看附近的人,看到附近的人之后可以跟他聊天。第三个是我们面向企业的开源产品。上面提到的开源项目大家都可以到我们的社区下载,当然你也可以成为这些项目的贡献者,一起来推动这些产品往前走。

InfoQ:最近IT行业内数据中心机房出的问题也很多,环信在异地多活这方面有什么样的规划吗?
刘俊彦:到现在为止,环信的云服务都托管在国内最一流的云服务平台上。按照他们的星级来说,都是最顶尖的机房,可靠性、安全性都是有保证的。但为了给大家提供更可靠、更放心的云服务,“异地多活”已经列入了我们的开发计划,未来的几个月环信的“异地多活”就会正式上线。
InfoQ:最近有消息说环信要开始新一轮的融资,您能不能谈一谈环信在短期内的发展计划呢?
刘俊彦:刚刚我提到过环信在过去一年里进行了三轮融资。我们目前其实正在做B轮融资,因为还在进行中,如果有更多的细节我会尽快告诉大家。

环信发展到现在已成规模,下一步我们会继续巩固环信在“即时通讯云”领域国内第一的位置,我们希望以最低的价格、最好的服务为做社交以及各种应用服务者提供即时通讯功能。其次我们在今年4月份上线了环信移动客服产品。移动客服是我们在即时通讯领域一个很大的扩展。在即时通讯领域有两种场景,一种是在APP里面用户和用户之间进行社交活动,另一种是用户与商家之间的聊天,也就是客服。我们一直认为任何一款APP,都需要即时通讯,那么要达到100%的覆盖,光做社交是无法实现的,所以我们要加上客服这一块。我们最终的愿景是用环信的力量和技术为每一款APP提供即时通讯功能。

 
0
评论

解析:带你从源码的角度彻底理解,Android事件分发机制(下) 移动开发

oscar 发表了文章 • 1258 次浏览 • 2015-07-03 14:28 • 来自相关话题

记得在前面的文章中,我带大家一起从源码的角度分析了Android中View的事件分发机制,相信阅读过的朋友对View的事件分发已经有比较深刻的理解了。

还未阅读过的朋友,请先参考上文:http://www.imgeek.org/article/51

那么今天我们将继续上次未完成的话题,从源码的角度分析ViewGruop的事件分发。


首先我们来探讨一下,什么是ViewGroup?它和普通的View有什么区别?

顾名思义,ViewGroup就是一组View的集合,它包含很多的子View和子VewGroup,是Android中所有布局的父类或间接父类,像LinearLayout、RelativeLayout等都是继承自ViewGroup的。但ViewGroup实际上也是一个View,只不过比起View,它多了可以包含子View和定义布局参数的功能。ViewGroup继承结构示意图如下所示:






可以看到,我们平时项目里经常用到的各种布局,全都属于ViewGroup的子类。

简单介绍完了ViewGroup,我们现在通过一个Demo来演示一下Android中VewGroup的事件分发流程吧。


先我们来自定义一个布局,命名为MyLayout,继承自LinearLayout,如下所示:
public class MyLayout extends LinearLayout {
02.
03. public MyLayout(Context context, AttributeSet attrs) {
04. super(context, attrs);
05. }
06.
07.}
然后,打开主布局文件activity_main.xml,在其中加入我们自定义的布局:

[html] view plaincopy
01.<com.example.viewgrouptouchevent.MyLayout xmlns:android="http://schemas.android.com/apk/res/android"
02. xmlns:tools="http://schemas.android.com/tools"
03. android:id="@+id/my_layout"
04. android:layout_width="match_parent"
05. android:layout_height="match_parent"
06. android:orientation="vertical" >
07.
08. <Button
09. android:id="@+id/button1"
10. android:layout_width="match_parent"
11. android:layout_height="wrap_content"
12. android:text="Button1" />
13.
14. <Button
15. android:id="@+id/button2"
16. android:layout_width="match_parent"
17. android:layout_height="wrap_content"
18. android:text="Button2" />
19.
20.</com.example.viewgrouptouchevent.MyLayout>
可以看到,我们在MyLayout中添加了两个按钮,接着在MainActivity中为这两个按钮和MyLayout都注册了监听事件:
myLayout.setOnTouchListener(new OnTouchListener() {
02. @Override
03. public boolean onTouch(View v, MotionEvent event) {
04. Log.d("TAG", "myLayout on touch");
05. return false;
06. }
07.});
08.button1.setOnClickListener(new OnClickListener() {
09. @Override
10. public void onClick(View v) {
11. Log.d("TAG", "You clicked button1");
12. }
13.});
14.button2.setOnClickListener(new OnClickListener() {
15. @Override
16. public void onClick(View v) {
17. Log.d("TAG", "You clicked button2");
18. }
19.});
 我们在MyLayout的onTouch方法,和Button1、Button2的onClick方法中都打印了一句话。现在运行一下项目,效果图如下所示:






分别点击一下Button1、Button2和空白区域,打印结果如下所示:






你会发现,当点击按钮的时候,MyLayout注册的onTouch方法并不会执行,只有点击空白区域的时候才会执行该方法。你可以先理解成Button的onClick方法将事件消费掉了,因此事件不会再继续向下传递。

那就说明Android中的touch事件是先传递到View,再传递到ViewGroup的?现在下结论还未免过早了,让我们再来做一个实验。

查阅文档可以看到,ViewGroup中有一个onInterceptTouchEvent方法,我们来看一下这个方法的源码:
/**
02. * Implement this method to intercept all touch screen motion events. This
03. * allows you to watch events as they are dispatched to your children, and
04. * take ownership of the current gesture at any point.
05. *
06. * <p>Using this function takes some care, as it has a fairly complicated
07. * interaction with {@link View#onTouchEvent(MotionEvent)
08. * View.onTouchEvent(MotionEvent)}, and using it requires implementing
09. * that method as well as this one in the correct way. Events will be
10. * received in the following order:
11. *
12. * <ol>
13. * <li> You will receive the down event here.
14. * <li> The down event will be handled either by a child of this view
15. * group, or given to your own onTouchEvent() method to handle; this means
16. * you should implement onTouchEvent() to return true, so you will
17. * continue to see the rest of the gesture (instead of looking for
18. * a parent view to handle it). Also, by returning true from
19. * onTouchEvent(), you will not receive any following
20. * events in onInterceptTouchEvent() and all touch processing must
21. * happen in onTouchEvent() like normal.
22. * <li> For as long as you return false from this function, each following
23. * event (up to and including the final up) will be delivered first here
24. * and then to the target's onTouchEvent().
25. * <li> If you return true from here, you will not receive any
26. * following events: the target view will receive the same event but
27. * with the action {@link MotionEvent#ACTION_CANCEL}, and all further
28. * events will be delivered to your onTouchEvent() method and no longer
29. * appear here.
30. * </ol>
31. *
32. * @param ev The motion event being dispatched down the hierarchy.
33. * @return Return true to steal motion events from the children and have
34. * them dispatched to this ViewGroup through onTouchEvent().
35. * The current target will receive an ACTION_CANCEL event, and no further
36. * messages will be delivered here.
37. */
38.public boolean onInterceptTouchEvent(MotionEvent ev) {
39. return false;
40.}
如果不看源码你还真可能被这注释吓到了,这么长的英文注释看得头都大了。可是源码竟然如此简单!只有一行代码,返回了一个false!好吧,既然是布尔型的返回,那么只有两种可能,我们在MyLayout中重写这个方法,然后返回一个true试试,代码如下所示:
public class MyLayout extends LinearLayout {
02.
03. public MyLayout(Context context, AttributeSet attrs) {
04. super(context, attrs);
05. }
06.
07. @Override
08. public boolean onInterceptTouchEvent(MotionEvent ev) {
09. return true;
10. }
11.
12.}
现在再次运行项目,然后分别Button1、Button2和空白区域,打印结果如下所示:





你会发现,不管你点击哪里,永远都只会触发MyLayout的touch事件了,按钮的点击事件完全被屏蔽掉了!这是为什么呢?如果Android中的touch事件是先传递到View,再传递到ViewGroup的,那么MyLayout又怎么可能屏蔽掉Button的点击事件呢?

看来只有通过阅读源码,搞清楚Android中ViewGroup的事件分发机制,才能解决我们心中的疑惑了,不过这里我想先跟你透露一句,Android中touch事件的传递,绝对是先传递到ViewGroup,再传递到View的。记得在Android事件分发机制完全解析,带你从源码的角度彻底理解(上) 中我有说明过,只要你触摸了任何控件,就一定会调用该控件的dispatchTouchEvent方法。这个说法没错,只不过还不完整而已。实际情况是,当你点击了某个控件,首先会去调用该控件所在布局的dispatchTouchEvent方法,然后在布局的dispatchTouchEvent方法中找到被点击的相应控件,再去调用该控件的dispatchTouchEvent方法。如果我们点击了MyLayout中的按钮,会先去调用MyLayout的dispatchTouchEvent方法,可是你会发现MyLayout中并没有这个方法。那就再到它的父类LinearLayout中找一找,发现也没有这个方法。那只好继续再找LinearLayout的父类ViewGroup,你终于在ViewGroup中看到了这个方法,按钮的dispatchTouchEvent方法就是在这里调用的。修改后的示意图如下所示:






那还等什么?快去看一看ViewGroup中的dispatchTouchEvent方法的源码吧!代码如下所示:
public boolean dispatchTouchEvent(MotionEvent ev) {
02. final int action = ev.getAction();
03. final float xf = ev.getX();
04. final float yf = ev.getY();
05. final float scrolledXFloat = xf + mScrollX;
06. final float scrolledYFloat = yf + mScrollY;
07. final Rect frame = mTempRect;
08. boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
09. if (action == MotionEvent.ACTION_DOWN) {
10. if (mMotionTarget != null) {
11. mMotionTarget = null;
12. }
13. if (disallowIntercept || !onInterceptTouchEvent(ev)) {
14. ev.setAction(MotionEvent.ACTION_DOWN);
15. final int scrolledXInt = (int) scrolledXFloat;
16. final int scrolledYInt = (int) scrolledYFloat;
17. final View[] children = mChildren;
18. final int count = mChildrenCount;
19. for (int i = count - 1; i >= 0; i--) {
20. final View child = children[i];
21. if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE
22. || child.getAnimation() != null) {
23. child.getHitRect(frame);
24. if (frame.contains(scrolledXInt, scrolledYInt)) {
25. final float xc = scrolledXFloat - child.mLeft;
26. final float yc = scrolledYFloat - child.mTop;
27. ev.setLocation(xc, yc);
28. child.mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
29. if (child.dispatchTouchEvent(ev)) {
30. mMotionTarget = child;
31. return true;
32. }
33. }
34. }
35. }
36. }
37. }
38. boolean isUpOrCancel = (action == MotionEvent.ACTION_UP) ||
39. (action == MotionEvent.ACTION_CANCEL);
40. if (isUpOrCancel) {
41. mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT;
42. }
43. final View target = mMotionTarget;
44. if (target == null) {
45. ev.setLocation(xf, yf);
46. if ((mPrivateFlags & CANCEL_NEXT_UP_EVENT) != 0) {
47. ev.setAction(MotionEvent.ACTION_CANCEL);
48. mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
49. }
50. return super.dispatchTouchEvent(ev);
51. }
52. if (!disallowIntercept && onInterceptTouchEvent(ev)) {
53. final float xc = scrolledXFloat - (float) target.mLeft;
54. final float yc = scrolledYFloat - (float) target.mTop;
55. mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
56. ev.setAction(MotionEvent.ACTION_CANCEL);
57. ev.setLocation(xc, yc);
58. if (!target.dispatchTouchEvent(ev)) {
59. }
60. mMotionTarget = null;
61. return true;
62. }
63. if (isUpOrCancel) {
64. mMotionTarget = null;
65. }
66. final float xc = scrolledXFloat - (float) target.mLeft;
67. final float yc = scrolledYFloat - (float) target.mTop;
68. ev.setLocation(xc, yc);
69. if ((target.mPrivateFlags & CANCEL_NEXT_UP_EVENT) != 0) {
70. ev.setAction(MotionEvent.ACTION_CANCEL);
71. target.mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
72. mMotionTarget = null;
73. }
74. return target.dispatchTouchEvent(ev);
75.}
这个方法代码比较长,我们只挑重点看。首先在第13行可以看到一个条件判断,如果disallowIntercept和!onInterceptTouchEvent(ev)两者有一个为true,就会进入到这个条件判断中。disallowIntercept是指是否禁用掉事件拦截的功能,默认是false,也可以通过调用requestDisallowInterceptTouchEvent方法对这个值进行修改。那么当第一个值为false的时候就会完全依赖第二个值来决定是否可以进入到条件判断的内部,第二个值是什么呢?竟然就是对onInterceptTouchEvent方法的返回值取反!也就是说如果我们在onInterceptTouchEvent方法中返回false,就会让第二个值为true,从而进入到条件判断的内部,如果我们在onInterceptTouchEvent方法中返回true,就会让第二个值为false,从而跳出了这个条件判断。这个时候你就可以思考一下了,由于我们刚刚在MyLayout中重写了onInterceptTouchEvent方法,让这个方法返回true,导致所有按钮的点击事件都被屏蔽了,那我们就完全有理由相信,按钮点击事件的处理就是在第13行条件判断的内部进行的!

那我们重点来看下条件判断的内部是怎么实现的。在第19行通过一个for循环,遍历了当前ViewGroup下的所有子View,然后在第24行判断当前遍历的View是不是正在点击的View,如果是的话就会进入到该条件判断的内部,然后在第29行调用了该View的dispatchTouchEvent,之后的流程就和Android事件分发机制(上)中讲解的是一样的了。我们也因此证实了,按钮点击事件的处理确实就是在这里进行的。

然后需要注意一下,调用子View的dispatchTouchEvent后是有返回值的。我们已经知道,如果一个控件是可点击的,那么点击该控件时,dispatchTouchEvent的返回值必定是true。因此会导致第29行的条件判断成立,于是在第31行给ViewGroup的dispatchTouchEvent方法直接返回了true。这样就导致后面的代码无法执行到了,也是印证了我们前面的Demo打印的结果,如果按钮的点击事件得到执行,就会把MyLayout的touch事件拦截掉。

那如果我们点击的不是按钮,而是空白区域呢?这种情况就一定不会在第31行返回true了,而是会继续执行后面的代码。那我们继续往后看,在第44行,如果target等于null,就会进入到该条件判断内部,这里一般情况下target都会是null,因此会在第50行调用super.dispatchTouchEvent(ev)。这句代码会调用到哪里呢?当然是View中的dispatchTouchEvent方法了,因为ViewGroup的父类就是View。之后的处理逻辑又和前面所说的是一样的了,也因此MyLayout中注册的onTouch方法会得到执行。之后的代码在一般情况下是走不到的了,我们也就不再继续往下分析。

再看一下整个ViewGroup事件分发过程的流程图吧,相信可以帮助大家更好地去理解:






现在整个ViewGroup的事件分发流程的分析也就到此结束了,我们最后再来简单梳理一下吧。
 
 Android事件分发是先传递到ViewGroup,再由ViewGroup传递到View的。 在ViewGroup中可以通过onInterceptTouchEvent方法对事件传递进行拦截,onInterceptTouchEvent方法返回true代表不允许事件继续向子View传递,返回false代表不对事件进行拦截,默认返回false。子View中如果将传递的事件消费掉,ViewGroup中将无法接收到任何事件。好了,Android事件分发机制完全解析到此全部结束,结合上下两篇,相信大家对事件分发的理解已经非常深刻了。
  查看全部
记得在前面的文章中,我带大家一起从源码的角度分析了Android中View的事件分发机制,相信阅读过的朋友对View的事件分发已经有比较深刻的理解了。

还未阅读过的朋友,请先参考上文:http://www.imgeek.org/article/51

那么今天我们将继续上次未完成的话题,从源码的角度分析ViewGruop的事件分发。


首先我们来探讨一下,什么是ViewGroup?它和普通的View有什么区别?

顾名思义,ViewGroup就是一组View的集合,它包含很多的子View和子VewGroup,是Android中所有布局的父类或间接父类,像LinearLayout、RelativeLayout等都是继承自ViewGroup的。但ViewGroup实际上也是一个View,只不过比起View,它多了可以包含子View和定义布局参数的功能。ViewGroup继承结构示意图如下所示:

7.png


可以看到,我们平时项目里经常用到的各种布局,全都属于ViewGroup的子类。

简单介绍完了ViewGroup,我们现在通过一个Demo来演示一下Android中VewGroup的事件分发流程吧。


先我们来自定义一个布局,命名为MyLayout,继承自LinearLayout,如下所示:
public class MyLayout extends LinearLayout {  
02.
03. public MyLayout(Context context, AttributeSet attrs) {
04. super(context, attrs);
05. }
06.
07.}
然后,打开主布局文件activity_main.xml,在其中加入我们自定义的布局:

[html] view plaincopy
01.<com.example.viewgrouptouchevent.MyLayout xmlns:android="http://schemas.android.com/apk/res/android"
02. xmlns:tools="http://schemas.android.com/tools"
03. android:id="@+id/my_layout"
04. android:layout_width="match_parent"
05. android:layout_height="match_parent"
06. android:orientation="vertical" >
07.
08. <Button
09. android:id="@+id/button1"
10. android:layout_width="match_parent"
11. android:layout_height="wrap_content"
12. android:text="Button1" />
13.
14. <Button
15. android:id="@+id/button2"
16. android:layout_width="match_parent"
17. android:layout_height="wrap_content"
18. android:text="Button2" />
19.
20.</com.example.viewgrouptouchevent.MyLayout>
可以看到,我们在MyLayout中添加了两个按钮,接着在MainActivity中为这两个按钮和MyLayout都注册了监听事件:
myLayout.setOnTouchListener(new OnTouchListener() {  
02. @Override
03. public boolean onTouch(View v, MotionEvent event) {
04. Log.d("TAG", "myLayout on touch");
05. return false;
06. }
07.});
08.button1.setOnClickListener(new OnClickListener() {
09. @Override
10. public void onClick(View v) {
11. Log.d("TAG", "You clicked button1");
12. }
13.});
14.button2.setOnClickListener(new OnClickListener() {
15. @Override
16. public void onClick(View v) {
17. Log.d("TAG", "You clicked button2");
18. }
19.});
 我们在MyLayout的onTouch方法,和Button1、Button2的onClick方法中都打印了一句话。现在运行一下项目,效果图如下所示:

8.png


分别点击一下Button1、Button2和空白区域,打印结果如下所示:

9.png


你会发现,当点击按钮的时候,MyLayout注册的onTouch方法并不会执行,只有点击空白区域的时候才会执行该方法。你可以先理解成Button的onClick方法将事件消费掉了,因此事件不会再继续向下传递。

那就说明Android中的touch事件是先传递到View,再传递到ViewGroup的?现在下结论还未免过早了,让我们再来做一个实验。

查阅文档可以看到,ViewGroup中有一个onInterceptTouchEvent方法,我们来看一下这个方法的源码:
/** 
02. * Implement this method to intercept all touch screen motion events. This
03. * allows you to watch events as they are dispatched to your children, and
04. * take ownership of the current gesture at any point.
05. *
06. * <p>Using this function takes some care, as it has a fairly complicated
07. * interaction with {@link View#onTouchEvent(MotionEvent)
08. * View.onTouchEvent(MotionEvent)}, and using it requires implementing
09. * that method as well as this one in the correct way. Events will be
10. * received in the following order:
11. *
12. * <ol>
13. * <li> You will receive the down event here.
14. * <li> The down event will be handled either by a child of this view
15. * group, or given to your own onTouchEvent() method to handle; this means
16. * you should implement onTouchEvent() to return true, so you will
17. * continue to see the rest of the gesture (instead of looking for
18. * a parent view to handle it). Also, by returning true from
19. * onTouchEvent(), you will not receive any following
20. * events in onInterceptTouchEvent() and all touch processing must
21. * happen in onTouchEvent() like normal.
22. * <li> For as long as you return false from this function, each following
23. * event (up to and including the final up) will be delivered first here
24. * and then to the target's onTouchEvent().
25. * <li> If you return true from here, you will not receive any
26. * following events: the target view will receive the same event but
27. * with the action {@link MotionEvent#ACTION_CANCEL}, and all further
28. * events will be delivered to your onTouchEvent() method and no longer
29. * appear here.
30. * </ol>
31. *
32. * @param ev The motion event being dispatched down the hierarchy.
33. * @return Return true to steal motion events from the children and have
34. * them dispatched to this ViewGroup through onTouchEvent().
35. * The current target will receive an ACTION_CANCEL event, and no further
36. * messages will be delivered here.
37. */
38.public boolean onInterceptTouchEvent(MotionEvent ev) {
39. return false;
40.}
如果不看源码你还真可能被这注释吓到了,这么长的英文注释看得头都大了。可是源码竟然如此简单!只有一行代码,返回了一个false!好吧,既然是布尔型的返回,那么只有两种可能,我们在MyLayout中重写这个方法,然后返回一个true试试,代码如下所示:
public class MyLayout extends LinearLayout {  
02.
03. public MyLayout(Context context, AttributeSet attrs) {
04. super(context, attrs);
05. }
06.
07. @Override
08. public boolean onInterceptTouchEvent(MotionEvent ev) {
09. return true;
10. }
11.
12.}
现在再次运行项目,然后分别Button1、Button2和空白区域,打印结果如下所示:

10.png

你会发现,不管你点击哪里,永远都只会触发MyLayout的touch事件了,按钮的点击事件完全被屏蔽掉了!这是为什么呢?如果Android中的touch事件是先传递到View,再传递到ViewGroup的,那么MyLayout又怎么可能屏蔽掉Button的点击事件呢?