Glow 技术团队博客

Thoughts, stories and ideas.

重构推送服务

最近对业务里发送 apple APNS, google FCM 部分的代码进行了重构, 抽出了一个单独的 service, 本文记录下过程. 存在的问题我们有好几个 mobile app, 每个 app 会有一套对应的 server 端 service 做业务逻辑, 因为历史原因, 每个 service 里面其实有很多重复代码, 大多只是一些配置和错误处理上有差异. 给 app 发推送是个典型, 原来的做法是当要发推送的时候, 往 python 的 celery 队列里扔一个 task, 由 celery 异步得去发. 有如下问题: celery 性能不佳, worker class 用的是 gevent,

  • Will Xu
android

LiveData基础使用方式+工作原理(上篇)

引入androidx后,ViewModel+LiveData搭配Activity/Fragment渐渐成为大家喜爱(习惯)的UI制作方式。 总体来说,这套模式的容易学习,使用也方便,但如果没有详细了解其背后的工作机制,也很容易错误使用造成bug。 在此将分享相关architecture component背后原理,将实际开发中遇到的问题和错误总结一些good practice points,以供参考。 这篇文章主要探讨LiveData的 工作原理 和 基本使用方式。 How it works: LiveData::setValue VS LiveData::postValueLiveData::observe(lifecycleOwner, observer)Good Practice Points: Activity观察LiveData,在onCreate注册观察,livedata.observe(this, Observer<T>

用 Swift 解读 React/React Native: Part 1 - React Element & React Component

React & React Native 不只是一种框架,它更是一种思维方式和方法论。 Glow 使用 React Native 至今一年半有余,项目里也有越来越多的组件被重构成 React Native。在使用 React Native 开发的过程中,我们对 React 和 React Native 本身的思想、架构也有了越来越深入的理解。而这些思想又开始逐渐反作用到 Native 的开发,影响着我们在其他 Native 组件开发过程中的架构选择和实现思路,促使我们重新审视 Native 的开发方式。 通过这个系列的文章,我们想把从 React 和 React Native 中所学,总结成一些有用的经验,为团队将来无论是 React

  • Allen
    Allen

使用 Apollo Client 快速构建一个支持 GraphQL 的 React App

这篇文章主要介绍 GraphQL 在 Client 的使用,为了方便,本文会直接使用 React 创建一个 Web demo 去介绍 Apollo 在 React 中的使用方法,当然在 ReactNative 中用法几乎一模一样。Apollo Client 是一个 GraphQL Client Library ,Apollo Client (以下简称 Apollo) 可以让我们很方便的去和 GraphQL server 通信。 为什么要使用 GraphQL Client Library 你当然可以自己用 Http 去构造一个 GraphQL 请求,然后自己去处理网络问题,以及数据的缓存问题等等,

  • Ray Pan

从 python2.7 迁移到 python3.6

python2.7 会在 2020 年停止维护, 很多第三方包也在去掉对 python2.7 的支持, 最近终于完成了内部代码向 python3 的迁移, 整个过程挺繁琐的, 记录一下. 总共需要迁移的代码大概有 50w 行(cloc 计算, 去注释空行), 包括业务代码 + ETL + data analysis... 前后花了3个月. 做之前确保已读过官方的 migration guide: https://docs.python.org/3/howto/pyporting.html 我的大致步骤: 清查依赖包, 不支持 python3 的 lib 寻找替代品(常用

  • Will Xu
用 GraphQL 快速搭建服务端 API
GraphQL

用 GraphQL 快速搭建服务端 API

(题图来源:https://nerdist.com/canadians-spock-their-fives-in-honor-of-leonard-nimoy/) Glow 从今年 4 月开始为中国的产品「共乐孕」app 的用户开发社区功能,虽然在之前美国的社区的类似的功能都进行过实现,但我们仍然决定要在这次中国的社区产品开发中尝试一些新东西。其中就包括 GraphQL 。 今天的文章中会简单介绍下 GraphQL 和我们在服务器端使用的第三方库-- Graphene-Python, 以及我们选择这个技术的原因。并通过一些简单的例子展现如何快速上手 GraphQL 。 GraphQL 的介绍 什么是 GraphQL 简单来说,GraphQL 是一种查询语言,

react-native

如何自动化测试 React Native 项目 (下篇) - 单元测试

原创发布于 tech.glowing.com。 接着上篇的内容, 这篇文章会详细的介绍在 Glow 我们如何写单元测试, 以及在 React Native 中各个模块单元测试的详细实现方式。 单元测试工具 - Jest & Enzyme   Jest - Facebook Jest 是 Facebook 开源的 Javascript 测试框架,提供了许多好用的 API,先介绍下主要的优点: 自带 snapshot 测试,让UI测试简单有效 几乎 0 配置,自带各种功能。 相比其他单元测试:karma (test runner) + mocha (test framework)

react-native

如何自动化测试 React Native 项目 (上篇) - 核心思想与E2E自动化

原创发布于 tech.glowing.com。 React Native (RN) 是 Facebook 开源的跨平台应用开发框架,由于 RN 提供的高效直观的跨平台开发模式和不错的性能,我们在开发 Glow 的中文 App - 共乐孕的时候选择了以 RN 为主要框架进行开发。 随着开发模式的逐渐成熟,对RN项目的自动化测试也在不断探索中慢慢完善, 最终选择了 Detox (by Wix) 做 E2E 自动化测试, Jest (FaceBook) + Enzyme (Airbnb) 做集成测试和单元测试。 在这篇文章中我会介绍一下我对 React Native 项目自动化测试的核心想法以及自动化测试中 E2E 部分的具体实现。在 如何自动化测试 React

在线查询系统性能优化

背景 在最近的一个项目是一个后台管理工具,WEB端需要根据后端录入的数据,显示一个庞大的表格。主要的几点需求如下: 每条记录包含多个字段,都需要显示在WEB端界面上 其中有些字段并不能通过数据库查询直接得出,需要另外计算得出 支持设置过滤条件和按字段排序 需求变化很快,字段可能随时调整 对此,后端为了整体解决,会把查询得到的所有记录都合并到一起作计算,得到包含所有字段的完整数据。有了完整的数据,之后的过滤和排序就相对容易实现了。 问题 这种设计在项目初期的确对快速变化的需求表现出了良好的应变能力。然而随着数据量的增加,该方案也出现了明显的性能问题,经分析发现主要的问题出在以下几个方面: 随着数据量增加,对所有记录做计算越来越耗时 因为数据量的关系,从数据库服务器取出记录的过程本身也很耗时 解决这两个问题的根本都是是减少数据量。很明显,不符合过滤条件的记录没有必要传输到后端服务器上,也没有必要做字段计算。如果可以提前得到甚至缩小符合过滤条件的记录ID,可以大大加速整个过程。 索引表 针对前端特殊的展示需求(一张大表格),一个直观的解决方案是扁平化所有的数据。为此我们新建了一张索引表SearchTable,将每条记录的相应字段预先计算并填入。数据表结构如下: 索引表中的每一行对应一条记录的字段及其取值,其中type标识了该行字段名称,value则是对应的值。 这样过滤条件可以转化为类似如下的查询语句,

  • Bood
    Bood

Glow data infrastructure 的演化

Glow 一向是一个 data driven 做决策的公司,稳定高效的平台是必不可少的支撑, 本文总结几年里公司 data infrastructure 的演进过程. 结合业务特点做技术选型和实现时候的几个原则: real time 分析的需求不高,时间 delta 控制在1 小时以内可接受 . 支持快速的交互式查询. 底层平台尽量选择 AWS 托管服务, 减少维护成本. 遇到故障, 数据可以 delay 但不能丢. 可回溯历史数据. 成本可控. 用到的 AWS 服务: 数据存储和查询: S3, Redshift (spectrum), Athena ETL: DMS, EMR, Kinesis, Firehose, Lambda 开源软件:

  • Will Xu
data-visualization

数据可视化的开源方案: Superset vs Redash vs Metabase (二)

在上篇结尾处我提到“如果现在让我重新选择,我会使用哪个可视化工具?”我的答案是 Redash,原因主要不是功能层面,而是技术层面。本篇就从项目关注度与活跃度,项目的技术架构,源代码的规模与质量,这三个方面来比较一下 Superset,Redash 与 Metabase。 关注度与活跃度 看一个项目在 Github 上的星数,是评判一个项目成熟度最快速的方法。**那除了星数以外,项目的 Github 页面上还有什么重要信息呢?这里我建议大家去看一看项目的 Insights。**首先我们来看 Superset 最近一个月的活跃度 这张图告诉我们以下几个信息 这个项目最近一个月有 53 个提交,说明项目仍在积极开发中。图中显示项目在最近一个月有新增 21 万行代码,这主要是因为提交了一个巨大的地理数据文件,去掉这个文件之后,实际新增的代码行数大约为 2000 行。 从新增和处理的 Issue

react-native

如何实现 React Native 里的页面导航系统

React Native 中的页面导航和跳转一直是一个让人头疼的问题,其实社区里也已经有各种实现,比如 react-navigation,wix/react-native-navigation,LeoLeBras/react-router-navigation,airbnb/native-navigation,如你所见,react native navigation 三个单词各种排列组合基本上都有了,所以从这些 library 里挑一个合适的同样更让人头疼。 我们在新起的项目中决定用纯 React Native 实现,以尽量减少对 native 的依赖,并且避免因 hybrid app 中 native 页面的层次结构(iOS 中 view controllers,Android 中 activities)在 React 侧不可知、不可控带来的状态管理问题。

  • Allen
    Allen
data-visualization

数据可视化的开源方案: Superset vs Redash vs Metabase (一)

人是视觉动物,要用数据把一个故事讲活,图表是必不可少的。如果你经常看到做数据分析同事,在SQL客户端里执行完查询,把结果复制/粘贴到Excel里再做成图表,那说明你的公司缺少一个可靠的数据可视化平台。数据可视化是Business Intelligence(简称BI)中的核心功能,有许多成熟的商用解决方案,如老牌的Tableau, Qilk,新生代的Looker,国内的FineBI等等。不过对于许多小公司来说,这些服务的License费用是一笔不小的开销,且有一种“杀鸡用牛刀”的感觉。那在开源软件如此发达的今天,在数据可视化方面,有什么靠谱的方案可以选择呢?今天给大家介绍三个比较知名的项目,分别是Superset, Redash和Metabase。前两个我都在产生环境中实际使用过,在本文中会重点介绍。Metabase我只是试玩了一下,但我觉得这是一个非常有想法的项目,所以也会和大家聊聊我对它的看法。 选择一个称手的工具,功能上能满足我的需求肯定是首要的。就先从功能需求讲起,我们的数据仓库用的是Amazon Redshift(如果你没听过Redshift,就把它看作是为大数据优化过的PostgreSQL),所以大部分的实际用例都是要将一个SQL查询的结果可视化。我们所需的图表类型也就是常用的那几种,包括折线图,柱形图,

DynamoDB

DynamoDB 是 AWS 的托管 NoSQL 数据库,可以当作简单的 KV 数据库使用,也可以作为文档数据库使用. Data model 组织数据的单位是 table, 每张 table 必须设置 primary key, 可以设置可选的 sort key 来做索引. 每条数据记作一个 item, 每个 item 含有一个或多个 attribute, 其中必须包括 primary key. attribute 对应的 value 支持以下几种类型: Number, 由于 DynamoDB 的传输协议是 http + json, 为了跨语言的兼容性, number

  • Will Xu

使用 Redshift Spectrum 查询 S3 数据

通常使用 redshift 做数据仓库的时候要做大量的 ETL 工作,一般流程是把各种来源的数据捣鼓捣鼓丢到 S3 上去,再从 S3 倒腾进 redshift. 如果你有大量的历史数据要导进 redshift,这个过程就会很痛苦,redshift 对一次倒入大量数据并不友好,你要分批来做。 今年4月的时候, redshift 发布了一个新功能 spectrum, 可以从 redshift 里直接查询 s3 上的结构化数据。最近把部分数据仓库直接迁移到了 spectrum, 正好来讲讲。 动机 Glow 的数据仓库建在 redshift 上, 又分成了两个集群,一个 ssd 的集群存放最近 4 个月的数据,供产品分析,metrics report,

  • Will Xu
python

Python web 应用性能调优

为了快速上线,早期很多代码基本是怎么方便怎么来,这样就留下了很多隐患,性能也不是很理想,python 因为 GIL 的原因,在性能上有天然劣势,即使用了 gevent/eventlet 这种协程方案,也很容易因为耗时的 CPU 操作阻塞住整个进程。前阵子对基础代码做了些重构,效果显著,记录一些。 设定目标: 性能提高了,最直接的效果当然是能用更少的机器处理相同流量,目标是关闭 20% 的 stateless webserver. 尽量在框架代码上做改动,不动业务逻辑代码。 低风险 (历史经验告诉我们,动态一时爽,重构火葬场....) 治标 常见场景是大家开开心心做完一个 feature, sandbox 测试也没啥问题,上线了,结果 server load 飙升,各种

  • Will Xu
android

在 Android 中集成 React Native 的经验分享

在之前的一篇博客中,Allen已经为大家介绍了React Native在Glow的应用以及大体架构。由于React Native库本身的一些原因,其在Android的成熟度远不及iOS,因此也给在Android的应用带来了更多的挑战。 在本文中,给大家分享一下在Android平台上集成React Native的过程中碰到的一些问题和解决办法。 64位支持 目前React Native的二进制库还不支持64位,而Android并不支持32位和64位二进制库的混合加载(详见Mixing 32- and 64-bit Dependencies in Android)。 因此如果应用中已经包含了64位的二进制库,必须用abiFilters去掉64位二进制库。 ndk { abiFilters "armeabi", "mips", "armeabi-v7a", "x86" } React Native社区也在努力解决这一问题(React Native for Android is

  • Bood
    Bood

React Native 在 Glow 的实践

1. 为什么使用 React Native 在最近发布的 Eve v2.8 里,我们用 React Native 重构了几乎整个 Community。本文记录了 React Native 在 Glow 的实践经验,并主要从 iOS 角度展开一些细节实现。但本文不会涉及太多 React Native 的入门知识,如果你还没有接触过 React Native,推荐先阅读官方文档和 React Native Express。 使用 React Native 主要原因: 在 JSPatch 和 Rollout.io 被

  • Allen
    Allen
python

Python profiling

Profiling(性能调试)是我一直很感兴趣的一个话题,之前给大家介绍过Datadog这个工具,今天我们来看看Python语言中有哪些方法来做Profiling。 Poorman's Profiler 最基础的就是使用time.time()来计时,这个方法简单有效,也许所有写过Python代码的人都用过。我们可以创建一个decorator使它用起来更方便。 import time import logging import functools def simple_profiling(func): @wraps.functools(func) def wrapped(*args, **kwargs): start_time = time.time() result = func(*args, **kwargs) time_spent = time.time() - start_

swift

Swift 3

Swift 3 正式发布已经 3 周了,大家 Swift 项目的代码迁移做的怎么样?Glow Baby 项目我花了近 3 天时间,12956 行增改,9817 行删减,360 个文件。迁移的过程是痛苦的,心很累,Xcode 8 的迁移工具也没有让我轻松多少。 不过待迁移完毕后,Swift 3 读起来、写起来都更舒服。Swift 1 确立了语言的基线:安全、快速、现代。Swift 2 展现了 Swift 应该是什么,未来怎么走:面向协议的编程、开源。而

  • 顾 鹏
    顾 鹏
android

谈谈移动应用的安全性实践

作为一家大数据公司,Glow不仅重视用户的数据,更加注重数据的安全性。 本文将从用户注册流程出发,逐步介绍我们在提高数据安全性方面采用的一些策略方法,供读者参考。下面将从 Android 和 服务端 两部分来进行讲解。 从注册说起 用户第一次打开app时便会进入注册页面,然后客户端会要求用户输入用户名、密码并传递给服务端去创建一个新的user。此时若通过明文传递用户名密码便是一个安全性隐患。或者说,如果有人监听注册API,那么很快就可以窃取到很多用户的账户数据,而且可以偷偷利用这些账户信息随时获取甚至更改用户数据。 这对于任何一家企业而言都是非常可怕的。 全站Https 因此,为了应对数据明文传输隐患这个问题,我们在自家所有app中都采用了Https方式通信。在Android端我们采用了Square家的OkHttp3作为网络层,为应用层提供Https服务。 下面先对Https的基本工作原理进行下介绍,以便后文的讲解。 首先,客户端去请求服务端的数字证书,这个证书包含了一个公钥。该证书购买后存储于我们自己服务器上。 当服务端收到客户端请求后,会把这个数字证书回传给客户端,由于是公钥,所以不害怕被窃取。 客户端收到数字证书后,先去验证证书的真实性。如果验证通过,就会从里面取出一个公钥。 客户端本地生成一个随机数,作为未来的会话私钥,利用前面的公钥进行加密。

android

Android里巧妙实现缓存

为了快速查询会被多次调用的数据,或者构建比较废时的实例,我们一般使用缓存的方法。缓存的基本概念大体上差不多,这里就不再重复,有兴趣的可以查看维基百科的介绍。 缓存有很多的实现方式,技巧性还有坑都很多,今天我给大家介绍一些非通用的方法,可以巧妙地帮大家简单实现一些内存缓存。 Supplier和Memoize SQLite是Android里常用的一种数据存储方式,在访问数据库数据时需要通过SQLiteOpenHelper。 一份好的数据库连接代码应该能解决以下几个问题: a) 构建实例比较费资源 b) 数据库连接最好能复用 c) onUpdate等方法在执行时不能和其他实例构成冲突。 这里可以很简单的这样写 Suppliers.memoize(new Supplier<SQLiteOpenHelper>() { @Override public SQLiteOpenHelper get() { return new ...; } }) 这段代码利用了Guava提供的一些辅助方法实现Supplier和Memoize和逻辑。顾名思义,Supplier一般被用作factory,generator,builder,closure。Memoize类似于缓存这种概念,它一旦生成了一个实例,在以后的调用中都会返回同一实例,而且,

  • 刘聪
    刘聪