逃离大厦142关27关怎么过

来这里找志同道合的小伙伴!正文这是写给开发同学系列文档中的一篇,主要讲单元测试。写这个系列的原因是发现开发同学,尤其是偏业务的开发同学对于软件开发中的很多实践和理论理解的不够清楚。比如设计文档,代码评审,单元测试,集成测试和自动化测试,持续集成和持续发布这样一些耳熟能详的概念,说起来每个开发同学都听过,但很多人并没有深入考虑过为什么要引入这些实践,实践需要哪些手段,要达到什么目的,要坚持什么原则?所以这些实践落地的过程也是千差万别,效果往往也不甚理想。通过这一系列文档,我会把我所了解的每个实践的来源、适用范围和价值用最简明的方式写出来,并结合具体的开发环境提供一些具体的操作手段,帮助同学们按照正确的路径快速了解和上手。1 &理论基础大数据就像青少年谈性,每个人都在说,但不知道谁做了。每个人认为另外人在做,所以每个人都声称自己在做。这是大数据火的时候调侃大数据的段子,套在单元测试上也一样适用。说起来单元测试是开发应该了解的基础概念,然而实际并非如此。我在若干团队(不限于淘宝)作过以下的调查,结果基本类似:有多少人写过单元测试? 60% ~ 80%,视团队而定每个单元测试里面都有至少一个assert语句,而非使用System.out.println? 20% ~ 30%单元测试的行覆盖率超过50%? & 10%每个单元测试平均每天会被执行10次以上? & 5%所有单元测试**一定不会因为断网失败**? & 1%大多数开发都认为自己写了单元测试,但大家写的&单元测试&都不相同。实际上,能达到最后一点要求的单元测试才是有价值的单元测试,其它所谓的&单元测试&最多只能算是&测试代码&甚至&代码片段&。&单元测试&和&测试代码&的区别就像钻石和煤炭,虽然都由碳元素(程序代码)构成,但前者价值远远大于后者。随着时间的流逝,&钻石恒久远,一颗永流传&,而煤炭只会被烧掉,变成二氧化碳;同样,随着项目的不断演进,&单元测试&能一直存在并发挥价值,而&测试代码&只会被一行行注释掉,直到某个接手的同学把一个全被注释掉的测试文件从项目中删除。要理解这一切发生的原因,首先我们需要了解软件开发中的几个定律:错误率恒定定律程序员的错误产出比是个常数对某一个程序员来说,实现相同功能会犯的错误(BUG)是固定的,不受程序员自身意愿影响,不受绩效影响,也不受项目紧急程度影响。不考虑程序员水平的成长,错误产出比在很长一段时间(每个项目的间隔)内可以认为是个常数。这个定律告诉我们,如果一个程序员感觉今天状态很好,比昨天多写了一倍代码并向QA声称bug数肯定比昨天还少,而QA测试的结果居然真的如此,那很大可能是QA测的不够仔细,而不是程序员的代码水平一夜之间突飞猛进。这个定律还告诉我们,TL开会时要求程序员写代码尽量不要犯错没有任何意义,这种要求就像要求程序员明天长高5公分一样,不具有可操作性。错误率恒定定律决定了错误数是一定的,但并不意味着这些错误产生的影响是一定的。恰恰相反,不同开发方式中,这些错误带来的影响差别非常巨大。菜鸟和老手完成相同功能发生的错误可能只差5倍,在具体项目实践中带来的影响却可能差了20倍、50倍甚至更多。原因就是以下的规模代价平方律:规模代价平方定律定位并修复一个BUG所需的代价正比于目标代码规模的平方如果一个20行的函数刚写完时作者就能发现有BUG,找到并修复这个BUG可能只需要1分钟,并且不担心影响其它使用者。如果是在200行的一个类中,别人调用时发现有BUG,阅读代码并定位问题可能就需要一个小时,对这个问题的修复重新代码评审又要花一个小时。如果在系统和系统联调的时候才发现这个问题,前面扯皮就要半天,改完了重新回归又是半天。如果改这个BUG的人已经不是原作者的话,往往担心改了这个BUG又引入其它问题,于是修改方案就要拖一群人讨论半天,最终改完了要求QA作大范围的回归,结果还是还不放心。规模代价平方律是很多软件工程实践的核心思想。根据平方律,为了减少错误修复的成本,要尽可能早的发现错误,在尽量小的范围内定位并修复错误。由于这是一个平方律而非线性率,所有这方面的努力都是非常划算的。比如以下实践很大程度上就是为了尽早发现错误,以后有机会我再逐一介绍这些实践。设计评审代码评审单元测试自动化测试结对编程(Scrum)小迭代,迭代后期的成果演示规模代价平方律对程序员的重要性可以和牛顿三定律在初等物理中的地位媲美&。遗憾的是很多程序员写了很多年都不知道这个定律律,往往低估了错误修复的时间。所以业界对程序员的自我评估有如下经典的吐槽。当一个程序员宣称他已经完成了90%的工作时,他的意思是还需要相同的时间来完成剩下10%的工作。2单元测试的目的错误率恒定律告诉我们错误是不可避免的,而规模代价平方律告诉我们要尽早发现错误。单元测试作为一个行之有效的工程实践,目的只有一个:单元测试的目的是尽早在尽量小的范围内暴露错误不同项目的单元测试方案各有不同,各种方案的选型往往也会有争议。这时候一定要记住单元测试的目的。凡是利于此目的,即使复杂一些的方案或有一定学习成本也可以采用,凡是不利于此目的的方案,即使看起来很美也没有采用的必要(本文最后有几个单测的误区具体说明这点)。3单测的要求为了达到&尽早&和&尽量小的范围&以及&暴露错误,对单测有以下要求。 实践证明,只有满足这些要求的单测才能实现单测的目的。单测要能报错有些同学不喜欢用Assert,而喜欢在test case中写个System.out.println,人肉观察一下结果,确定结果是否正确。这种写法根本不是单测,原因是即使当时被测试代码是正确的,后续这些代码还有可能被修改,而一旦这些代码被改错了。println根本不会报错,测试正常通过只会带来虚假的自信心,这种所谓的&单测&连暴露错误的作用都起不到,根本就不应该存在。单测要有强度有些同学写的测试里面会有Assert,但用的很少,往往只是在最后用一个assertNotNull(result),这样的测试强度是不够的。举个例子,假设有以下的待测方法:&public class User{& & & & & & && & & & & & & public S& & & & }& & & & //待测试的方法,位于UserDAO中& & & & /**& & & & * 根据用户名模糊查找用户,双向模糊& & & & **/& & & & public List&User& findUserByFuzzyName(String fuzzyName){& & & & & & & //实现& & & & }以下的测试用例强度就太差了,这个用例虽然也用了Assert,但对测试的结果校验很弱,即没有校验结果中有多少User,也没有校验双向模糊逻辑是否正确实现了。实际上即使查询结果是空,返回的也是个empty list,测试用例还是不会报错。&// 数据准备,假设测试库中已经有了 tom tommy jerry 三个用户& & & & @Test& & & & public void testFindUserByFuzzyName(){& & & & & & List&User& users= userDAO.findUserByFuzzyName(&tom&);& & & & & & Assert.assertNotNull(users);& & & & }单测要能反应函数的明确需求才算有强度。这样以后函数的实现一旦被改错了单测才能尽快报错,针对以上这个例子,单测至少要达到以下强度:// 数据准备,假设测试库中已经有了 tom tommy jerry 三个用户& & & & @Test& & & & public void testFindUserByFuzzyName(){& & & & & & //左模糊& & & & & & List&User& users= userDAO.findUserByFuzzyName(&tom&);& & & & & & Assert.assertEquals(2,users.size());& & & & & & Assert.assertEquals(&tom&, users.get(0).name);& & & & & & Assert.assertEquals(&tommy&, users.get(1).name);& & & & & & //右模糊& & & & & & List&User& users= userDAO.findUserByFuzzyName(&y&);& & & & & & Assert.assertEquals(2,users.size());& & & & & & Assert.assertEquals(&tommy&, users.get(0).name);& & & & & & Assert.assertEquals(&jerry&, users.get(1).name);& & & & }单测要有覆盖度强度是指单元测试中对结果的验证要全面,覆盖度则是指测试用例本身的设计要覆盖被测试程序(SUT, Sysem Under Test)尽可能多的逻辑。只有覆盖度和强度都比较高才能较好的实现单测的目的。按照测试理论,SUT的覆盖度分为方法覆盖度,行覆盖度,分支覆盖度和组合分支覆盖度几类。不同的系统对单测覆盖度的要求不尽相同,但这是有底线的。一般来说,程序配套的单测至少要达到&80%的方法覆盖以及&60%的行覆盖,才能起到&看门狗&的作用,也才是有维护价值的单测。等价类划分可以帮助我们用更少的测试代码写出更高覆盖度的单测。单元测试是典型的白盒测试,等价类的划分以及单元测试的编写最好都由SUT的编写者自己去完成,这样整体效率最高。单测粒度要小和集成测试不同,单元测试的粒度一定要小,只有粒度小才能在出错时尽快定位到出错的地点。单测的粒度最大是类,一般是方法。**单测不负责检查跨类或者跨系统的交互逻辑** , 那都是集成测试的范围。通俗的说,程序员写单测的目的是&擦好自己的屁股&,把自己的代码从实现中隔离出来,在集成测试前先保证自己的代码没有逻辑问题。至于集成测试乃至其它测试中暴露出来的接口理解不一致或者性能问题,那都不在单元测试的范围内。单测要稳定单元测试通常会被放到持续集成(CI)中,每次有代码check in时单元测试都会被执行。如果单测依赖有对外部环境(网络、服务、中间件)的依赖,任何一次网络抖动或者返回的变化都会造成单测失败进而造成持续集成的失败。这会造成整个持续集成有大量误报,进而导致持续集成机制的不可用。所以单测不能受到外界环境的影响。为了不受外界环境影响,要求设计代码时就把SUT的依赖改成注入,在测试时用spring或者guice这样的DI框架注入一个本地(内存)实现或者Mock实现。用这种方法保证在SUT出错时单测才会报错,持续集成才能更稳定,单测的失败也才更重要。单测速度要快作为&看门狗&,最好是在每次代码有修改时都运行单元测试,这样才能尽快的发现问题。这就要求单元测试的运行一定要快。一般要求单个测试的运行时间不超过3秒,而整个项目的单测时间控制在3分钟之内,这样才能在持续集成中尽快暴露问题。单测不仅仅是给持续集成跑的,跑测试更多的是程序员本身,单测速度和程序员跑单测的意愿成反比,如果单测只要5秒,程序员会经常跑单测,去享受一下全绿灯的满足感,可如果单测要跑5分钟,能在提交前跑一下单测就不错了。实际上,上一条要求将单测的外部依赖全部改成本地实现或者Mock,除了系统稳定性外,执行速度也是考量之一。改成本地实现或者Mock后,绝大多数单测运行的时间都非常快,基本上可以说是瞬间就能跑完。4单元测试的方案明确了单测的目标之后,单测方案的选型也比较明确了。原则就是本地化和快,选型上也尽量以内存方案为主。下面我们以Spring boot开发为例,给出一套解决方案,以下代码都是以Spring Annotation Configuration给出的,如果有必要也可以换成XML。数据库测试数据库测试多用在DAO中,DAO对数据库的操作依赖于mybatis的sql mapper 文件,这些sql mapper多是手工写的,在单测中验证所有sql mapper的正确性非常重要,在DAO层有足够的覆盖度和强度后,Service层的单测才能仅仅关注自身的业务逻辑。为了验证sql mapper,我们需要一个能实际运行的数据库。为了提高速度和减少依赖,可以使用内存数据库。内存数据库和目标数据库(MySQL,TDDL)在具体函数上有微小差别,不过只要使用标准的SQL 92,两者都是兼容的。下面的方案中就使用H2&作为单测数据库。数据库单测方案需要解决3个问题:Schema的初始化和同步每个测试完成后的数据清除调试过程查看数据库内容下面的方案中对这3个问题都给出了方法在pom中引入H2的依赖&dependency&& & &groupId&com.h2database&/groupId&& & &artifactId&h2&/artifactId&& & &version&1.4.190&/version&& & &scope&test&/scope&&/dependency&在测试资源目录 src/test/resource 下新建 your_module.sql,其中的内容是需要初始化的建表语句,这些建表语句可以从idb中导出。如果表结构发生了更改,需要人工重新导出。create table something(& & id bigint unsigned &not null auto_increment comment '主键',& & gmt_create datetime &not null comment '创建时间',& & gmt_modified datetime &not null comment '修改时间',& & primary key (id)) &comment='something';创建DAO接口,注意这里不用写实现。只要按照一定的规范,可以动态生成所有DAO的实现,自动映射到相应的sql mapper中:package com.taobao.daren.service.qualification.server.domain.import com.taobao.daren.service.qualification.server.domain.entity.HSFDataSourceM/**&* @author lotus.jzx&*/public interface HSFDataSourceMetaDao {& & /**& & &* 生成一个新的数据源元信息& & &*& & &* @param name & &名称& & &* @param group & HSF组别& & &* @param version HSF版本& & &*& & &* @return ID& & &*/& & Long insertHSFDataSourceMeta(String name, String group, String version);}在程序的资源目录src/main/resources/sqlmapper中放置对应的sqlmapper文件,文件名最好和DAO对应,以便人工查找,比如这里对应的sqlmapper就叫HSFDataSourceMetaDao.xml。注意!为了实现自动映射,&mapper的namespace一定要和DAO的类名相同。&?xml version=&1.0& encoding=&UTF-8& ?&&!DOCTYPE mapper PUBLIC &-//mybatis.org//DTD Mapper 3.0//EN& &http://mybatis.org/dtd/mybatis-3-mapper.dtd& &&mapper namespace=&com.taobao.daren.service.qualification.server.domain.dao.HSFDataSourceMetaDao&&&resultMap id=&HSFDataSourceMetaResultMap&& & & & & &type=&com.taobao.daren.service.qualification.server.domain.entity.HSFDataSourceMeta&&& & &id column=&id& property=&id&/&& & &result column=&gmt_create& property=&gmtCreate&/&& & &result column=&gmt_modified& property=&gmtModified&/&& & &result column=&name& property=&name&/&& & &result column=&is_active& property=&active&/&& & &result column=&service_group& property=&group&/&& & &result column=&service_version& property=&version&/&&/resultMap&&select id=&findHSFDataSourceMetaById& parameterType=&Long& resultMap=&HSFDataSourceMetaResultMap&&& & select& & id,& & name,& & gmt_create,& & gmt_modified,& & service_group,& & service_version,& & is_active& & from daren_qualification_hsf_datasource_meta& & where id=#{id}&/select&&/mapper&在测试目录 src/test/java/com/taobao/.../your_module/config 下新建测试配置;@Configuration@ComponentScan({&com.taobao.your_modle&})public class BaseTestBeanConfig{@Bean(name = QualificationBeanConfig.QUALIFICATION_DATASOURCE)public DataSource dataSource() {& & EmbeddedDatabaseBuilder databaseBuilder = new EmbeddedDatabaseBuilder();& & EmbeddedDatabase db = databaseBuilder& & & & & & .setType(EmbeddedDatabaseType.H2)& & & & & & & & & & //启动时初始化建表语句& & & & & & .addScript(&classpath:schema/qualification.sql&)& & & & & & .build();& &}&@Bean(name = &h2WebServer&, initMethod = &start&, destroyMethod = &stop&)//启动一个H2的web server, 调试时可以通过localhost:8082访问到H2的内容//JDBC URL: jdbc:h2:mem:testdb//User Name: sa//Password: 无//注意如果使用断点,断点类型(Suspend Type)一定要设置成Thread而不能是All,否则web server无法正常访问!public Server server() throws Exception {& & //在8082端口上启动一个web server& & Server server = Server.createWebServer(&-web&, &-webAllowOthers&, &-webDaemon&, &-webPort&, &8082&);& &}@Bean(name = QualificationBeanConfig.QUALIFICATION_SQL_SESSION_FACTORY_BEAN)public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {& & final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();& & sessionFactory.setDataSource(dataSource);& & PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();& & //加载所有的sqlmapper文件& & Resource[] mapperLocations = resolver.getResources(&classpath*:sqlmapper/**/*.xml&);& & sessionFactory.setMapperLocations(mapperLocations);& & return sessionFactory.getObject();}@Bean(name = QualificationBeanConfig.QUALIFICATION_MAPPER_SCANNER_CONFIGURER)public MapperScannerConfigurer mapperScannerConfigurer() {& & //只需要写DAO接口,不用写实现类,运行时动态生成代理& & MapperScannerConfigurer configurer = new MapperScannerConfigurer();& & configurer.setBasePackage(&com.taobao.daren.service.qualification.server.domain.dao&);& & configurer.setSqlSessionFactoryBeanName(QualificationBeanConfig.QUALIFICATION_SQL_SESSION_FACTORY_BEAN);& &}}写一个数据库单测的基类,后续的数据库单测继承这个基类即可;@RunWith(SpringJUnit4ClassRunner.class)@SpringApplicationConfiguration(BaseTestBeanConfig.class)//每次跑完测试方法后清空数据库@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)public abstract class BaseTest {& & @Autowired& & protected DataSource dataS& & /**& & &* Execute SQL directly, these SQL may be for test purpose only and should not be included in mybatis sqlMapper& & &* configuration files.& & &*& & &* @param sql SQL statement to execute, variable binding is NOT supported for simplicity.& & &*/& & protected void execute(String sql) {& & & & try {& & & & & & dataSource.getConnection().createStatement().execute(sql);& & & & } catch (SQLException e) {& & & & & & throw new RuntimeException(e);& & & & }& & }}然后就可以写数据库单测了;/*** @author lotus.jzx*/public class QualificationDaoTest extends BaseTest {@Autowiredprivate QualificationDao qualificationD@Testpublic void testFindQualificationItemMetaById() {& & String sql = &insert into daren_qualification(&& & & & & & + &id&& & & & & & + &,gmt_create&& & & & & & + &,gmt_modified&& & & & & & + &,root_item_id&& & & & & & + &)&& & & & & & + & values (&& & & & & & + &1&& & & & & & + &,NOW()&& & & & & & + &,NOW()&& & & & & & + &,10&& & & & & & + &)&;& & execute(sql);& & Assert.assertNull(qualificationDao.findQualificationById(-1L));& & Qualification qualification = qualificationDao.findQualificationById(1L);& & Assert.assertEquals(1, qualification.getId().intValue());& & Assert.assertNotNull(qualification.getGmtCreate());& & Assert.assertNotNull(qualification.getGmtModified());& & Assert.assertEquals(10, qualification.getRootId().intValue());& & Assert.assertNull(qualification.getRoot());}}到此为止搭建了一整套基于H2的数据库单测方案。这套方案基于内存,没有对外部的依赖,可以在单机上飞快的跑完 mvn clean test。对于前文提到的三个问题,这个方案是这么解决的:1、Schema的初始化和同步通过离线的方式人工同步Schema至src/test/resources/sqlmapper目录。这步目前还不够自动化。如果idb能开放接口,这个步骤也可以通过脚本一键完成,当然目前还是比较人肉的。2、每个测试完成后的数据清除在BaseTest中@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)这行会自动完成数据清除,写test case时可以认为表都是空的。而且我们采用的是内存表,非持久化,所以不存在持久化数据对后续单测的影响3、调试过程查看数据库内容在测试配置中有一个h2WebServer,在测试用例运行的过程,可以访问本地server,通过H2 web console用如下配置查看数据库中的数据。JDBC URL: jdbc:h2:mem:testdbUser Name: saPassword: 无(ps:要注意的是,如果在测试用例中加了断点,一定要把断点类型从缺省的&All&改成为“Thread”,否则H2 web console会被阻塞。)其它外部依赖对于除数据库以外的依赖,包括Tair, Diamond,Nofity等中间件以及外部的HSF/HTTP服务,在单测中全部采用Mock进行解耦。具体的Mock框架采用 easymock,主要是考虑到它的语法相对自然,同时支持对class的mock。是否使用mock的争议一直很大,反对者认为mock要额外写很多代码,同时mock通过并不能保证线上工作正常,而支持者认为mock速度快并且稳定,这就是最大的作用。而我们觉得在单元测试中mock外部依赖还是合理的。一方面单元测试的目的是&擦好自己的屁股&,对接口的理解错误应该在(自动化)集成测试而不是单元测试中去检测,另一方面mock的使用范围仅仅是边界上的外部依赖,其使用还是可控的。下面以一个例子说明如何用easymock写单元测试这是需要测试的代码package com.jinlo.springbootdemo.import java.util.Limport org.springframework.beans.factory.annotation.A/**&* 根据黑名单和白名单确认用户是否能访问&*/public class AccessControlService {& & private UICService UICS& & private BlackListProvider blackListP& & private WhiteListProvider whiteListP& & @Autowired& & public void setUICService(UICService UICService) {& & & & this.UICService = UICS& & }& & @Autowired& & public void setBlackListProvider(BlackListProvider blackListProvider) {& & & & this.blackListProvider = blackListP& & }& & @Autowired& & public void setWhiteListProvider(WhiteListProvider whiteListProvider) {& & & & this.whiteListProvider = whiteListP& & }& & /**& & &* 返回指定用户是否能够访问& & &* @param userId 用户ID& & &*& & &* @return& & &*/& & public boolean canAccess(Long userId) {& & & & List&Long& whiteListProviderList = whiteListProvider.provideUserIdWhiteList();& & & & if (whiteListProviderList.contains(userId)) {& & & & & && & & & } else {& & & & & & return !blackListProvider.provideUserNameBlackList().contains(UICService.findNameById(userId));& & & & }& & }}其中UICSerive定义如下,这是一个HSF的远程服务public interface UICService {& & /**& & &* 查找ID对应的名称& & &* @param id& & &* @return& & &*/& & String findNameById(Long id);}黑名单提供者有一个本地实现/**&* 黑名单提供者&*/public interface BlackListProvider {& & /**& & &* 提供黑名单& & &* @return& & &*/& & List&String& provideUserNameBlackList();}/**&* BlackListProvider的一个本地实现&*/public class LocalBlackListProvider implements BlackListProvider {& & private List&String& blackL& & public LocalBlackListProvider(List&String& blackList) {& & & & this.blackList = new ArrayList&&(blackList);& & }& & @Override& & public List&String& provideUserNameBlackList() {& & & & return Collections.unmodifiableList(blackList);& & }}白名单则需要通过HSF远程获取/**&* 白名单提供者&*/public interface WhiteListProvider {& & /**& & &* 提供白名单ID& & &* @return& & &*/& & List&Long& provideUserIdWhiteList();}由于代码中有两个对外部服务的依赖,想在实际环境中去验证canAccess代价很大。一方面跨系统准备数据很麻烦;另一方面即使当时数据准备好了,过两天可能又没了。这个验证没法自动化就没法到持续集成,也就称不上单元测试。通过使用Mock,可以让这两个外部依赖按照我们的想法返回数据,准备数据变得容易,单测的强度也就容易提升。首先在pom中引入easymock&dependency&& & & & & & &groupId&org.easymock&/groupId&& & & & & & &artifactId&easymock&/artifactId&& & & & & & &version&3.4&/version&& & & & & & &scope&test&/scope&& & & & &/dependency&(由于微信文章字数限制,更多精彩,请点击“阅读原文”!)本文为云栖社区文章,如需转载,请注明出处,并附上云栖社区微信公众号:yunqiinsight。点击“阅读原文”可查看原文。想和这群聪明人共事吗?加入阿里云云栖社区(全职/兼职):yqeditor@list.投稿或入驻云栖社区,请联系:yqeditor@list.“2016,为了实现更多技术梦想,云栖社区与你携手并行。yunqiinsight长按二维码,一网打尽所有深度技术文章戳原文,更有料!云栖社区(gh_015af649354b) 
 文章为作者独立观点,不代表大不六文章网立场
的最新文章
点击?阅读原文?查看往期精彩尊敬的云栖大会嘉宾,13-16日杭州气温16-23℃,可能有阵雨,请您备好外套和雨具。会场周边有临时交通管制,建议选乘公共交通,大会接驳车信息详见大会官网。再次提醒您尽早预定酒店房间,特奉上大会专属酒店红包。点击?阅读原文?查看往期精彩阿里云宣布中国区云产品全线下调,核心云产品最高降幅达50%。此外,云栖大会15日还特设置了“云栖社区开发者技术峰会——架构专场”,详情点击阅读原文查看,这种好事一般人我不告诉他。点击?阅读原文?查看往期精彩点击?阅读原文?进入云栖现场当浩瀚的数字化信息能够联网在线,在万物互联网的新世界中,所有东西都可能有感知、变智能,想象一下电表、冰箱、心电图等设备的信息都能数字化并联网,从城市管理到个人生活,都会迎来翻天覆地的变化。现在让我们看看阿里是如何用计算和数据去改变整个世界。点击?阅读原文?查看往期精彩10月16日,持续四日的2016杭州云栖大会顺利收官。大会涵盖云计算、大数据、人工智能、智能硬件、VR、AR、芯片技术、数据库、操作系统、生物识别、天文科研、金融科技等前沿议题,集中向世界展示中国科技的创新力量。点击?阅读原文?查看往期精彩环顾时下,未来的大数据引擎究竟采用什么样的方式尚不可知,不过在大数据平台构建过程中如何去做好技术选型,以及在后续过程中如何做好开源的自主研发却是个值得讨论问题。点击?阅读原文?查看往期精彩本文主要介绍阿里云 MongoDB 数据库上客户遇到的问题,及相应的解决方案。点击?阅读原文?查看往期精彩MaxCompute云栖文章索引。点击?阅读原文?查看往期精彩MaxCompute OpenMR的7个性能优化策略。10月13日,阿里云首席科学家周靖人发表演讲,他表示,随着计算能力提升、大数据和深度学习的发展,人工智能迎来了新的春天——数据智能时代。集合多年数据智能技术、代表领域最先进水平的阿里云人工智能ET,则在各行业进行创新、变革、数据化和智能化。点击?阅读原文?查看往期精彩摘要: 通过简单的几步配置,教你如何快速实现ODPS的数据可视化。Zeppelin简介Zeppelin是一款在作为HDFS诞生以来的最大改进——支持了纠删码(erasure coding)之后,面对这个比较完善但并不十全十美的方案,面对Hadoop开源生态,HDFS的下一步将走向何处呢?点击?阅读原文?查看往期精彩DT时代,一切都将走向数据化,可视化。在阿里云所阐述的“技术拓展商业的边界,商业驱动技术的变革”理念中,阿里云逐步实现了“将计算能力变成像水电一样的基础设施”的目标,走向“为了无法计算的价值”。点击?阅读原文?查看往期精彩在本次分享中,曾文旌从GPDB架构入手,辅助以SQL和优化器的案例以及对GPDB的硬件和性能的分析,对GPDB实现进行了详细解析。分享最后,他还对比了GPDB的优势和局限性,并对GPDB的未来发展进行了展望。点击?阅读原文?查看往期精彩点击?阅读原文?查看往期精彩点击?阅读原文?查看往期精彩点击?阅读原文?查看往期精彩大数据领域一定会朝着更加实时、更加智能、数据更加多样化的方向前进。Kafka、Spark和Flink之类的支持流式计算的软件会越来越流行,同时各类机器学习平台和工具也会越来越成熟。我们已经生活在一个开源的时代!互联网技术正统治着市场,任何新兴企业都在利用开源技术。这是一个飞速变革的世界,只有开源技术才能满足这些新的需求。我们发现许多新的开源数据库为了满足新需求应运而生。点击?阅读原文?查看往期精彩我们更倾向于Greenplum的方案,合理的涉及distribution key是可以完全避免数据倾斜的问题。想要构造一个web系统中的TPM,首要问题就是需要保证输入数据安全,打造一个相对可信的前端环境。但是由于web的开放特性,前端作为数据采集的最前线,js代码始终暴露在外,在这种情况下,js代码混淆的重要性逐渐彰显出来。点击?阅读原文?查看往期精彩点击?阅读原文?查看往期精彩点击?阅读原文?查看往期精彩微服务设计不应是一个讲求标准答案, 简单粗暴的设计过程。而应该是一个考量各方因素下的一个决策的过程。所谓的微服务具体应包含哪些核心的概念?从既有架构迁移到微服务架构又有那些策略?阿里云数据库团队正式迈出开源的第一步——开始内测。点击?阅读原文?查看往期精彩本文从数据库的原理出发,讨论下如何写出高性能的SQL。Google在2005年收购了Urchin,在2006年以免费工具的形式发布了Google Analytics,其功能非常强大,只要在网站的页面上加入一段代码,就可以提供丰富详尽的图表式报告。本文让我们聊聊视频网站数据平台变迁之路。点击?阅读原文?查看往期精彩所谓Role,可以认为是一个权限的集合,这个集合有一个统一的名字,就是Role名,你可以为多个账户赋予统一的某个Role的权限,而权限的修改可以直接通过修改Role来实现。本文主要从高速增长的阿里业务开始谈起,讲述当年面对的业务场景和背景,碰到了什么样的技术挑战,且用什么样的思路去解决它,最后和大家分享了解决后产生的产品Aliware中非常重要的EDAS。点击?阅读原文?查看往期精彩金建明认为企业IT管理服务的未来会变得更加智能化、自动化,企业的IT人员会越来越靠近企业的业务,而远离简单重复的底层工作。经过多年在全球最大的电商平台大数据上的沉淀和积累,阿里电商反作弊形成了一套监控预警、识别分析和处罚管控的多维度监管机制,特别是对虚假交易的数据监控和算法识别上应用了覆盖全链路大数据的实时分析。点击?阅读原文?查看往期精彩见招拆招,本文带你浅析蚂蚁金服利用Freeline带来的解决方案。gh_015af649354b云栖社区是由阿里云负责运营、阿里巴巴技术协会和阿里巴巴集团各技术团队提供内容支持的开放式技术社区。热门文章最新文章gh_015af649354b云栖社区是由阿里云负责运营、阿里巴巴技术协会和阿里巴巴集团各技术团队提供内容支持的开放式技术社区。}

我要回帖

更多关于 逃离大厦124关怎么过 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信