Quantcast
Channel: IT社区推荐资讯 - ITIndex.net
Viewing all 11804 articles
Browse latest View live

如何在数据库事务提交成功后进行异步操作

$
0
0

问题

业务场景

业务需求上经常会有一些边缘操作,比如主流程操作A:用户报名课程操作入库,边缘操作B:发送邮件或短信通知。

业务要求

  • 操作A操作数据库失败后,事务回滚,那么操作B不能执行。

  • 操作A执行成功后,操作B也必须执行成功

如何实现

  • 普通的执行A,之后执行B,是可以满足要求1,对于要求2通常需要设计补偿的操作

  • 一般边缘的操作,通常会设置成为异步的,以提升性能,比如发送MQ,业务系统负责事务成功后消息发送成功,然后接收系统负责保证通知成功完成

本文内容

如何在spring事务提交之后进行异步操作,这些异步操作必须得在该事务成功提交后才执行,回滚则不执行。

要点

  • 如何在spring事务提交之后操作

  • 如何把操作异步化

实现方案

使用TransactionSynchronizationManager在事务提交之后操作

public void insert(TechBook techBook){
        bookMapper.insert(techBook);
       // send after tx commit but is async
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public void afterCommit() {
                System.out.println("send email after transaction commit...");
            }
        }
       );
        ThreadLocalRandom random = ThreadLocalRandom.current();
        if(random.nextInt() % 2 ==0){
            throw new RuntimeException("test email transaction");
        }
        System.out.println("service end");
    }

该方法就可以实现在事务提交之后进行操作

操作异步化

使用mq或线程池来进行异步,比如使用线程池:

private final ExecutorService executorService = Executors.newFixedThreadPool(5);
    public void insert(TechBook techBook){
        bookMapper.insert(techBook);
//        send after tx commit but is async
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public void afterCommit() {
                executorService.submit(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println("send email after transaction commit...");
                        try {
                            Thread.sleep(10*1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println("complete send email after transaction commit...");
                    }
                });
            }
        }
        );
//        async work but tx not work, execute even when tx is rollback
//        asyncService.executeAfterTxComplete();
        ThreadLocalRandom random = ThreadLocalRandom.current();
        if(random.nextInt() % 2 ==0){
            throw new RuntimeException("test email transaction");
        }
        System.out.println("service end");
    }

封装以上两步

对于第二步来说,如果这类方法比较多的话,则写起来重复性太多,因而,抽象出来如下:
这里改造了 azagorneanu的代码:

public interface AfterCommitExecutor extends Executor {
}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@Component
public class AfterCommitExecutorImpl extends TransactionSynchronizationAdapter implements AfterCommitExecutor {
    private static final Logger LOGGER = LoggerFactory.getLogger(AfterCommitExecutorImpl.class);
    private static final ThreadLocal<List<Runnable>> RUNNABLES = new ThreadLocal<List<Runnable>>();
    private ExecutorService threadPool = Executors.newFixedThreadPool(5);
    @Override
    public void execute(Runnable runnable) {
        LOGGER.info("Submitting new runnable {} to run after commit", runnable);
        if (!TransactionSynchronizationManager.isSynchronizationActive()) {
            LOGGER.info("Transaction synchronization is NOT ACTIVE. Executing right now runnable {}", runnable);
            runnable.run();
            return;
        }
        List<Runnable> threadRunnables = RUNNABLES.get();
        if (threadRunnables == null) {
            threadRunnables = new ArrayList<Runnable>();
            RUNNABLES.set(threadRunnables);
            TransactionSynchronizationManager.registerSynchronization(this);
        }
        threadRunnables.add(runnable);
    }
    @Override
    public void afterCommit() {
        List<Runnable> threadRunnables = RUNNABLES.get();
        LOGGER.info("Transaction successfully committed, executing {} runnables", threadRunnables.size());
        for (int i = 0; i < threadRunnables.size(); i++) {
            Runnable runnable = threadRunnables.get(i);
            LOGGER.info("Executing runnable {}", runnable);
            try {
                threadPool.execute(runnable);
            } catch (RuntimeException e) {
                LOGGER.error("Failed to execute runnable " + runnable, e);
            }
        }
    }
    @Override
    public void afterCompletion(int status) {
        LOGGER.info("Transaction completed with status {}", status == STATUS_COMMITTED ? "COMMITTED" : "ROLLED_BACK");
        RUNNABLES.remove();
    }
}
public void insert(TechBook techBook){
        bookMapper.insert(techBook);
//        send after tx commit but is async
//        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
//            @Override
//            public void afterCommit() {
//                executorService.submit(new Runnable() {
//                    @Override
//                    public void run() {
//                        System.out.println("send email after transaction commit...");
//                        try {
//                            Thread.sleep(10*1000);
//                        } catch (InterruptedException e) {
//                            e.printStackTrace();
//                        }
//                        System.out.println("complete send email after transaction commit...");
//                    }
//                });
//            }
//        }
//        );
        //send after tx commit and is async
        afterCommitExecutor.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(5*1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("send email after transactioin commit");
            }
        });
//        async work but tx not work, execute even when tx is rollback
//        asyncService.executeAfterTxComplete();
        ThreadLocalRandom random = ThreadLocalRandom.current();
        if(random.nextInt() % 2 ==0){
            throw new RuntimeException("test email transaction");
        }
        System.out.println("service end");
    }

关于Spring的Async

spring为了方便应用使用线程池进行异步化,默认提供了@Async注解,可以整个app使用该线程池,而且只要一个@Async注解在方法上面即可,省去重复的submit操作。关于async要注意的几点:

1、async的配置

<context:component-scan base-package="com.yami" /><!--配置@Async注解使用的线程池,这里的id随便命名,最后在task:annotation-driven executor= 指定上就可以--><task:executor id="myExecutor" pool-size="5"/><task:annotation-driven executor="myExecutor" />

这个必须配置在root context里头,而且web context不能扫描controller层外的注解,否则会覆盖掉。

<context:component-scan base-package="com.yami.web.controller"/><mvc:annotation-driven/>

2、async的调用问题

async方法的调用,不能由同类方法内部调用,否则拦截不生效,这是spring默认的拦截问题,必须在其他类里头调用另一个类中带有async的注解方法,才能起到异步效果。

3、事务问题

async方法如果也开始事务的话,要注意事务传播以及事务开销的问题。而且在async方法里头使用如上的TransactionSynchronizationManager.registerSynchronization不起作用,值得注意。


CAS实现SSO单点登录原理

$
0
0

原文地址 

http://www.cnblogs.com/gxbk629/p/4473569.html

 

 

====================

 

CAS实现SSO单点登录原理

1.      CAS 简介

1.1.  What is CAS ?

CAS ( Central Authentication Service ) 是 Yale 大学发起的一个企业级的、开源的项目,旨在为 Web 应用系统提供一种可靠的单点登录解决方法(属于 Web SSO )。

CAS 开始于 2001 年, 并在 2004 年 12 月正式成为 JA-SIG 的一个项目。

1.2.  主要特性

1、   开源的、多协议的 SSO 解决方案; Protocols : Custom Protocol 、 CAS 、 OAuth 、 OpenID 、 RESTful API 、 SAML1.1 、 SAML2.0 等。

2、   支持多种认证机制: Active Directory 、 JAAS 、 JDBC 、 LDAP 、 X.509 Certificates 等;

3、   安全策略:使用票据( Ticket )来实现支持的认证协议;

4、   支持授权:可以决定哪些服务可以请求和验证服务票据( Service Ticket );

5、   提供高可用性:通过把认证过的状态数据存储在 TicketRegistry 组件中,这些组件有很多支持分布式环境的实现,如: BerkleyDB 、 Default 、 EhcacheTicketRegistry 、 JDBCTicketRegistry 、 JBOSS TreeCache 、 JpaTicketRegistry 、 MemcacheTicketRegistry 等;

6、   支持多种客户端: Java 、 .Net 、 PHP 、 Perl 、 Apache, uPortal 等。

 

2.      SSO 单点登录原理

本文内容主要针对 Web SSO 。

2.1.  什么是SSO

单点登录( Single Sign-On , 简称 SSO )是目前比较流行的服务于企业业务整合的解决方案之一, SSO 使得在多个应用系统中,用户只需要  登录一次 就可以访问所有相互信任的应用系统。

2.2.  SSO 原理

2.2.1.      SSO 体系中的角色

一般 SSO 体系主要角色有三种:

1、 User (多个)

2、 Web 应用(多个)

3、 SSO 认证中心(  1 个 

2.2.2.      SSO 实现模式的原则

SSO 实现模式一般包括以下三个原则:

1、   所有的认证登录都在 SSO 认证中心进行;

2、   SSO 认证中心通过一些方法来告诉 Web 应用当前访问用户究竟是不是已通过认证的用户;

3、   SSO 认证中心和所有的 Web 应用建立一种信任关系,也就是说 web 应用必须信任认证中心。(单点信任)

2.2.3.      SSO 主要实现方式

SSO 的主要实现方式有:

1、   共享 cookies

基于共享同域的 cookie 是 Web 刚开始阶段时使用的一种方式,它利用浏览同域名之间自动传递 cookies 机制,实现两个域名之间系统令牌传递问题;另外,关于跨域问题,虽然 cookies本身不跨域,但可以利用它实现跨域的 SSO 。如:代理、暴露 SSO 令牌值等。

缺点:不灵活而且有不少安全隐患,已经被抛弃。

2、   Broker-based( 基于经纪人 )

这种技术的特点就是,有一个集中的认证和用户帐号管理的服务器。经纪人给被用于进一步请求的电子身份存取。中央数据库的使用减少了管理的代价,并为认证提供一个公共和独立的 "第三方 " 。例如 Kerberos 、 Sesame 、 IBM KryptoKnight (凭证库思想 ) 等。 Kerberos是由麻省理工大学发明的安全认证服务,已经被 UNIX 和 Windows 作为默认的安全认证服务集成进操作系统。

3、   Agent-based (基于代理人)

在这种解决方案中,有一个自动地为不同的应用程序认证用户身份的代理程序。这个代理程序需要设计有不同的功能。比如,它可以使用口令表或加密密钥来自动地将认证的负担从用户移开。代理人被放在服务器上面,在服务器的认证系统和客户端认证方法之间充当一个 " 翻译 "。例如 SSH 等。

4、   Token-based

例如 SecureID,WebID ,现在被广泛使用的口令认证,比如 FTP 、邮件服务器的登录认证,这是一种简单易用的方式,实现一个口令在多种应用当中使用。

5、   基于网关

6、   基于 SAML

SAML(Security Assertion Markup Language ,安全断言标记语言)的出现大大简化了 SSO ,并被 OASIS 批准为  SSO 的执行标准 。开源组织 OpenSAML 实现了 SAML 规范。

 

3.      CAS 的基本原理

3.1.  结构体系

从结构体系看, CAS 包括两部分: CAS Server 和 CAS Client 。

3.1.1.      CAS Server

CAS Server 负责完成对用户的认证工作 , 需要独立部署 , CAS Server 会处理用户名 / 密码等凭证(Credentials) 。

3.1.2.      CAS Client

负责处理对客户端受保护资源的访问请求,需要对请求方进行身份认证时,重定向到 CAS Server 进行认证。(原则上,客户端应用不再接受任何的用户名密码等 Credentials )。

CAS Client 与受保护的客户端应用部署在一起,以 Filter 方式保护受保护的资源。

3.2.  CAS 原理和协议

3.2.1.      基础模式

基础模式 SSO 访问流程主要有以下步骤:

1. 访问服务: SSO 客户端发送请求访问应用系统提供的服务资源。

2. 定向认证: SSO 客户端会重定向用户请求到 SSO 服务器。

3. 用户认证:用户身份认证。

4. 发放票据: SSO 服务器会产生一个随机的 Service Ticket 。

5. 验证票据: SSO 服务器验证票据 Service Ticket 的合法性,验证通过后,允许客户端访问服务。

6. 传输用户信息: SSO 服务器验证票据通过后,传输用户认证结果信息给客户端。

下面是 CAS 最基本的协议过程:

 

cas基础协议图

基础协议图

 

如上图: CAS Client 与受保护的客户端应用部署在一起,以 Filter 方式保护 Web 应用的受保护资源,过滤从客户端过来的每一个 Web 请求,同时, CAS Client 会分析 HTTP 请求中是否包含请求 Service Ticket( ST 上图中的 Ticket) ,如果没有,则说明该用户是没有经过认证的;于是 CAS Client 会重定向用户请求到 CAS Server ( Step 2 ),并传递 Service (要访问的目的资源地址)。 Step 3 是用户认证过程,如果用户提供了正确的 Credentials , CAS Server 随机产生一个相当长度、唯一、不可伪造的 Service Ticket ,并缓存以待将来验证,并且重定向用户到 Service 所在地址(附带刚才产生的 Service Ticket ) ,  并为客户端浏览器设置一个 Ticket Granted Cookie ( TGC ) ; CAS Client 在拿到 Service 和新产生的 Ticket 过后,在 Step 5 和 Step6 中与 CAS Server 进行身份核实,以确保 Service Ticket 的合法性。

在该协议中,所有与 CAS Server 的交互均采用 SSL 协议,以确保 ST 和 TGC 的安全性。协议工作过程中会有  2 次重定向 的过程。但是 CAS Client 与 CAS Server 之间进行 Ticket 验证的过程对于用户是透明的(使用 HttpsURLConnection )。

    CAS 请求认证时序图如下:

 

cas认证时序图  

3.2.1.      CAS 如何实现 SSO

当用户访问另一个应用的服务再次被重定向到 CAS Server 的时候, CAS Server 会主动获到这个 TGC cookie ,然后做下面的事情:

1) 如果 User 持有 TGC 且其还没失效,那么就走基础协议图的 Step4 ,达到了 SSO 的效果;

2) 如果 TGC 失效,那么用户还是要重新认证 ( 走基础协议图的 Step3) 。

 

3.2.2.      CAS 代理模式

该模式形式为用户访问 App1 , App1 又依赖于 App2 来获取一些信息,如: User -->App1 -->App2。

这种情况下,假设 App2 也是需要对 User 进行身份验证才能访问,那么,为了不影响用户体验(过多的重定向导致 User 的 IE 窗口不停地闪动 ) , CAS 引入了一种 Proxy 认证机制,即 CAS Client 可以代理用户去访问其它 Web 应用。

代理的前提是需要 CAS Client 拥有用户的身份信息 ( 类似凭据 ) 。之前我们提到的 TGC 是用户持有对自己身份信息的一种凭据,这里的 PGT 就是 CAS Client 端持有的对用户身份信息的一种凭据。凭借TGC , User 可以免去输入密码以获取访问其它服务的 Service Ticket ,所以,这里凭借 PGT , Web应用可以代理用户去实现后端的认证,而  无需前端用户的参与 

下面为代理应用( helloService )获取 PGT 的过程: (注: PGTURL 用于表示一个 Proxy 服务,是一个回调链接; PGT 相当于代理证; PGTIOU 为取代理证的钥匙,用来与 PGT 做关联关系;)

 

cas代理PGT获取  

如上面的 CAS Proxy 图所示,  CAS Client 在基础协议之上,在验证 ST 时提供了一个额外的PGT URL( 而且是 SSL 的入口 ) 给 CAS Server ,使得 CAS Server 可以通过 PGT URL 提供一个 PGT 给 CAS Client 。

CAS Client 拿到了 PGT(PGTIOU-85 … ..ti2td) ,就可以通过 PGT 向后端 Web 应用进行认证。

下面是代理认证和提供服务的过程:

 

如上图所示, Proxy 认证与普通的认证其实差别不大, Step1 , 2 与基础模式的 Step1,2 几乎一样,唯一不同的是, Proxy 模式用的是 PGT 而不是 TGC ,是 Proxy Ticket ( PT )而不是 Service Ticket 。

 

3.2.3.      辅助说明

CAS 的 SSO 实现方式可简化理解为: 1 个 Cookie 和 N 个 Session 。 CAS Server 创建 cookie,在所有应用认证时使用,各应用通过创建各自的 Session 来标识用户是否已登录。

用户在一个应用验证通过后,以后用户在同一浏览器里访问此应用时,客户端应用中的过滤器会在 session 里读取到用户信息,所以就不会去 CAS Server 认证。如果在此浏览器里访问别的 web 应用时,客户端应用中的过滤器在 session 里读取不到用户信息,就会去 CAS Server 的 login 接口认证,但这时CAS Server 会读取到浏览器传来的 cookie ( TGC ),所以 CAS Server 不会要求用户去登录页面登录,只是会根据 service 参数生成一个 Ticket ,然后再和 web 应用做一个验证 ticket 的交互而已。

3.3.  术语解释

CAS 系统中设计了 5 中票据: TGC 、 ST 、 PGT 、 PGTIOU 、 PT 。

Ø     Ticket-granting cookie(TGC) :存放用户身份认证凭证的 cookie ,在浏览器和 CAS Server 间通讯时使用,并且只能基于安全通道传输( Https ),是 CAS Server 用来明确用户身份的凭证;

Ø   Service ticket(ST) :服务票据,服务的惟一标识码 , 由 CAS Server 发出( Http 传送),通过客户端浏览器到达业务服务器端;一个特定的服务只能有一个惟一的 ST ;

Ø   Proxy-Granting ticket ( PGT ):由 CAS Server 颁发给拥有 ST 凭证的服务, PGT 绑定一个用户的特定服务,使其拥有向 CAS Server 申请,获得 PT 的能力;

Ø   Proxy-Granting Ticket I Owe You ( PGTIOU ) : 作用是将通过凭证校验时的应答信息由 CAS Server 返回给 CAS Client ,同时,与该 PGTIOU 对应的 PGT 将通过回调链接传给 Web 应用。 Web 应用负责维护 PGTIOU 与 PGT 之间映射关系的内容表;

Ø   Proxy Ticket (PT) :是应用程序代理用户身份对目标程序进行访问的凭证;

 

其它说明如下:

Ø   Ticket Granting ticket(TGT) :票据授权票据,由 KDC 的 AS 发放。即获取这样一张票据后,以后申请各种其他服务票据 (ST) 便不必再向 KDC 提交身份认证信息 (Credentials) ;

Ø   Authentication service(AS) --------- 认证用服务,索取 Credentials ,发放 TGT ;

Ø   Ticket-granting service (TGS) --------- 票据授权服务,索取 TGT ,发放 ST ;

Ø   KDC( Key Distribution Center ) ---------- 密钥发放中心;

 

4.      CAS 安全性

CAS 的安全性仅仅依赖于 SSL 。使用的是 secure cookie 。

4.1.  TGC/PGT 安全性

对于一个 CAS 用户来说,最重要是要保护它的 TGC ,如果 TGC 不慎被 CAS Server 以外的实体获得, Hacker 能够找到该 TGC ,然后冒充 CAS 用户访问  所有 授权资源。 PGT 的角色跟 TGC 是一样的。

从基础模式可以看出, TGC 是 CAS Server 通过 SSL 方式发送给终端用户,因此,要截取 TGC 难度非常大,从而确保 CAS 的安全性。

TGT 的存活周期默认为 120 分钟。

4.2.  ST/PT 安全性

ST ( Service Ticket )是通过 Http 传送的,因此网络中的其他人可以 Sniffer 到其他人的 Ticket 。 CAS 通过以下几方面来使 ST 变得更加安全(事实上都是可以配置的):

1、   ST 只能使用一次

CAS 协议规定,无论 Service Ticket 验证是否成功, CAS Server 都会清除服务端缓存中的该Ticket ,从而可以确保一个 Service Ticket 不被使用两次。

2、   ST 在一段时间内失效

CAS 规定 ST 只能存活一定的时间,然后 CAS Server 会让它失效。默认有效时间为 5 分钟。

3、   ST 是基于随机数生成的

ST 必须足够随机,如果 ST 生成规则被猜出, Hacker 就等于绕过 CAS 认证,直接访问  对应的服务。

 

5.      参考资料

1、 https://wiki.jasig.org/display/CASUM/Introduction

2、 http://www.jasig.org/cas/protocol/

3、 http://www.ibm.com/developerworks/cn/opensource/os-cn-cas/index.html

4、 http://www.blogjava.net/security/archive/2006/10/02/sso_in_action.html

5、 http://baike.baidu.com/view/190743.htm



已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



Twitter 是如何为硬件故障做准备的

$
0
0
twitter-down

在理想的情况下,Twitter 的基础设施与运营总监马兹达克·哈希米(Mazdak Hashemi)可以走到公司的数据中心,然后拔掉其中一台服务器的电源线,这时公司的服务也不会受到影响。虽然他现在还不会这么做,但是他和他的团队一直在研究如何在 Twitter 内部模拟类似的故障,同时确保服务能够维持正常运行。

“在如此大的服务规模之下,我们的基础设施有可能会出现各种各样的问题,我们随时都可能出现断电、机架故障、配置不当或者网络故障。”哈希米说道,“所以我们开始思考,除了面对突如其来的故障以外,检测故障的最佳方式是什么。”

他的工程团队基本上设计了一系列的测试,他们会以可控的方式向系统注入故障,模拟上面提到的情况。这样做的目的是确保所有工作人员可以为各种意外故障做好准备,比如服务器宕机,或者电源线意外脱落导致整个服务器节点离线。

Twitter 会在服务中注入一些小型的故障,测试运行系统和基础设施的反应。它会监控 Twitter 服务的系统健康状况,确保不会有全站规模的故障发生,然后回滚之前注入的故障状态。在整个测试过程当中,这支团队还可以使用一系列的工具来了解系统的情况。他们希望可以监控服务器集群出现断电,或者在写入新配置的时候出现断网的问题。

screen-shot-2015-12-14-at-2-40-59-pm

以上都是 Twitter 内部应急工具的一部分,确保 Twitter 在任何情况之下都不会束手无策。“失败鲸”(Fail Whale)曾经是 Twitter 网站上的常驻吉祥物,不过现在 Twitter 正不遗余力地避免这条鲸鱼再次出现。

最终这个工具有望会被开源,这样就可以让开发者社区找到更多的使用方式,甚至对它进行改进。“Twitter 与其他公司的区别在于——我们的所有东西都是实时的。”哈希米说道,“我们不会说‘你去准备黑色星期五,你去准备超级碗。’其他人想到某些日子将要来临的时候就会做准备,但是对我们来说,每一天都可以是黑色星期五,每一天都可以是超级碗。我们的网站是充满不确定性的,世界这么大,什么事情都有可能发生。”

这些测试的意义当然不止如此。如果仅仅是为了测试的话,他们随时都可以拔掉 服务器的网线来测试服务能否继续运行。这些测试的目标是为了确保每个团队都能准备好应对任何级别的真正事故。

“我希望终有一天可以在数据中心里随便拔掉一条电线,然后看看会发生什么事情。”哈希米说道,“我今天会这么做吗?也许不会,不过我现在还不想这么做。我对部分情况还是比较放心的,但是如果故障的层级越高,它所造成的影响也会越大。我们团队的终极考验是,当我们在数据中心随意拔掉各种线缆的时候,系统能否保持安然无恙。”

题图来自:Bryce Durbin

翻译:关嘉伟( @consideRay

A Look At One Way Twitter Prepares For Hardware Failures

360:2015年医疗行业搜索行为研究报告

如何使用PE估值抓牛股?

$
0
0
1、股票上涨的本质是什么?
       弄清楚这个问题,有助于我们正确的构建自己的投资体系、确认自己的投资风格。从PE的公式PE=Price/Earnings,可以得知股价=每股收益*市盈率,那么股价上涨幅度=每股收益涨幅*市盈率涨幅,考虑到每股收益受股本变化影响,因此用归属净利率替代,也即股价涨幅=归属净利润涨幅*市盈率涨幅。
       因此,决定股价上涨的本质因素就出来了,即归属净利润以及市盈率。其中归属净利润代表了基本面估值,而市盈率代表了情绪估值。要判断股价未来几年的涨幅则需要判断出净利润的涨幅以及市盈率的涨幅。以净利润为出发点的投资者往往研究基本面,也因此产生了价值投资者、成长股投资者;而市盈率更多的代表了情绪估值,情绪由市场整体行情(也即牛、熊市)、资金、政策、概念等决定,也因此衍生了各种技术派、资金派、概念炒作等。下面举几个例子来看看净利润和市盈率对股价的长期决定性影响。
       第一种情况:净利润增长,市盈率也增长。请看乐视网2011年到2015年走势,从3元到90元,5年翻了约30倍。而净利润只翻了7倍多,那么剩下的4倍从哪里贡献的?我们可以看到乐视网11年市盈率在80倍左右,而15年牛市到了惊人的350倍左右,市盈率翻了4倍,乘以净利润增长正好30倍左右。非常经典的戴维斯双击。


        第二种情况:净利润增长,市盈率不变。请看昆药集团2012年到2015年走势,股价从13到39翻了约3倍,市盈率基本横盘在38倍左右,那么显而易见的昆药的涨幅基本全部来自净利润的增长,估值没有贡献收益,确实如此,12年到15年昆药净利润翻了约3倍(考虑15年增速)。


        第三种情况:净利润增长,市盈率下降。请看探路者2010年到2014年走势,股价从6元到18元,翻倍3倍,但是净利润却翻了7倍,净利润涨幅被什么吞噬了?我们可以看到探路者从10年到14年估值从60多倍下降到27倍。正是估值的下降侵蚀了本应该获得的收益。


        第四种情况:净利润下跌,市盈率下跌。请看五粮液2012年到2014年走势,股价从12年30元到13年20元,再到14年14元。五粮液净利润从12年100亿到14年60亿,跌了40%,估值从20倍跌到最低6倍不到。这就是典型的戴维斯双杀,杀业绩杀估值,导致股价大跌。13年10倍PE怎么也不算高了,如果投资者抄底进去还是会造成很大亏损。五粮液是消费股,属于弱周期股,但是我想给白酒股加上个周期属性“腐败周期”(你懂的!),投资白酒股一定要把握好这个周期,不要被低PE蒙骗。


        净利润和市盈率的组合还有很多,比如净利润下滑及不变的情况下还有N种情形,但是剩下的情形对赚钱都没太大帮助。因此上面总结了四种典型情况:80倍PE买的乐视网5年赚了30倍,38倍PE买的昆药4年翻了3倍,60倍PE买的探路者也翻了3倍,而20倍PE买的五粮液亏了一半多。可见低PE未必风险更低,收益更高,也可能会出现亏损。
2、PE的合理使用
        那么PE该怎么合理正确的使用?首先:对于未来预期净利润不再增长甚至负增长的公司一律剔除(对未来净利润的预估比较复杂也因人而异的,可以参考《怎样选择成长股》这本书),A股股票那么多,从安全的赚钱的角度出发,没必要研究那么多。然后首先进行行业比选,选择行业内比行业均值估值更低的公司。当选择出公司后,再对这个股票的历史市盈率进行分析,选择多年PE均值作为估值中枢,多年PE低点作为买入参考点,卖出同理。下面以2015年9月份建仓探路者为例,说明PE的运用。

        9月份创业板市盈率从最高的130倍跌到60倍,而当时探路者市盈率才25倍,在创业板中排前三,纺织服装行业平均市盈率约32倍,中值市盈率35倍,可见探路者横向比较是非常有优势的,再看下图探路者自身PE走势,25倍已经是历年最低水平。因此在9月份建仓了部分探路者,成本15元。

       总结:想长期从股票上赚到钱,你需要判断出企业未来净利润的增长幅度,并在一个合理的估值买入,两者缺一不可。成长股的魅力在于享受净利润的增长的同时,可能还会享受估值的戴维斯双杀。而单纯低PE选股,可能会遭受戴维斯双杀。

利益披露:本人持有上述提及的 $昆药集团(SH600422)$  、 $探路者(SZ300005)$ ,请勿抬轿。 

@今日话题@雪球达人秀@胖咪咪@徐佳杰Pierre@林奇法则@魏员外@落灰灰 
$乐视网(SZ300104)$   $五粮液(SZ000858)$

本话题在雪球有27条讨论,点击查看。
雪球是一个投资者的社交网络,聪明的投资者都在这里。
点击下载雪球手机客户端 http://xueqiu.com/xz

深入解析Java对象的hashCode和hashCode在HashMap的底层数据结构的应用

$
0
0

一、java对象的比较

 

等号(==):
对比对象实例的内存地址(也即对象实例的ID),来判断是否是同一对象实例;又可以说是判断对象实例是否物理相等;

 

equals():

对比两个对象实例是否相等。

当对象所属的类没有重写根类Object的equals()方法时,equals()判断的是对象实例的ID(内存地址),是否是同一对象实例;该方法就是使用的等号(==)的判断结果。

 

  当对象所属的类重写equals()方法(可能因为需要自己特有的“逻辑相等”概念)时,equals()判断的根据就因具体实现而异,有些类是需要比较对象的某些指或内容,如String类重写equals()来判断字符串的值是否相等。判断逻辑相等。

 

 hashCode():

计算出对象实例的哈希码,并返回哈希码,又称为散列函数。根类Object的hashCode()方法的计算依赖于对象实例的D(内存地址),故每个Object对象的hashCode都是唯一的;当然,当对象所对应的类重写了hashCode()方法时,结果就截然不同了。

 

  二、Java的类为什么需要hashCode?---hashCode的作用,从Java中的集合的角度看。

 

  总的来说,Java中的集合(Collection)有两类,一类是List,再有一类是Set。你知道它们的区别吗?前者集合内的元素是有序的,元素可以重复;后者元素无序,但元素不可重复。那么这里就有一个比较严重的问题了:要想保证元素不重复,可两个元素是否重复应该依据什么来判断呢?这就是 Object.equals方法了。但是,如果每增加一个元素就检查一次,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了。也就是说,如果集合中现在已经有1000个元素,那么第1001个元素加入集合时,它就要调用1000次equals方法。这显然会大大降低效率。

 

   于是,Java采用了哈希表的原理。哈希算法也称为散列算法,是将数据依特定算法直接指定到一个地址上。关于哈希算法,这里就不详细介绍。可以这样简单理解,hashCode方法实际上返回的就是对象存储位置的映像。
   

  这样一来,当集合要添加新的元素时,先调用这个元素的hashCode方法,就能定位到它应该放置的存储位置。如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就表示发生冲突了,散列表对于冲突有具体的解决办法,但最终还会将新元素保存在适当的位置。这样一来,实际调用equals方法的次数就大大降低了,几乎只需要一两次。
   

所以,Java对于eqauls方法和hashCode方法是这样规定的:
1、相等的对象必须具有相等的哈希码(或者散列码)。
2、如果两个对象的hashCode相同,它们并不一定相同。
   
 上述的对象相同指的是通过eqauls方法判断,结果为true。

 

 你当然可以不按要求去做了,但你会发现,相同的对象可以出现在Set集合中。同时,增加新元素的效率会大大下降。

 



已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



Zookeeper的Session

$
0
0

介绍一下基于zookeeper的一些API的编程。
在此之前,我们先来熟悉一下相关知识:

Zookeeper的Session:
(1)客户端和server间采用长连接
(2)连接建立后,server产生session ID(64位)返还给客户端
(3)客户端定期发送ping包来检查和保持和server的连接
(4)一旦session结束或超时,所有ephemeral节点会被删除
(5)客户端可根据情况设置合适的session超时时间

Zookeeper的Watchs:
Watch是客户端安装在server的事件侦听方法
(1) 当侦听的变化发生时,server发消息给客户端进行通知
(2) 客户端使用单线程对所有事件按顺序同步回调
(3) 触发回调条件:
• 客户端连接、断开连接
• 节点数据发生改变
• 节点本身发生变化
(4)Watch是单发的,每次触发后会被自动删除
(5)如果需要再次侦听事件,必须重新安装watch
(6)无法保证跟踪到每一个变化
(7)避免安装大量watches侦听在同一个节点

Zookeeper的一些注意事项:
在客户端事件回调实现有阻塞调用
• 试图跟踪每个状态变化
• 大量watch侦听同一个znode的状态变化
• 客户端会有需要长时间处理的GC(garbage collection)
• Session超时后上层应用不进行恢复处理 

可以把zookper看成一个文件系统,文件系统中的所有文件形成一个数状结构,zookeeper维护着这样的树形层次结构,树中的节点称为znode。每个znode有一个与之相关联的ACL(Access Control List)
znode通过路径被引用,而且要采用绝对路径,即必须以/开头。znode存储的数据要小于1M,这个可以配置,建议不要存储太大的东西,避免同步操作时间过长。
znode类型
短暂znode:回话结束,zookeeper就会把短暂znode删除,短暂znode不可以有子节点。
持久znode:回话结束也不会被删除,除非客户端明确要删除此znode,持久znode可以有子节点。
对于在特定时刻需要知道有哪些分布式资源可用的应用来说,使用短暂znode比较合适。

znode的观察机制
znode以某种方式发生变化时,“观察”(watch)机制可以让客户端得到通知。可以针对ZooKeeper服务的“操作”来设置观察,该服务的其他操作可以触发观察。比如,客户端可以对某个客户端调用exists操作,同时在它上面设置一个观察,如果此时这个znode不存在,则exists返回false,如果一段时间之后,这个znode被其他客户端创建,则这个观察会被触发,之前的那个客户端就会得到通知。

zookeeper的一些基本操作如下:

 

 

 

操作描述create创建一个znode(必须有父节点)delete删除一个znode(该znode不能有任何子节点)exists测试一个znode是否存在,并且查询它的元数据getACL,setACL获取/设置一个znode的ACLgetChildren获取一个znode的子节点名字列表getData,setData获取/设置一个znode所保存的数据sync将客户端的znode视图与ZooKeeper服务端同步



Zookeeper中的更新操作是有条件的。在使用delete或者setData操作时必须提供被更新znode的版本号,如果版本号不匹配,则更新操作失败。一般情况下设置-1即可。 

API
目前主要有java和C两种客户端,每种操作都有同步和异步两种执行方式。
观察触发器
可以设置观察的操作:exists,getChildren,getData
可以触发观察的操作:create,delete,setData
下面给出一些事件截图:









 

 

NodeCreated:节点创建事件
NodeDeleted:节点被删除事件
NodeDataChanged:节点数据改变事件
NodeChildrenChanged:节点的子节点改变事件

下面我们再来看下ACL(zookeeper的访问控制列表),每个znode被创建时都会带有一个ACL列表,用于决定谁可以对它执行何种操作。

ACL权限允许的操作CREATE创建节点create("name")READgetChildren()  getData()WRITEsetDataDELETEdelete("name")删除节点ADMINsetACL()设置权限


每个ACL都是身份验证模式、符合该模式的一个身份和一组权限的组合。身份验证模式有三种:
digest:用户名,密码

host:通过客户端的主机名来识别客户端

ip: 通过客户端的ip来识别客户端

所以我们可以类似这样构建一个ACL类:
new ACL(Perms.READ,new Id("host","example.com"));
这个ACL对应的身份验证模式是host
符合该模式的身份是example.com
权限的组合是:READ


下面给出一个API连接zookeeper的示例:

Java代码 复制代码  收藏代码
  1. package com.util;  
  2.   
  3. import java.util.concurrent.CountDownLatch;  
  4.   
  5. import org.apache.zookeeper.WatchedEvent;  
  6. import org.apache.zookeeper.Watcher;  
  7. import org.apache.zookeeper.ZooKeeper;  
  8.   
  9. /** 
  10.  * 测试zookeeper的连接 
  11.  * @author 三劫散仙 
  12.  *  
  13.  * ***/  
  14. public class Test {  
  15.       
  16.       
  17.       
  18.     public static void main(String[] args)throws Exception {  
  19.           
  20.           
  21.           
  22.         ZooKeeper  zk=new ZooKeeper("10.2.143.5:2181", 5000, new Watcher() {  
  23.             CountDownLatch down=new CountDownLatch(1);//同步阻塞状态  
  24.             @Override  
  25.             public void process(WatchedEvent event) {  
  26.              if(event.getState()==Event.KeeperState.SyncConnected){  
  27.                  down.countDown();//连接上之后,释放计数器  
  28.              }  
  29.                   
  30.             }  
  31.         });  
  32.           
  33.         System.out.println("连接成功:"+zk.toString());  
  34.         zk.close();//关闭连接  
  35.     }  
  36.   
  37. }  
package com.util;

import java.util.concurrent.CountDownLatch;

import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;

/**
 * 测试zookeeper的连接
 * @author 三劫散仙
 * 
 * ***/
public class Test {
	
	
	
	public static void main(String[] args)throws Exception {
		
		
		
		ZooKeeper  zk=new ZooKeeper("10.2.143.5:2181", 5000, new Watcher() {
			CountDownLatch down=new CountDownLatch(1);//同步阻塞状态
			@Override
			public void process(WatchedEvent event) {
			 if(event.getState()==Event.KeeperState.SyncConnected){
				 down.countDown();//连接上之后,释放计数器
			 }
				
			}
		});
		
		System.out.println("连接成功:"+zk.toString());
		zk.close();//关闭连接
	}

}


打印效果如下:

Java代码 复制代码  收藏代码
  1. 连接成功:State:CONNECTING sessionid:0x0 local:null remoteserver:null lastZxid:0 xid:1 sent:0 recv:0 queuedpkts:0 pendingresp:0 queuedevents:0 


已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



2016年分析领域的5大预测

$
0
0

PoF_wordle

1、机器学习在企业生根发芽

机器学习(Machine learning)的历史可以追溯到 1950 年,但直到最近,它都只是精英人才的领域并长期被人忽视。我预言机器学习会就此稳步发展,因为许多大型企业正在接纳机器学习。如今除了研究者和数字时代原住民,企业也在探索如何把机器学习变为生产力。在一些已经规范化的行业,模型解释性较差,曾导致模型难以应用。如今这些行业的从业者使用机器学习,寻找更多创造性的方法,从模型中选择变量,而这些变量之后能由常用工具进一步构建。机器学习从多个学科中获取营养,所以未来预计会产生更多跨学科的兴趣。回想去年 INFORMS 年会的主题,Dimitris Bertsimas 讲“现代优化视野下的统计与机器学习”( Statistics and Machine Learning via a Modern Optimization Lens )。我的同事 Patrick Hall 也对于“为什么是机器学习?为什么是现在?”(Why Machine Learning? Why Now?)这一话题给出了他的看法。

2、物联网大潮降温,面对现实

根据 Gartner 公司的新科技周期理论(Hype Cycle)来看, 物联网 (Internet of Things, IoT)正处在科技周期的顶峰。但在 2016 年我预计物联网这个概念将有所降温,开始面对现实。如何采集是一个很实际的障碍——信息太多了。我的一个同事正在把我们新大楼的HVAC 暖通系统,作为一个物联网测试项目进行分析。这栋楼里到处都是传感器,但获取数据却并不容易。设施部门告诉他这是IT部门的职权,IT部门把他又踢到了制造商那里,因为 HVAC 收集数据之后发送给了制造商。“数据所有权”是一个在逐渐浮现的议题:你生产了数据,却无法获取它。如何证实自己的价值是物联网面对的更大挑战。物联网在企业级的整体生产应用依然有限。物联网给出的承诺无与伦比,所以在 2016 年让我们期待早期使用者们能解决问题,给出答案。

3、 大数据走出喧嚣,让模型变得丰富

大数据已经走出了喧嚣,产生了实际的价值。如今的建模者可以获取的数据种类前所未有地丰富(例如,非结构数据,地理空间数据,图像,声音),而这些数据使得模型可以变得更加丰富。大数据的另一新进展来自各类竞赛,这些竞赛超越了之前游戏化的形式,通过众包和数据分享产生了实际价值。拿前列腺癌 DREAM 挑战为例,参赛队伍使用四种临床诊断的匿名数据挑战开放的临床研究问题。这些数据来源众多,大部分是第一次公之于众。参赛队伍的数目史无前例,最终的获胜者战胜了之前此领域尖端研究者开发的模型。

4、通过分析提高信息安全

随着物联网发展,传感器的广泛使用肯定让数码空间的犯罪分子感到兴奋。他们使用这些设备,用一种缓慢而低调的木马手段进行劫持。许多传统的侦查手段对此无效,因为侦查不再是寻找一个稀有事件的过程,而需要对情境中事件的累积进行理解。跟物联网一样,信息安全面对的一个挑战和数据有关。我预计先进的分析作为追踪数据的手段,能为侦查和预防做出新的贡献。很可惜,本文无法谈论大数据的合作中正在发展出的方法,因为我们不想让坏蛋知道我们是怎么发现它们的。这方面的许多优秀工作都是在高度安全的隔离环境中完成的。不过,2016 年 SAS 和其他各方仍会高度关注信息安全。

5、分析驱动着 企业 与学界加强互动

北卡罗来纳州立大学的高级分析研究所(The Institute for Advanced Analytics, IAA)关注分析领域的硕士项目数量增长。新的硕士项目与日俱增。企业的招聘需求促进了增长,但同时我也看到了它们对于研究的兴趣。越来越多的企业在设立学术扩展部门,并表现出对于研究合作的浓厚兴趣。有时这种兴趣超越合作伙伴关系,转而直接雇佣学界名人。这些学界名人可能是休假期间来工作,或者在学界和企业往返。例如,机器学习顶尖研究者 Yann LeCun 曾在贝尔实验室工作,也曾是纽约大学的教授,曾是建立纽约大学数据科学中心的主管,现在在 Facebook 带领人工智能研究团队。INFORMS(运筹学与管理科学研究协会),通过为学界提供与分析有关的教学材料的方式,支持这种产学互动。2016 年 INFORMS 会为业界提供一个可查询的、分析领域(硕士)项目的数据库以促进双方往来,并提供新的 Associate Certified Analytics Professional 证书来帮助选拔毕业生。

您可能也喜欢的文章:

缔元信:2015年12月第五周热门车型销量预测

中国人民银行:2016 年中国宏观经济预测

预测2016年VR元年将遭遇哪些问题和机遇

ReadWrite:2013年的14个预测

App Annie :2016年热门应用预测
无觅

spring的三种注入方式

$
0
0

spring的三种注入方式:

1、属性注入

2、构造方法注入

3、工厂方法注入

 

属性注入:

属性注入需要注意的是在bean的配置时属性名称是setter方法的名字而不是字段名称,如:

 

<bean id="car" class="com.za.Car"><property name="IDCard"><value>123</value></property></bean>

 而Java类:

 

 

Class Car{
    private Integer iDCard;
    public void setIDCard(Integer iDCard){
        this.iDCard=iDCard;
    }
}

 如果property属性中name写成了iDCard 当启动spring时就会报错

 

 

构造方法注入:

当一个类中只有一个有参构造并且入参类型不一致时:

 

Class Car{
    private String name;
    private Double price;
    public Class(String name,Double price){
        this.name = name;
        this.price = price;
    }
    //setter、getter...
}

bean的xml配置:

 

 

<bean id="car" class="com.za.Car"><constructor-arg type="java.lang.String" value="hongqi"/><constructor-arg type="java.lang.Double" value="555555"></bean>

  当只有一个入参并且入参类型有重复时:

Class Car{
    private String name;
    private String CarNo;
    private Double price
    public Class(String name,String CarNo,Double price){
        this.name = name;
        this.CarNo= CarNo;
        this.price=price;
    }
    //setter、getter...
}

 此时bean的xml配置使用type就不可以了,要使用index来区分:

<bean id="car" class="com.za.Car"><constructor-arg index="0" value="hongqi"/><constructor-arg index="1" value="苏A00000"><constructor-arg index="2" value="555555"></bean>

 当构造方法有重载并且入参类型重复时,这时使用type和index来结合使用加以区分(例子省略)

构造方法注入可能会出现的一种情况是:循环依赖问题,比如在Car的构造方法中依赖了Wheel类,而Wheel类的构造方法中也依赖了Car类,此时启动spring容器就会有问题。解决方法:修改bean代码把构造方法注入修改为属性注入就可以了。

工厂方法注入:

非静态工厂方法:

public CarFactory{
    public Car creatCar(){
        Car car = new Car();
        car.setName("红旗");
        return car;
    }
}

 bean配置:

<bean id="car" class="com.za.Car" factory-bean="carFactory" factory-method="creatCar"></bean><bean id="carFactory class="com.za.CarFactory/>

 因为是非静态的,所以要有一个工厂bean,在工厂注入时引用

静态工厂方法:

public CarFactory{
    public static Car creatCar(){
        Car car = new Car();
        car.setName("红旗");
        return car;
    }
}

 bean配置:

<bean id="car" class="com.za.CarFactory" factory-method="creatCar"/>

 省去了工厂bean的配置

 

 

 

 

 



已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



微信支付js api

$
0
0

       JSAPI 支付前需要调用 登录授权接口获取到用户的 Openid 。所以需要做一次授权,这次授权是不弹出确认框的。
其实质就是在用户访问:

//使用jsapi接口
$jsApi = new JsApi_pub();

//=========步骤1:网页授权获取用户openid============
//通过code获得openid
if (!isset($_GET['code']))
{
    //触发微信返回code码
    $url = $jsApi->createOauthUrlForCode(WxPayConf_pub::JS_API_CALL_URL);
     Header("Location: $url"); 
 }else
 {
     //获取code码,以获取openid
     $code = $_GET['code'];
     $jsApi->setCode($code);
     $openid = $jsApi->getOpenId();
}

 这一步的最终结果就是获得了当前用户的openid

JS API支付

前面的准备工作做好了以后,JS API根据prepay_id生成jsapi支付参数
生成代码如下:

//=========步骤3:使用jsapi调起支付============
$jsApi->setPrepayId($prepay_id);
$jsApiParameters = $jsApi->getParameters();

 生成的json数据如下

 

 

 

{"appId": "wx8888888888888888","timeStamp": "1414411784","nonceStr": "gbwr71b5no6q6ne18c8up1u7l7he2y75","package": "prepay_id=wx201410272009395522657a690389285100","signType": "MD5","paySign": "9C6747193720F851EB876299D59F6C7D"
}

 

在微信浏览器中调试起js接口,代码如下

<html><head><meta http-equiv="content-type" content="text/html;charset=utf-8"/><title>微信安全支付</title><script type="text/javascript">
        //调用微信JS api 支付
        function jsApiCall()
        {
            WeixinJSBridge.invoke(
                'getBrandWCPayRequest',<?php echo $jsApiParameters; ?>,
                function(res){
                    WeixinJSBridge.log(res.err_msg);
                    //alert(res.err_code+res.err_desc+res.err_msg);
                }
            );
        }

        function callpay()
        {
            if (typeof WeixinJSBridge == "undefined"){
                if( document.addEventListener ){
                    document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
                }else if (document.attachEvent){
                    document.attachEvent('WeixinJSBridgeReady', jsApiCall); 
                    document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
                }
            }else{
                jsApiCall();
            }
        }</script></head><body></br></br></br></br><div align="center"><button style="width:210px; height:30px; background-color:#FE6714; border:0px #FE6714 solid; cursor: pointer;  color:white;  font-size:16px;" type="button" onclick="callpay()" >贡献一下</button></div></body></html>

 当用户点击“贡献一下”按钮时,将弹出微信支付插件,用户可以开始支付。

 

支付通知
支付成功后,通知接口中也将收到支付成功的xml通知 :

<xml><appid><![CDATA[wx8888888888888888]]></appid>  <bank_type><![CDATA[CFT]]></bank_type>  <fee_type><![CDATA[CNY]]></fee_type>  <is_subscribe><![CDATA[Y]]></is_subscribe>  <mch_id><![CDATA[10012345]]></mch_id>  <nonce_str><![CDATA[60uf9sh6nmppr9azveb2bn7arhy79izk]]></nonce_str>  <openid><![CDATA[ou9dHt0L8qFLI1foP-kj5x1mDWsM]]></openid>  <out_trade_no><![CDATA[wx88888888888888881414411779]]></out_trade_no>  <result_code><![CDATA[SUCCESS]]></result_code>  <return_code><![CDATA[SUCCESS]]></return_code>  <sign><![CDATA[0C1D7F2534F1473247550A5A138F0CEB]]></sign>  <sub_mch_id><![CDATA[10012345]]></sub_mch_id>  <time_end><![CDATA[20141027200958]]></time_end>  <total_fee>1</total_fee>  <trade_type><![CDATA[JSAPI]]></trade_type>  <transaction_id><![CDATA[1002750185201410270005514026]]></transaction_id> </xml>

 

 

 

 

 

 

 

 

 



已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



MySQL 5.7 新特性大全和未来展望

$
0
0
本文转自微信公众号: 高可用架构
作者:杨尚刚
引用
美图公司数据库高级 DBA,负责美图后端数据存储平台建设和架构设计。前新浪高级数据库工程师,负责新浪微博核心数据库架构改造优化,以及数据库相关的服务器存储选型设计。之前在「高可用架构」发表的《单表 60 亿记录等大数据场景的 MySQL 优化和运维之道》广受好评。

2015 年最重磅的当属 MySQL 5.7 GA 的发布,号称 160 万只读 QPS,大有赶超 NoSQL 趋势。



上面这个图是 Oracle 在只读场景下官方测试的结果,看上去 QPS 确实提升很大。不过官方的硬件测试环境是很高的,所以这个 160 万 QPS 对于大家测试来说,可能还比较遥远,所以实际测试的结果可能会失望。但是,至少我们看到了基于同样测试环境,MySQL 5.7 在性能上的改进,对于多核利用的改善。

提高运维效率的特性
MySQL 5.7 动态修改 Buffer Pool
从 MySQL 5.7.5 开始可以在线动态调整,对运维更友好。很多人都经历过 Buffer Pool 过大或过小调整需要重启实例,运维成本非常高,尤其是主库或其他核心业务。

MySQL redo log 大小
5.5 <= 4G, 5.6 +<= 512G
当然这个也不是越大越好,但是提供了可以 尝试的机会,越大的 redo log 理论会有更稳定的性能。当然带来的风险就是故障恢复时间会更长。

下图就是不同 redo 大小的性能对比,主要是看性能抖动情况



innodb_file_per_table
默认值 Off <= 5.6.5 <=On,独立表空间优点很明显。尤其可以使用 InnoDB Transportable tablespaces,可以像 MyISAM 一样快速迁移表。

query cache
1 <= 5.6.8 <= 0,默认关闭。整体来说关闭 query cache 是利远大于弊,官方最终也选择了关闭。

SQL_Mode 变为Strict mode
SQL要求更严格,version < 5.6.6 sql_mode 为空,最为宽松,不够严谨。
5.6.6 < version < 5.7.4
  • NO_ENGINE_SUBSTITUTION

version > 5.7.9
  • ONLY_FULL_GROUP_BY
  • STRICT_TRANS_TABLES
  • NO_ZERO_IN_DATE
  • NO_ZERO_DATE
  • ERROR_FOR_DIVISION_BY_ZERO
  • NO_AUTO_CREATE_USER NO_ENGINE_SUBSTITUTION

以 NO_ZERO_DATE 为例,如果你原表里有 0000-00-00 这种数据,在 MySQL 5.7 使用默认 SQL_Mode 时候改表时候就会报错了。

binlog_rows_query_log_events
默认关闭 ,可选打开,建议打开,还是比较有用的。可以看到row格式下的sql语句,方便排查问题和恢复数据。
以 NO_ZERO_DATE 为例,如果你原表里有 0000-00-00 这种数据,在 MySQL 5.7 使用默认 SQL_Mode 时候改表时候就会报错了。

binlog_rows_query_log_events
默认关闭 ,可选打开,建议打开,还是比较有用的。可以看到row格式下的sql语句,方便排查问题和恢复数据。



上图就是开启之后 binlog 解析出来的内容,可以看到正常 SQL。

max_execution_time
5.7.4 刚引入名字是 max_statement_time,后来改成 max_execution_time
单位是毫秒,SQL 语句的超时中断,自我保护的一种方案。
只针对 select,也可以在 sql 里指定。如果 percona 版本 的话,这个参数更暴力,对所有请求生效慎用。

replication info in tables
crash-safe slave 方案,最早 Google 做的方案是存储在事务日志里。单独存储更灵活,可以解决很多从库宕机后 duplicate key 问题。



innodb_numa_interleave
建议关掉 numa。最早 Twitter 开源分支里有提供,也可以启动实例时候设置 numactl –interleave all,不过实际线上使用系统默认 numa 策略,并没有遇到过因为 numa 导致的 swap 问题。

动态修改 replication filter
方便做拆分或做级连复制时候使用,可以通过 change 动态修改。如果用过 replication filter 应该清楚 这个还是比较有用的。



优化器 Server 层改进

优化器主要还是基于 cost model 层面和给用户更多自主优化



可配置 cost based optimizer,mysql.server_cost 和 mysql.engine_cost。



New JSON 数据类型和函数支持。当然 JSON 也可以存在 Text 或 VARCHAR 里用内置 json,更容易访问,方便修改。



支持生成列(虚拟列),以及虚拟列上索引。

CREATE TABLE order_lines (orderno integer,
lineno integer,
price decimal(10,2),
qty integer,
sum_price decimal(10,2) GENERATED ALWAYS AS (qty * price) STORED );

简化查询,有 virtual 和 stored 两种情况,感觉这个功能还是比较小众。

下图是二者对比



5.7 还对 explain 做了增强,对于当前正在运行查询 explain。
EXPLAIN [FORMAT=(JSON|TRADITIONAL)] FOR CONNECTION <id>;

InnoDB 层优化

InnoDB 层核心还是拆分各种锁,提高并发。只读事务优化就是其中一个例子
不再使用只读事务 list,重构 MVCC 代码,不为只读事务分配事务 id,降低内存开销。

如何使用只读事务:
start transaction read only
开启 autocommit 下的不加锁的 select 语句

原生支持分区 Native Partitioning,之前版本分区表是放在 server 层管理的,现在是在引擎层面支持,更节省内存,分区越多,效果越明显。

atomic write, disable double write,MySQL 5.7 开始支持 atomic write,成本高,性价比不算高,需要底层存储硬件支持,感觉比较鸡肋。

支持 spatial index 空间索引
基于 R tree 实现
目前只支持 2D 数据类型
支持 GeoHash 和 GeoJson ,提高数据查找效率

Transparent page compression
需要文件系统支持 PUNCH HOLE,ext4 和 xfs 都可以支持,测试效果比目前压缩效果好一些。适配更多压缩算法,支持 lz4 zlib,功能上还不够稳定和成熟。



performance_schema 改进,增加了很多统计信息表,metadata_locks,status_by_host ,status_by_user,status_by_thread,获取当前执行的慢查询 top10,可以获取到更多状态信息。



上图是对单个 thread_id 吞吐量统计信息

新增加的 sys 数据库,相当于对 performance_schema 的数据整合。IO 信息和索引信息,相当于 Oracle 里的 V$ Catalog,基于 ps_helper 实现。基于 performace schema 画的 SQL 执行时间分布图。



replication改进



上图是 MySQLreplication 的发展历史

最大的亮点 GTID 增强,支持在线调整 GTID。当然也不是简单的 SET @@GLOBAL.GTID_MODE = ON,步骤也是很复杂,不过至少不用停机,也是进步
从库可以不开启 log_slave_updates,通过引入 gtid_executed 表实现,对性能优一定帮助,大大简化切换流程。增强半同步复制,确保从库先收到,设置半同步从库个数。使用 mysqlbinlog 作为伪 slave 是个不错方案。



上图就是 loss-less 半同步和之前的区别

并行复制优化 ,Database 5.6 默认并行复制。logical-clock 5.7 引入,一个组提交内事务都可以并行,可以达到接近主库并发效果。



不同复制方案的可用性级别



5.7 引入的 group replication 也是为了提高可用性。多主复制,多点写入,内部检测冲突,保证一致性,自动探测。支持 GTID,共享 UUID,只支持 InnoDB,不支持并发 DDL。



安全方面密码自动过期,这个要注意,建议关闭。default_password_lifetime 控制过期默认一年。锁定用户,支持 SSL 访问,server 端利用 OpenSSL 加密。

工具支持 mysqlpump,并行版 mysqldump,也是替换原生 mysqldump 和 mydumper 的。--watch-progress 查看 dump 进度,--compress-ouptut 压缩。mysqldump 可以做为一个伪 slave 接受 binlog,做 binlog 备份的匪巢的方案,也支持 SSL。

从整体来说,MySQL 5.7 做的改进还是非常有吸引力的,不论是从运维角度还是性能优化上,当然真正在生产环境上遇到问题时在所难免的,要做好踩坑的准备。

未来发展

RDS服务
应该大家很多人都用过 RDS 服务,确实降低了使用成本。下图是各种架构区别,普通物理服务器,EC2,RDS,优势很明显。



阿里云 RDS MySQL,支持读写分离,多 zone,支持异地容灾,压缩(支持 TokuDB),阿里云宣称的一大亮点,代码控制能力强。

老牌 RDS 服务 Amazon RDS,目前有 MySQL Aurora 和 MariaDB 这三种。Aurora 虽然目前来说,会有一些问题,但是方向还是不错的。

HA 架构,从可用性来说 Galera > Aurora > MHA



关于 RDS 服务的一些建议,数据库经验积累还是很重要的,面临过或解决的问题越多,提供的服务也相对越稳定。RDS 提供便利的同时,也存在数据安全的风险和 RDS 服务本身的 SLA 保证,是用户更关心的。

如何降低云服务商故障对业务影响,其实从 RDS 提供的性能指标考量,如果使用同等性能配置的物理服务器,RDS 成本还是偏高一些的。从功能上来说大部分 RDS 还算完备,具体哪些坑实际用的不多不好评判。

存储层的优化
LSM Tree : LevelDB, RocksDB,适配高性能存储 SSD,更高的压缩比,,更低的写入放大比例,缺点读性能差,适合写多读少场景。
MyRocks: MySQL + RocksDB



统层优化
系统优化主要还是 IO 方面的,blk-mq、scsi-mq、IO 中断多队列、3D Xpoint 接近内存的访问速度和非易失存储,说不定以后整个数据库实例都可以放在这种介质上面,也是一场新的变革。

运维经验总结

数据恢复
备份 xtrabackup 物理为主,mydumper/mysqlpump 为辅,binlog 备份也是很重要的。恢复导出 SQL 文件正常恢复。
myloader
xtrabackup
InnoDB transportable space
online ddl

5.6 和 5.7 虽然一直在改善,但是在主从同步问题上依然有问题,下图是目前主流的 online DDL 方案。



总体使用 pt-osc 更通用一些,pt-osc 注意的一些坑,添加唯一键,导致数据丢失延时备份。行格式下,只在从库使用 OSC,丢数据。

MySQL 慢日志系统
基于 pt-query-digest logstash 和 Anemometer 实现,可以定期跟踪线上业务慢查询优化。



系统状态收集
基于某些特定条件触发,比如 MySQL 连接数增长到一定阈值,收集当前系统状态,方便后续问题排查。比如系统 top mpstat strace tcpdump 等,MySQL 的 processlist show engine innodb status 等。



Q & A

1、请问 query cache 关闭的原因,MySQL 是否支持全同步?
query cache 访问需要获取一个全局锁,高并发时候争用很严重。更主要的是 query cache 缓存的效果并不好。原生 MySQL 的话,5.7 里的 group replication 是支持全同步的,还有目前的基于 galera 实现的 percona xtradb cluster 也是支持全同步的。

2、有没有 MySQL 的读写分离中间件?最好没有语言限制的,谢谢!
目前开源的中间件很多了,比如 mycat、atlas、vitess等,你指的语言限制是指的对开发语言的兼容吧,我觉得每种都兼容的很好的 不多,毕竟现在的中间件都是基于开发者本公司的现状开发的,在兼容性上不太能做到很完美。现在官方做了个MySQL Fabric,现在应该也 GA 了,后面可以关注一下。

3、你们备份的策略(比如完整多久一次,增量多久一次,备份恢复测试多久一次), 备份对线上系统的影响如何控制都是选一个slave备份的么?
我们目前的策略是以周备+日备,结合 binlog 备份,理论可以恢复到一周内任意时间点。全部是全量备份,没有做增量。备份恢复测试,我们目前还没有做,基于xtrabackup备份数据可靠性还是很高的 ,之前在新浪是有实现备份测试的,大概2-3天能对线上备份端口做一轮测试。目前备份是选择一个线上从库来做的,控制影响的话主要是通过对备份工具 xtrabackup 的并行度和 IO 来进行限制。

4、请问关于 DB 管理的问题,线上数据库是否可开放给业务方技术人员查询?开放到什么程度?有没有必要做 WEB 查询平台?
开发人员还是有必要开放的,如果完全禁止,很多业务数据查询的事情可能就需要 DBA 介入,其实效率是比较低的。当然在权限上可以限制,比如只开放读权限,禁止 dump 这种。对核心库限制要更严格一些。如果能做 Web 平台 当然更好,可以在入口层做限制,后端控制数据访问频度和策略等。

5、当插入一条数据,非唯一索引是通过 change buffer 更新提高并发,那么唯一索引或者主键如何更新呢?保证高并发?
唯一索引或主键需要看更新或插入的数据在不在 Buffer Pool,没有的话就需要去磁盘读取数据做检测,需要维持约束。

6、" 聚簇索引的数据的物理存放顺序与索引顺序是一致的,即:只要索引是相邻的,那么对应的数据一定也是相邻地存放在磁盘上的 ",有个疑问,某条数据的更新,是新生成一条,老本的打上版本号,然后定期删除。这样有个问题,新数据应该在新的物理地址。聚簇索引是不是失效了?
聚簇索引在实际磁盘存储也不是严格顺序的,并且老的版本是存储在 undo里,也就是 ibdata 共享表空间里 ,和实际数据不冲突。

7、MySQL 5.7 有没有对复合索引做优化,在违背 left most prefixing 时也能使用复合索引?
最左前缀的原则比较难突破,当然在 5.6 引入了 index condition pushdown 机制,可以在存储引擎层面做一些过滤,减少过滤行数,会有一定优化。

感谢 mengyidan1988投递这篇资讯

资讯来源: 高可用架构

已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



魅族科技宣布裁员约200人 以后每年裁5%

$
0
0

【TechWeb报道】1月4日消息,魅族科技宣布裁员约5%。

魅族科技人力资源部在1月1日发布内部邮件称,为了优化团队结构,每年进行一次裁员,2016年1月1日部分员工将离开公司。

1

魅族科技宣布裁员约200人 以后每年裁5%

2

在裁员比例方面,根据总裁白永祥在内部群上的说法,本次裁员不会超过5%。

根据白永祥在内部群有关“魅族目前接近4000人”的说法,5%的比例将意味着此次裁员波及200人左右。

魅族科技一位发言人向TechWeb透露,以后每年会进行一次约5%比例的裁员。

在本此裁员补偿方面,转正员工在年终额外获得一个月工资补偿之外,再根据2N+1(N为在魅族工作年限)月工资进行补偿,未转正员工将获得1个月工资补偿。(小峰)

蚕豆网微信

[转载]三种风格的Dashboard仪表板设计

$
0
0
三种风格的Dashboard设计
Dashboard是BI项目的高级应用,国内一般称作仪表盘/仪表板、决策面板等。Dashboard应该是个什么样子?在个人制作、非BI系统领域,根据我的了解,至少存在三种风格或流派的仪表板做法。

一、豪华派

这类Dashboard,界面极其豪华,强调用户交互性。各种华丽精美的图表和控件对象,极尽炫酷之能事,相当吸引眼球。


特点:
1、使用仪表盘(量表)、温度计、进度条、地图等形象性部件
2、使用各种超酷的选择器,如旋钮、滑标、鱼眼菜单、地图菜单、股票条等
3、追求炫酷,部件多具惊艳的水晶质感,图表多有优美的动画效果
4、用户交互性强,擅长表现what-if分析

但是,当我们看到这样的仪表板时,往往会惊叹于其界面的豪华和制作的精美,早已忘了分析决策的事情。特别是在一些What-if分析模型中,我们往往会沉溺于把玩其动态效果。一般见于高端商务演示和BI系统,不适合于书面报告。

工具上以BO的 Xcelsius为代表,需要一定的开发技术。BO的网站上原来有很多showcase的,现在不知道放哪里去了。现在还推出了Engage、Present,还没有试过。 brightpointinc.com是一家为客户提供Dashboard设计开发的公司,网上也有一些案例。本博最近介绍的美国大选仪表板也是此类例子。

这种类型在实际工作中当然会大受欢迎,但工具难以获得,制作和学习成本较高。并且华丽的东西容易让人审美疲劳,毕竟天天吃鲍鱼燕窝也令人倒胃口,不如粗茶淡饭来得舒服。


二、ET拥趸派

塔夫特(ET)是数据可视化设计的大师,他反对在图表中使用效果、色彩等图表垃圾,所以按他的理论做出来的图表都素不啦叽的。塔夫特发明了叫做sparkline的微线图,另外一个人Few发明了叫做bullet的图,这两类图构成了这类Dashboard的主要部件。


其特点非常明显,也易于模仿:
1、使用bullet显示kpi完成情况
2、使用sparklines显示kpi13个月的趋势
3、使用bar图显示Top10 或者bottom10
4、使用红点显示预警
5、拒绝花哨,整个Dashboard的颜色只有黑白灰和预警的暗红点
6、此外,限制使用饼图,他们对饼图很反感

这类Dashboard不强调交互性,要求控制在一屏以内,一般见于个人报告和BI系统。

工具上以bonavista公司的 microchart为代表,在单元格中输入他们的函数,即可产生单元格内的微图表。在他们的网站上有很多类似风格的Dashboard可参考。仅用Excel也可做出类似效果的sparkline和bullet图表,不过要稍微麻烦点。

这种类型在实际工作中可能会有限制,比如一般人看不懂sparkline、bullet图,你要先教会他们,还要他们认同这类图表。并且一般人可能难以忍受仅使用黑白灰的单调。



三、一页式分析报告

Kyd这个人很了不起, 他的网站上的所有内容都值得细细研读。他受《商业周刊》每周数据栏目的启发,开发了一套制作一页式分析报告的方法,他称之为Dashboard reporting。方法技巧可以说平淡无奇,妙就妙在他的思路和态度。

(最后一个是商周报告的原形)

其特点是:
1、运用“小而多”策略,即大量使用邮票般大小的迷你图表
2、图表与表格的配合
3、页面精心布局,严格控制在一页纸或一个屏幕内
4、追求专业,颜色运用以商业杂志为榜样

这种做法适合于个人制作书面报告,不强调交互性。BI系统也可参考。

工具上使用最普通的Excel即可,不需要任何其他软件,均使用最基本的excel方法,所以几乎是零成本。如果设计得当,每月数据刷新只需要调整一个控制参数即可。

这种类型的Dashboard报告,一张A4纸上,图、表、文、色,相得益彰,关键信息一目了然,尤其适合于个人书面报告,让你的数据报告象商业杂志般专业,实际工作中必定大受欢迎。本博也决定进一步钻研这种做法。


除此三种典型风格外,其他类型Dashboard的一般居于三种风格之间,或豪华一点或朴素一点,或图多一点或表多一点,控件美观或者丑陋一点,设计精良或者粗糙一点,等等。


不管哪种类型的Dashboard,要做到优秀,最终不是在于使用何种工具和技术,而在于对业务的深刻理解,对关键信息的准确把握,再加上专业的设计思路和规范,从而可设计出优秀的仪表板,帮助决策者分析问题、制定决策,而这也是最困难的。

遗憾的是,Dashboard作为BI项目的四大应用(报表、OLAP、即席查询、仪表板)中的高端应用,在国内通信行业BI厂商的产品中,还没看到比较出色的Dashboard,一般就是堆砌几个图呀表呀的,然后,诺,这就是决策仪表盘、领导驾驶仓了。

看来,优秀的仪表板只能来自于对客户业务最了解的人,而这往往只能是客户内部的优秀分析人员。


 

Docker 架构私有云的机遇和挑战

$
0
0

本文系 ArchSummit 大会 CODING 工程师王振威演讲实录。

图片

大家好,非常高兴在这里跟大家分享,我是王振威,来自 Coding 的一个程序员。今天给大家带来的分享主要是我们团队在使用 Docker 改进原有的业务系统的演进计划和实施的经验教训。

图片

说起 Docker,必须要介绍 Docker 是什么东西,为什么中小企业私有云适合使用 Docker。其次是我们做一套架构系统的变迁,总是事出有因的,我们必须介绍一下为什么变迁。第三是怎么变迁,作为中小型企业要想把业务假设到私有云上,如何一步一步来做。最后我们在使用Docker的过程中遇到了比较棘手和麻烦的问题。

第一,Docker,在座有相当一部分人已经了解了,它是容器技术,跟私有云有什么关系?那么首先要解释一下什么叫私有云。

私有云用这样一句话来形容是最为贴切的:就是企业内部的服务于企业自身的云服务平台。企业内部有很多服务器,有不同的业务系统,但是想让这些业务系统高效地运行起来,我们往往会采用类似于 IaaS 或者 PaaS 的技术来搭建这个平台。那么 Docker 为什么适用于搭建一个私有云的企业平台呢?因为容器技术比传统的VM技术成本更低、效率更高。关键点在于这种技术是兼容性又好的,可以使我们传统的架构变迁显得更为平滑,这是最为重要的一点。另外,容器技术一大特点就是快速实现隔离,统一调配。有如下三快:

  • 构建快
    一个应用最终的形式往往是环境加上程序包,形成最终的镜像,image 就是程序本身外加环境,Docker 让我们可以用 Dockerfile 之类的技术定义镜像,自动构建,免去在很多服务器上繁杂的安装配置应用程序环境的过程

  • 启动快
    容器相比虚拟机的启动速度是非常快的,开一台虚拟机的启动速度慢一点的一分钟,快一点的也要十几秒,但是容器往往可以做到秒级启动,这为我们后面所讲的容器化交付奠定了基础。

  • 迁移快
    应用以容器的方式标准化交付,这个主机跟另外一个主机只要安装了 Docker 就没有什么差别,image 不管扔到这里还是扔到那里都可以很快地正常运行。而传统的 VM,只是省去了我们购置租用物理服务器的过程,本质上来讲还是一个裸的操作系统,本来这个程序在 A 机运行,但 A 机挂了,现在来配置 B机,装了 JDK,发现不行,这个 JDK 版本不对啦,JDK 缺少了本地的库啦,之类一系列问题。但是如果用了 Docker,用了容器技术,它把这些依赖环境全打成 image,只要把 image 下载下来就行了,这是编程语言,框架无关的,因为应用的环境是跟着应用走的。

看一下现在的架构图

图片

开个玩笑。

如果我们的架构是这样的话那就没什么好讲了,我的意思是说一个成熟的以容器来做基层建设的私有云环境,最终的效果应该像巨轮一样,可以把所有的货舱都码放整齐,可以平稳地向前航行,这是基于容器的私有云的愿景。

有人会问了,如果说你之前的架构没问题,为何要迁移到这个环境来呢?

事出有因,假如传统的架构是很好的,我们没必要迁移到 Docker 这种私有云环境来,我们为什么要迁移?

有几个原因:

  • 第一是我们之前的业务系统随着时间的发展越来越多,不同的组件需要协同去做不同的工作,给运维带来了巨大的挑战,有 JAVA 写的程序,还有些程序制定了必须用 JDK7,一些部门觉得 JDK8 有些特性比较好用所以用了 JDK8,还有些组件是用 Ruby 写的,还有 Golang,NodeJS等等,目前我们系统中牵扯的系统语言已经达到了八九种,这对运维来讲是一个巨大的挑战,我们必须要给各种各样的程序准备各种各样的环境,维护,迁移都非常麻烦。

  • 另外配置混乱,当你应用的服务器数量越来越多,有的系统可能是用 upstart 来管理程序,有的是用 Supervisor , 有些程序可能只是个 定时任务。我们的编程语言每一种都会有自己的构建工具,构建工具对依赖的管理也不太一样。最终的结果是操作系统中的配置文件和各种黑科技补丁脚本散落在系统的各个角落,没人能找得到,也没人搞得懂。

  • 最后致命的一点是监控和资源的混乱, 监控混乱,如果是一个很简单的程序,往往只需要做到当发生错误,把这个错误日志打印出来,运维上看一下日志就行了。当涉及到几百台应用服务器,其中的各个组件每天打印上百万条、上千万条各种不同级别的日志的时候,运维是没有精力去了解的,我们只能做错误报告,做消息的推送,但是因整体系统混乱,每个应用有各自的方式,最终导致日志,错误监控都没能达到相应的预期。然后是混乱的资源,我们做 WEB 的应用往往出现白天是高峰期,晚上是低峰期,低峰期zi'yuanziyuan使用率很低,属于资源的浪费。另外有些业务在申请计算资源的时候不能提前预估到使用量有多少,申请的过多或者过少,运维又要经常承担着缩容扩容的问题。

  • 有因必有果,环境不匹配导致测试跟生产环境不一样,比如生产环境是 JDK8 跑的,某一个开发者本地用 JDK7 测试的程序,上去发现这个东西根本不对,虽然 JDK7 和 JDK8 的兼容性已经是99%以上,但是一个严谨的业务系统必须要做到测试环境跟生产环境是一致的。

配置混乱导致事故频发,做过运维的肯定了解,这个配置被谁改掉了,这个服务宕掉了,当你的组件越来越多的时候根本无从管理。监控不一致,资源效率低。计算资源的成本很高,却达不到相应的目标。所以之前那艘看起来航行很平稳的巨轮,在上面这四大原因的影响下,事实上是这样的。

上面这四点导致我们必须要统一架构,最终把整个业务系统迁移到基于 Docker 的类似于 PaaS 的私有云的平台。

架构变迁,作为一个架构团队的 Leader,在做架构变迁遵循的时候要掌握如下原则:

DevOps 变迁原则

  • 即面向未来,又不过于激进

  • 即追求稳定,又不过与保守

其实就是掌握平衡,追求一个度。我们用新技术,必然是为了解决旧技术的问题我们才用,但如果过于追求新技术,忽略了业务的重要性,你会发现你最终是得不偿失的。所以我们遵循的原则是既面向未来,又不过于激进,既追求稳定,又不过于保守。

关于技术选型,这是我们团队的做法。

OSContainerService DiscoveryConfigContainer Management
WindowsRocketConsulJSONK8s
UbuntuRunCEtcdINIMesos
CentOSDockerYAMLSwarm
RedhatCompose
UbuntuNone

容器技术现在有几种选择,Docker 本身的底层就是 RunC。谷歌内部有自己的容器技术,VMware 也有容器技术,但是就目前来讲,Docker 是最好的选择。服务发现我们用了 ETCD,我不再讲哪个软件好哪个软件坏,不同的软件会适用不同的业务场景,只有适合与不适合。

接下来我会讲具体的架构变迁三步走。

架构变迁三步走遵循的最重要的一点是平滑演进。我们都知道我们的业务系统是脆弱的,经不起风吹雨打,如果大动干戈搞一下,新的架构出问题了,业务系统是承受不住,技术部门也无法承受住其他部门带来的压力。所以我们必须有序平稳平滑的演进升级。微服务是这套升级的一个基础点,如果你的这些应用不是微服务,不是无状态化的,那你就没办法让多个实例协同工作。最后是软硬分离,分割计算资源和具体业务的强依赖,其实这个问题,在我们全部走完,只要在配置好的服务器环境装一个 Docker 就搞定了。

三步走的具体第一步是 Dockerize,什么叫 Dockerize?

先把应用无状态化,你可以采用一些集中式缓存这种技术让应用变得没有自己的状态,它随时起停,起多少份都是无所谓的,只要有负载均衡器就可以让这些组件对外提供一致的服务。当无状态化应用实现之后,我们就可以给这个应用写 Dockerfile 了,Dockerfile 构建的结果就是 Docker  image ,其本身就是应用和环境,第一行是from java jdk7,第二行设置应用程序,第三行把这个程序运行起来。

# Base
FROM java:jdk-7

COPY ./.src/target/app-1.0.jar /app/

# ENTRYPOINT
WORKDIR /app
CMD [ "java", "-Dfile.encoding=UTF-8", "-jar", "./app-1.0.jar" ]

这是很简单的 Dockerfile,不要看他简单,我推荐的是各位用 Docker 就应该这么用。不需要在 Dockerfile 里写一堆 apt-get install ,一大堆 run 命令这些东西,记住 Dockerfile 就是声明应用环境和应用本身。Docker 现在做的功能太多了,很多都是不怎么靠谱的,Docker 需要更专注于它本身作为容器的技术。完成无状态化应用和写完 Dockerfile 之后,这个程序就可以被打报成 Docker image 了,放到一个 Docker Host 上运行起来就得到了无状态的应用容器,也就完成了把应用装容器的过程。

架构变迁的第二步是管理你的容器。

不能说应用扔进去就不管了,如何管,管的办法有很多,容器技术这个圈里争论最多的就是编排技术。

容器的管理方式对 Docker 来讲,目前就三种:

  • 第一是直接管,我们都知道Docker 官方有一个 CLI 工具,只要装了 Docker 就可以使用这个 CLI 工具把指定的程序运行在容器里,这是更直接的方式。但明显我们有几十台上百台服务器的时候,不能每个都上去搞一下,虽然它更直接,但它比较麻烦。

  • 另外一个是 Docker remote API,更为灵活,提供了相关的编程接口来管理容器。

  • 最后是编排系统,它们更为复杂,定义的条条框框更多。我这里不推荐做架构渐变演化的团队采用。主要原因是,我们迁移到这些编排系统往往都是跳跃式的升级,不是平滑演进,业务系统不能容许直接把整个业务系统跳跃式升级,无法承担风险,出问题的回退预案也很难定制。当然如果是一个本身从零开始的系统,那你可以尝试一下,但也不保证这种编排系统就适应于你的业务系统。我们推荐一步一步走,先把这种应用变成容器,再来想办法管理这些容器。

很显然我们采用的是第二种选择。

配置文件配合 Docker remote API。根据实际情况,选择Docker的少量的一些特性,例如文件系统、网络、资源限定等这些成熟的,我们最为需要的功能,我们编写了一个便捷的操作工具 cli/web。

在配置文件中定义一个任务,名字写下来,这个任务用什么 image 跑,什么版本,运行在哪台机器上,注意这里,机器名并不跟具体的业务绑定,而是一个资源池,不管什么应用都是无差别的,只要是无状态的应用,所有的存储、依赖都通过网络的形式来解决,我们整个资源池就可以实现自由调度。

如果把这个应用绑定到某一些具体的特有的机器上的话,局限性比较大,万一这些机器出问题,将无法快速迁移。有一些选项是没填的,比如 port, port 其实是 Docker 支持把容器内的某个端口映射到容器外,我们没填这个东西是因为,我们默认在全系统级都只使用Docker的 host 网络模式。 host 模式下,Docker 内部容器的网络跟宿主机的网络是一样的,这是 Docker 所有网络模式中性能最高的,缺点是不能做隔离。

这里有人可能会问,为什么要放弃隔离呢?这里解释下没用 Docker 的高级的网络模式,以及 SDN、端口映射等的原因。就是没必要。注意我们讲的是私有云平台,私有云平台内部都是企业自身的业务,大部分业务都基于业务层面做隔离和权限就可以了, 所以 Docker 用 host 的模式运行就跟传统应用没有差别,不需要做 NAT,SDN,也不需要做端口影射,另外一个好处就是,对于应用来讲他们的依赖用容器和不用容器都是一样的,这完全符合我们要求的平滑演进。

图片

下面还有其他的配置,我们会通过环境变量控制一些应用内部的参数,因为我们的配置文件往往是打包到 image 里面,但是 Docker 这点挺烦的,改一个配置文件都要重新打一个 image,我们最终把配置项做成环境变量或者 CMD 参数,这样可以在组件间共享一些 image。

图片

这是我们用CLI在更新某个实例的时候打印出的内容,这是我们自己的定制的,它会告诉我们当前运行的实例的名字是什么,运行时间是什么等等一系列内容,只要选择指定版本代码的 Docker image,我们就可以完成全自动化的更新。

另外我们还部署了一套 DockerUI,这个软件总体用下来不是特别好用,这是它大概的界面,跟我们 CLI 的功能比较类似,我们之后会自己定制一个运维的系统级 DashBoard。

图片

架构变迁第三步就是如何真正地把我们上面实现的内容替换到现有的系统中。

釜底抽薪,这个形容是比较贴切的。我们的服务都是无状态化的,这个服务运行在哪里是无关紧要的,运行多少份也是无关紧要的,只要把这些新的容器化的交付应用替换掉之前的以各种杂乱的形式运行的应用,由于演进是平滑的,直接替换即可,整个系统就有机结合起来了。

完成架构变迁前两部之后,假如现在系统有50个组件,只完成了5个组件的 Docker 化、无状态化、编排。没问题,我们的原则就是平滑,渐进,你不需要全部搞定,就可以开始应用到生产环境了。目前 Coding 的 95% 的组件都运行在 Docker里面,为什么留5%,是因为有一些极其边缘的组件,因历史遗留原因还没有迁移过去。事实上我们发现只要前两步做的好,第三步是很容易的,简单来说就是停掉旧服务,启动新服务。

这里值得一提的是,不光我们的主业务系统需要这么做,我们的一些附属业务系统包括监控系统、负载均衡系统、服务发现等等,都应该按照这个架构一步一步替换过来。最后实现计算和存储分离,软件和硬件分离。因之前不是在容器中运行,应用对某个服务器可能都是一种强依赖的状态,而现在把这些组件替换掉之后,你所有应用的环境都封装在 Docker image 里面,这些服务器上本身没有任何各个语言的执行环境,他们都是 Docker 宿主机,自动就变成无差别化的了。Docker Image只要放到任何一台装有 Docker 的环境上,就可以很快运行起来。

图片

这是线上的 Docker 容器的列表截图,这是某一台服务器运行的实例。最终形成的架构是这样的:

图片

当你们看到这个架构的时候觉得它并不高端也并不奇怪,因为很多传统架构就是这样。而我想说的是我们完成这些东西其实也并不违背传统的高可用分布式架构,只是釜底抽薪,把底层的进程组件换成了容器,把原来管理应用的方式换成了管理容器的方式。

我们现在运维的流程是这样,运维有两种方式来操作这些容器,分别是 CLI 和 UI 界面,运维操作都是发往这个工具,这个工具是可以管理现有所有的容器,所有的容器的定义都会存放在相应的配置文件里,这些配置文件还会在 ETCD 里做一个副本,LB 系统监控系统等等需要知道这些组件的状态。

LB系统是内部服务的总入口,比如内部有一个很小的服务,这个服务做的事情很简单,所以它属于微服务的特点,微服务就是某一个组件每一个服务只做好一件事情,把这个事情做到极致。而 LB 就是把对这些服务的请求转发给相应的无状态组件。

我们有一个微服务的组件 md2html 就做一件事情,就是编译 Markdown ,所有其他组件但凡有需要编译 Markdown 的都通过 LB 系统调它。这个组件使用 Ruby 写的,其运行环境比较难配置,牵扯到一些原生的 C 的库,会对一些本地库有些版本需求,新增服务器很容易配置错误。现在就没问题了,这个应用的环境已经被我们打包成 image 存入了 Docker registry ,即便我们装有运行环境的那台机器宕了,我们只要用 Docker pull 下来,立马就能迁移到另外一台服务器。

我们的监控系统跟 LB 是什么关系?监控系统会对每一个容器的关键指标做数据收集,比如 LB,比如刚提到的 md2html ,都会维护一个 Http 接口,这个接口里提供它的关键指标的数据信息。计算资源服务器的关键指标有内存使用量,CPU 使用率等等。应用程序的关键指标都由各个业务应用自己定义。

例如我们这个 md2html 他的一个关键指标就是每秒钟处理的MD数量。

我们的监控系统会定时抓取这些关键指标,要求较高的是 5 秒一次,要求低的可能是1分钟,抓取之后存入数据库,再配上一些监控的报警规则。比如一个 md2html 实例,正常业务量可能是每秒钟处理10个编译的任务,但是监控系统查到连续五分钟处理量都低于3,我们就认为这个实例有问题了。

监控系统在遇到问题时,一方面会发一条消息到 ETCD 里面,告知现在这个实例异常,LB 系统订阅ETCD,LB 系统 watch 到相应的改变之后就会把自己的配置改一下然后做一次 reload,这个实例就自动下线了。另外,监控系统监测到问题的时候会发一条消息到通知中心,通知中心会把错误的信息直接通过手机 APP 推送给运维人员。另外我们还支持包括发邮件,发短信,打电话等等形式。通知中心是我们这个系统中组件共用的,还有些普通的业务应用也会用到通知中心这个组件。

这些组件都是运行的多个实例,不要觉得业务量不大何必运行这么多实例,对一个服务来讲,它没什么负载,它运行着也不会占你太多的计算资源,据我的了解我接触大多数人的系统架构里计算资源都属于过剩的状态,他们却不愿意去多运行几个实例来提升可靠度。

这里是我们这个架构图的一些细节:

  • LB 系统: Nginx / HAProxy / confd / Etcd

  • 监控系统: Prometheus / cAdvisor / Http Metrics

  • Docker Registry V1

  • Docker 网络:Host

  • Docker 日志:Mount 宿主机

HAProxy/ nginx这些很普通的负载均衡软件。confd 是一个很简单的程序,就做一件事情,confd 一直 watch  Etcd 中服务的容器应用状态,一旦有改动,就生成新的LB 配置文件,并 reload LB 程序。这也印证了我们坚持的一点,系统中所有的组件只做一件事情,而且把这件事情做到极致。

假如说我们现在有三个 md2html 实例,当某一个实例挂了,监控系统检查到了相关问题,知道它挂了,这时监控系统会两件事情,把它挂的消息通知到 ETCD,推送到ETCD 后,confd 会自动 reload LB,实现 LB 系统的自动切换。另外就是发送通知给运维人员,好让运维查出系统的问题,从而做出响应。

我们搭建一个 Docker RegistryV1 版本,现在已经发布了V2 版本,Docker 官方 V1 和 V2 版本不兼容,V2 也改了名字,叫做 Distribution。我们用到现在没出特别大的问题,完全没有激发我们升级新版本的动力,因为V1用得挺好的。

Docker 网络,Host 模式,优点在于性能高,平滑。如果不用Host的模式,用 NAT 模式会非常痛苦,NAT 模式虽然安全,但是对于私有云内部来讲没有危险的应用,所有程序都是自己写的,没有不安全的,就算它不安全,你之前没有用 Docker 的时候它也是这样,所以用这个 Host 模式并没有增加不安全度。最后是 Docker 日志,我们之前踩了一些坑,现在的做法是让它直接写到宿主机的日志文件里。

我们的架构接下来的改进方向是如下几个点:

  • Job-Tool 进化成 Job DashBoard ,集成监控(cAdivsor),日志(ELK)等功能

  • 利用监控系统的硬件指标,根据业务用量实现自动扩容,缩容

  • 分析各个业务对硬件资源的使用量和高低峰,设计混布实现提升硬件使用率

  • Docker image 的构建和管理

  • 动态调整 container 的资源限制

吐槽一下Docker的问题。Dockerfile 有点用,但没什么大用,就是几句话的问题非要编译那么大的镜像,改一行配置都需要重新编译一个 image。Docker Daemon,很不稳定,我们出的很多问题都是它导致的,它功能太多,很多问题也就是他这些无用的功能导致,我们认为 Docker daemon 只需要做几件简单的事情,帮你管理容器,起、停、删除就完了。Docker 官方最近刚推出了一个 ContainerD,就是一个简化版的 Docker Daemon,基于 RunC 的,就非常符合我们对于 Container 管理的看法。

我们之前踩了两个比较大的坑,一个是容器标准输出输出大量数据,会导致内存泄露,从而导致 Docker Daemon crash。另外一个是Docker Daemon 在频繁创建删除容器(每天几十万个)会出现性能严重下降等问题,只能重启 Docker Daemon。标准输出问题,必须要满足的两个条件是输出数据量大、输出速度快。

这里列出了我们关于标准输出问题的简易重现方式和最终 Docker 的修复方案。

最后,关于并发性能问题,测试环境比较复杂,还在进一步研究中,欢迎各位来 Coding.net冒泡 共同探讨

谢谢大家。

Dubbo原理解析-监控

$
0
0

监控中心

1.  监控中心启动,我们先看下dubbo的属性文件

dubbo.container=log4j,spring,registry,jetty

dubbo.application.name=simple-monitor

dubbo.application.owner=

dubbo.registry.address=zookeeper://127.0.0.1:2181

dubbo.protocol.port=7070

dubbo.jetty.port=8080

dubbo.jetty.directory=${user.home}/monitor

dubbo.charts.directory=${dubbo.jetty.directory}/charts

dubbo.statistics.directory=${user.home}/monitor/statistics

 

相比于provider, consumer的启动注册中心多了registry, jetty容器启动

它们都是基于dubbo的spi扩展机制的。

SpringContainer容器启动就是加载classpath*:META-INF/spring/ *.xml spring的配置文件

<beanid= "monitorService"class= "com.alibaba.dubbo.monitor.simple.SimpleMonitorService">

       <propertyname= "statisticsDirectory"value= "${dubbo.statistics.directory}"/>

       <propertyname= "chartsDirectory"value= "${dubbo.charts.directory}"/>

</bean>

<dubbo:applicationname= "${dubbo.application.name}"owner= "${dubbo.application.owner}"/>

<dubbo:registryaddress= "${dubbo.registry.address}"/>

<dubbo:protocolname= "dubbo"port= "${dubbo.protocol.port}"/>

<dubbo:serviceinterface= "com.alibaba.dubbo.monitor.MonitorService"ref= "monitorService"delay= "-1"/>

<dubbo:referenceid= "registryService"interface= "com.alibaba.dubbo.registry.RegistryService"/>

 

2. SimpleMonitorService

监控中心配置了监控服务的实现SimpleMonitorService, 并且作为一个普通的dubbo服务暴露到注册中心,供服务的提供者和服务的消费方调用,将服务提供者和服务的消费方的调用数据保存到监控中心。

监控服务的接口定义

public interface MonitorService {

    /**

     * 监控数据采集.

     * 1. 支持调用次数统计:count://host/interface?application=foo&method=foo&provider=10.20.153.11:20880&success=12&failure=2&elapsed=135423423

     * 1.1host,application,interface,group,version,method记录监控来源主机,应用,接口,方法信息。

     * 1.2 如果是消费者发送的数据,加上provider地址参数,反之,加上来源consumer地址参数。

     * 1.3 success,faulure,elapsed 记录距上次采集,调用的成功次数,失败次数,成功调用总耗时,平均时间将用总耗时除以成功次数。

     *

     * @paramstatistics

     */

    void collect(URLstatistics);

 

    /**

     * 监控数据查询. 

     * 1. 支持按天查询:count://host/interface?application=foo&method=foo&side=provider&view=chart&date=2012-07-03

     * 1.1host,application,interface,group,version,method查询主机,应用,接口,方法的匹配条件,缺失的条件的表示全部,host用0.0.0.0表示全部。

     * 1.2 side=consumer,provider 查询由调用的哪一端采集的数据,缺省为都查询。

     * 1.3 缺省为view=summary,返回全天汇总信息,支持view=chart表示返回全天趋势图表图片的URL地址,可以进接嵌入其它系统的页面上展示。

     * 1.4 date=2012-07-03指定查询数据的日期,缺省为当天。

     *

     * @param query

     * @returnstatistics

     */

    List<URL> lookup(URL query);

}

 

注: lookup方面可能在开源过程中依赖了阿里的什么系统,并没有具体的实现,如果使用着需要此功能则需要根据接口定义自己实现

 

MonitorService的dubbo默认实现SimpleMonitorService

Collect方法被远程调用后将数据url(传过来的url包含监控需要的数据)保存到一个阻塞队列中BlockingQueue<URL>

启动定时任务将统计日志记录到本地,

String filename =${user.home}/monitor/statistics

                        + "/" + day

                        + "/" +statistics.getServiceInterface()

                        + "/" +statistics.getParameter( METHOD)

                        + "/" + consumer

                        + "/" + provider

                        + "/" + type + "." + key

这是文件在本地存储的格式

文件内容如图保存时间方法消费耗时

 

3. 起定时任务利用JFreeeChart绘制图表,保存路径

${user.home}\monitor\charts\date\interfaceName\methodName

 

 

 

产生监控数据

注册中心暴露了MonitorService服务,它是被谁调用的呢,监控中心的数据是从哪里来呢,下面我们看下服务提供方与服务的消费方式如何介入监控中心的。

在服务的提供方跟消费方的dubbo配置加入如下配置

通过注册中心<dubbo:monitor protocol="registry" />

或者直连  <dubbo:monitor address="127.0.0.1:7070" />

在构建服务的调用链的时候有如上基于监控的扩展,下面我们就来看下这个类

@Activate(group = {Constants. PROVIDER, Constants. CONSUMER})

//此过滤器在服务的提供方,服务的消费方应用中被激活,也就是起作用

public class MonitorFilter implements Filter {

private MonitorFactory monitorFactory;

    public Result invoke(Invoker<?>invoker, Invocation invocation) throws RpcException {

    if(invoker.getUrl().hasParameter(Constants.MONITOR_KEY)) {

         //有注监控中心处理

1.  获取invoker的调用上下文

2.  记录起始时间戳

3.  并发计数加一

try {

4.  调用调用链的下一步

5.  采集调用信息

} finally {

6.  并发计数减一

}

    } else {

         //没有配置监控中心,直接往下调用

         return invoker.inovke(invocation);

   }

}

 

上面第5点信息采集

1. 计算调用耗时

2. 获取并发数

3. 获取服务名称

4. 获取方法名

5. 判断是服务消费方监控还是服务提供方监控

6. 由工厂类monitorFactory.getMonitor(监控url),获取DubboMonitor对象,

构建调用监控中心服务的的Url, url中包括了监控中心所需的监控信息

monitor.collect(newURL(Constants.COUNT_PROTOCOL,

                  NetUtils.getLocalHost(),localPort,

                  service + "/" +method,

                  MonitorService.APPLICATION, application,

                   MonitorService.INTERFACE,service,

                   MonitorService.METHOD,method,

                   remoteKey, remoteValue,

                   error ?MonitorService.FAILURE : MonitorService.SUCCESS, "1",

                   MonitorService.ELAPSED,String.valueOf(elapsed),

                   MonitorService.CONCURRENT,String.valueOf(concurrent),

                   Constants.INPUT_KEY, input,

                  Constants.OUTPUT_KEY, output));

 

DubboMonitor是调用监控中心的服务的封装,之所以没有直接调监控中心而是通过DubboMonitor调用,是因为监控是附加功能,不 应该影响主链路更不应该损害主链路的新能,DubboMonitor采集到数据后通过任务定时调用监控中心服务将数据提交到监控中心。

 

RegistryContainer

监控中心refer引用了注册中心暴露的RegistryService服务,主要是被下面的RegistryContainer使用的。

 

RegistryContainer主要是到注册中心收集服务,分组,版本信息,并注册回调当注册中心数据发生变化的时候更新到监控中心

下面看下RegistryContainer的start方法流程:

1. 通过SpringContainer获取前面初始化的RegistryService, 得到其实是对注册中心的一个远程代理服务

2. 构建订阅注册中心数据的URL,看可以看出下面的url是订阅服务提供者和服务消费者的所有服务

subscribeUrl = newURL(Constants.ADMIN_PROTOCOL, NetUtils.getLocalHost(), 0,"",

                Constants.INTERFACE_KEY,Constants.ANY_VALUE,//所有服务

                Constants.GROUP_KEY,Constants.ANY_VALUE,//所有分组

                Constants.VERSION_KEY, Constants.ANY_VALUE,//所有版本

                Constants.CLASSIFIER_KEY,Constants.ANY_VALUE,//所有分类

Constants.CATEGORY_KEY,Constants.PROVIDERS_CATEGORY + ","  + Constants.CONSUMERS_CATEGORY,//服务的提供者和服务的消费者

                 Constants.CHECK_KEY,String.valueOf( false));//不检查

3.  调注册中心服务registry.subscirbe(subscribeUrl,listener)订阅所有数据, NotifyListener在监控中心暴露为回调服务,由注册中心回调

回调接口NotifyListener实现的功能主要是按服务提供者和服务的消费者分类,收集服务名称,服务的url,服务提供方或者消费方的系统相关信息。 同时提供了一系列方法供注册中心调用查询。

 

JettyContainer

监控中心将采集到的信息通过内置jetty来展现给用户,这里为了不依赖与jsp, velocity,freemarker等一些编写web应用的技术,采用在servlet中将html,css,js打印出来

JettyContainer的start方法启动了内置的jettyweb容器

将监控中心访问的本地文件目录设置到ResourceFilter中,并设置这个filter的访问映射到jetty中   , ResourceFilter主要是读取本地保存的JFreeChart绘制的图片到浏览器中去。

将监控中心的前置控制器PageServlet, 以及这个servlet的访问映射配置到jetty中。之所以叫PageServet为前置控制器,就像其他的mvc框架一样用来分发具体的业务类

 

PageServet的init初始化方法在web容器启动的时候加载所有的页面处理器PageHandler, 用来根据不同的请求生成不同的页面,前面说过这里页面html都是通过java代码打印出来的。

PageServet的init方法加载所有PageHandler时会判断PageHandler上是否有@Menu注解,将有注解的PageHandler加入集合,以被HomePageHandl er用来生成主页以及各个页面的uri

PageServet的doGet, doPost接收浏览器请求,请求以xx.hml形式,xx就是PageHandler扩展的key,找到对应的PageHandler绘制对应的页面返回给浏览器。

 

 

@Menu(name = "Home",desc = "Home page.", order = Integer.MIN_VALUE)

//有注解 name跟desc属性都是在页面中展示给用户看的

public class HomePageHandlerimplements PageHandler {

    public Page handle(URL url) {

        List<List<String>> rows =new ArrayList<List<String>>();

        for (PageHandler handler :PageServlet.getInstance().getMenus()) {

            String uri =ExtensionLoader.getExtensionLoader(PageHandler.class).getExtensionName(handler); //这个uri其实就是PageHandler扩展配置的key,页面中用它来请求选择具体的handler绘制     //出具体的page

            Menu menu =handler.getClass().getAnnotation(Menu.class);

            List<String> row = newArrayList<String>();

            row.add("<ahref=\"" + uri + ".html\">" + menu.name() +"</a>");

            row.add(menu.desc());

            rows.add(row);

        }

        return new Page("Home","Menus",  new String[]{"Menu Name", "Menu Desc"}, rows);  //一个Page实体就是一个页面,这里包含所有主要HomePage的页面内容

    }

}

 

PageHandler的在com.alibaba.dubbo.container.page.PageHandler文件中的扩展配置

index=com.alibaba.dubbo.container.page.pages.HomePageHandler

providers=com.alibaba.dubbo.monitor.simple.pages.ProvidersPageHandler

consumers=com.alibaba.dubbo.monitor.simple.pages.ConsumersPageHandler

。。。。

下面截图看下dubbo大概提供了哪些扩展

 下面截几张图看看监控中心的页面。

   

http://blog.csdn.net/quhongwei_zhanqiu/article/details/41896667

http://blog.csdn.net/quhongwei_zhanqiu/article/details/41896943



已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐




微服务架构--服务框架,metrics 和调用链数据

$
0
0
服务框架
微服务化以后,为了让业务开发人员专注于业
务逻辑实现,避免冗余和重复劳动,规范研发
提升效率,必然要将一些公共关注点推到框架
层面。服务框架 ( 图 9) 主要封装公共关注点
逻辑,包括:
1.
服务注册、发现、负载均衡和健康检查,
假定采用进程内 LB 方案,那么服务自注
册一般统一做在服务器端框架中,健康检
查逻辑由具体业务服务定制,框架层提供
调用健康检查逻辑的机制,服务发现和负载均衡则集成在服务客户端框架中。
2.
监控日志,框架一方面要记录重要的框架
层日志、metrics 和调用链数据,还要将
日志、metrics 等接口暴露出来,让业务
层能根据需要记录业务日志数据。在运行
环境中,所有日志数据一般集中落地到企
业后台日志系统,做进一步分析和处理。
3.
REST/RPC 和序列化,框架层要支持将业
务逻辑以 HTTP/REST 或者 RPC 方式暴露出
来,HTTP/REST 是当前主流 API 暴露方式,
在性能要求高的场合则可采用Binary/
RPC方式。针对当前多样化的设备类型(浏
览器、普通 PC、无线设备等 ),框架层要
支持可定制的序列化机制,例如,对浏览
器,框架支持输出 Ajax 友好的 JSON 消息
格式,而对无线设备上的 Native
App,
框架支持输出性能高的Binary消息格式。
4.
配置,除了支持普通配置文件方式的配置,
框架层还可集成动态运行时配置,能够在
运行时针对不同环境动态调整服务的参数
和配置。
5.
限流和容错,框架集成限流容错组件,能
够在运行时自动限流和容错,保护服务,
如果进一步和动态配置相



已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



内容的作用机理 为什么要投资内容?

$
0
0
【工场投资手札】内容的作用机理(上)

 

编者按:本文作者 陈悦天,创新工场投资总监,看在线娱乐、社区和游戏,勾搭可移步 知乎。本文是《创新工场文化内容投资手札》系列的第三篇,其他文章见文末目录。

这次就不长篇大论了,我选了内容产业一个较有代表性的门类来提出我的一个观点。大家先来仔细看几个养眼的 MV 吧

  • AKB48,乃木坂 46,Perfume,BabyMetal
  • WonderGirls,T-ara,少女时代,Stellar,GFriend

日本女子偶像团体近年来的演变

【工场投资手札】内容的作用机理(上)

从音乐、服装、舞蹈三个角度来感受的话

  • AKB48:JPOP,强烈的架子鼓点;短裙,制服,略有时尚感的学生妹;热血的感觉,蹦蹦跳跳的感觉
  • 乃木坂 46:钢琴、小提琴的抒情情歌;过膝长裙,蕾丝;没有大幅度跳跃动作。希望的感觉,仙仙的感觉
  • BabyMetal:三弦 + 重金属;红黑两色的蓬蓬裙,狐妖面具,和服;1 人演唱,2 人舞蹈,重金属萝莉?已经有点看不懂了

韩国女子偶像团体近年来的演变

【工场投资手札】内容的作用机理(上)

从音乐、服装、舞蹈三个角度来感受的话

  • WonderGirls:KPOP 舞曲;时尚顽皮的可爱系少女;活力的感觉
  • T-ara:KPOP 舞曲;猫耳朵 + 猫手套 + 猫尾巴;迪斯科复古舞蹈,背对着镜头抖尾巴。可爱性感
  • 少女时代:KPOP 舞曲;大长腿,皮靴,丝袜,突出腰线的紧身衣,军帽;Jazz,有大量的大幅度扭胯动作,前后移动两腿交叉过肩。青春活力性感
  • Stellar:丝袜,胸部镂空毛衣,裙子干脆就没有了,超高跟鞋;基本就是标准的自摸和扭胯,还有很多基本背对着镜头的动作。这是我第一次在 MV 里面看到女生背对镜头摸屁股的…令人汗颜。超过尺度的性感
  • GFriend:运动球鞋,运动短裤,运动 T 恤,同一色的连衣裙,发卡;体操动作的舞蹈,跳马等,大风车甩臂。青春、力量

总体来说,韩国的女子团体的舞蹈和服装,尺度都偏大,逃脱不了 “性感” 这种感觉。与韩国比起来,日本的女子团体简直都是小白兔…

这也导致受众受到的刺激太过于简单直接,差异化偏弱,好比中国的网页游戏,付钱付钱付钱→爽爽爽→什么都没留下,只能刷流量,还是大量的低质量流量。

日本团体的演变经历过:

清正美的偶像(山口百惠时代)→帅气女子团体(Speed 时代)→活蹦乱跳的元气女孩(早安美少女,桃色幸运草,AKB 时代)→多元化(乃木坂的清纯感动,大家闺秀;BabyMetal 的重金属萝莉)

韩国团体经历过:

早期 WonderGirls(Tell Me) →BrownEyed Girls(Abracadabra)→Nobody 时代的 Wonder Girls→T-ara(可爱性感)→少女时代(清纯性感)→Stellar(过尺度性感)→GFriend(力量青春活力)

在性感层面真是一骑绝尘,彻底地跑偏了。到了 GFriend 总算看到了些许清流的状况,但毕竟 1年 不到的时间,2 首热门单曲还不能确定团队的未来会如何。

但不管是日本还是韩国,总体来说都是在不断创造新的感觉。当旧的感觉成为业界标准的时候,总会有能够创造新感觉的团体冒出来。

用一种新的感觉去攻打旧的感觉是内容产业在任何战略层面都正确的做法。

所以说,做内容就是做感觉,为受众创造新的感觉。

做内容就是做感觉。

内容是通过引起受众的共鸣来发生作用的,共鸣的发生是通过将受众的一种感受关联(或者叫做 “固定”、“锚定 anchor”)到某一个具体的元素上,形成 “投射” 来完成的

※NLP(Neuro-Linguistic Programming)和催眠疗法大部分就是通过感受和语言、图像、声音的锚定来完成的

做内容,就是不断缩短感受 和 元素 间的反射弧,让受众最终形成条件反射的过程。

上篇里面之所以列出这么多音乐、舞蹈、服装是为了让大家更深切地体会元素和感觉到底是如何关联起来的。比如红黑二色到底是怎样一种感觉,皮靴和运动球鞋分别代表的是什么感觉,三弦、钢琴、小提琴、架子鼓或者变音吉他到底分别是什么感觉。

再举一些例子大家就能明白:

1. 有很多人听一段红白机上《魂斗罗》的 8bit 主题曲的时候就会觉得莫名的兴奋

2. 为什么东方系列的 BGM 可以这么受欢迎?

【工场投资手札】内容的作用机理(下)

  • 独特的纵版飞行游戏配合上华丽的弹幕创造了一种特殊的游戏感觉(视觉 + 操作),音乐地不断循环固定住了这种感觉
  • 但是更重要的是 ZUN 主在做东方系列的游戏的时候是先谱曲,再做游戏的。
  • 实际上音乐的起伏感和节奏感已经预先设定好了,之后只是拿弹幕和 BOSS 配上去,让感觉更强烈更具象而已

3. 80 后听灌篮高手和圣斗士星矢的片头曲的时候,90 后听数码宝贝的片头曲的时候就会浑身汗毛直立。等待动画片的激动兴奋感被固定到了主题歌上

4. 小朋友看到王尼玛的头套就会一下子觉得很开心并且笑起来

5. 23333 在 B 站里面就是代表了一种心理状态,经历了两个步骤

  • 一开始是某一些人不断地在觉得好笑的地方发 2333 用来自我表达
  • 但是到了最后,电脑屏幕另一端的人看到 “23333” 的时候,可以产生愉悦感,他能够同感发弹幕人的心理状态

6. 摇滚俱乐部的乐迷们为何要做这个手势

【工场投资手札】内容的作用机理(下)

符号化

人幼年和少年时体会到某一种新鲜的感觉时,身体和大脑会寻找解释,并且将这种感觉和找到的解释进行关联。前面 3 个例子都和音乐有关,王尼玛的例子和图像有关,23333 和语言有关、更符号化。

首先要创造一种全新的感觉,然后再提供一些元素和符号让受众与之产生关联,这种关联可以通过经年累月地被动重复达成,也可以主动诱导而产生。

相关的元素和符号,我们称为 “文化符号”。迈克尔杰克逊就是个符号化特别强的人,礼帽、太空舞步、亮片手套,这些都是会重复不断出现的元素。
【工场投资手札】内容的作用机理(下)

如何评价内容的好坏?

看内容要看一表一里,即表现形式和内涵,“形” 和 “意”

两个特性都可以让受众产生共鸣:

    • “搞笑漫画日和” 和 “万万没想到” 的特殊节奏感
    • 鬼畜音乐(duang 和加特技)
    • 哲♂学
  • 意,即内容本身宣言和需要表述的价值主张和态度

优秀内容必须具有两个特性中的最起码一个,“意” 的能量比 “形” 更大,在受众中产生的共鸣更长久、更丰富

内容的 “形” 方面

  1. 优秀的内容往往具有一种特殊的 “节奏感”。比如唐诗宋词、郭敬明的小说、幕星社的条漫,在消费内容时可以明显感受到紧张、舒缓的速度和上下起伏的感觉。
  2. 优秀的内容在内容格式(指文字、图片)和内容创造模式(指流水线化机制)上是易复制的,从而可以系列化、规模化的量产。
  3. 足够高质量,是指品质感上的质量,外在的。比如《大圣归来》的品质感就很不错

内容的 “意” 方面:

  1. 优秀的内容附带了一种精神内核和价值观,是一个想法(盗梦空间中说的 idea),可以称之为 “文化”。
  2. 文化是内容的高阶形式,后文会详解。优秀的文化易传播,因为它贴合了某一个已存在的人群的精神内核和价值观

附注:如果再深入,会发现有真实的节奏感和虚拟的节奏感。虚拟的节奏感就是《故事》里面所说的价值的起伏和正负,用古话说的是 “起”“承”“转”“合”。虚拟的节奏感同样和 “意” 相关

另外初期的抓人眼球的内容还要足够独特、足够稀缺,有冲击性、要与众不同,这是由 “形” 和 “意” 同时构成的。优质的内容初期独特性就会很强,独特性只会随时间被稀释;模仿人多了、扩大受众,口味就被稀释了

符合上述标准的优秀内容,我还可以举出很多例子,就不一一分析了,我罗列如下:

  • 舌尖上的中国,以纪录片的形式,通过拍摄每个地区的特色食物,勾起中国人的乡愁,同时让大家体会到泱泱大国的饮食文化的博大精深,增加了自豪感,后续可能炫耀。(微博上的舌尖上的英国、舌尖上的美国系列) 【工场投资手札】内容的作用机理(下)
  • 阿里巴巴的企业文化,以阿里人手册和内部论坛为主,主要传递的价值观是 “为中国千千万万的中小企业服务,让中国没有难做的生意”。 这个愿景有相当强的正能量和传播性,让大家一听就热血沸腾,感觉正在从事的是一件非常伟大的事业。当我们挖掘这句话的时候,发现,帮助弱小,实现梦想潜藏在这个愿景背后。这两个潜意识的正能量让我们热血沸腾,产生了情绪上的反应。利他是一个伟大的愿景,很多优秀的文化内容中都包含利他的成分,我在后面会再次提到。 【工场投资手札】内容的作用机理(下)
  • 小时代,4 本书 +4 部电影。传递的精神内核是:大上海的纸醉金迷,年轻、梦想、友情。我们说好不分离,要一直一直在一起;就算与世界为敌,就算与全世界背离 【工场投资手札】内容的作用机理(下)
  • 海贼王、火影忍者、圣斗士星矢等集英社漫画(但是由于非统一画风的原因,这些不能整合到一个统一世界观内,甚为可惜) 【工场投资手札】内容的作用机理(下)
  • 古风音乐,以用古诗词、文言文填曲的歌曲为主,传播的价值内核是:中华浩荡五千年,英雄儿女代代出;盛唐大宋,泱泱大国,引起的是民族自豪感。可以欣赏诗词的人能体会优美,从而产生优越感。 【工场投资手札】内容的作用机理(下)
  • 宗教,精神内核是 “牺牲”“救赎”“博爱”。同样也是利他的,奉献的,从而升华成伟大的。“我不入地狱,谁入地狱?” 【工场投资手札】内容的作用机理(下)

※多提一句 “利他主义”,帮助弱小、实现梦想。强调理想牺牲救赎、强调集体精神(对用户产生更好的粘性、控制力)、不强调现世。

常碰到一个问题:“请帮我说说二次元吧?” 好吧,那我做一下知识普及。

NACG产业链到底是什么?

  • 这条产业链其实是参照着日本目前的业态搭建起来的:
  • A:Animation 动画
  • C:Comics 漫画
  • G:Game 游戏
  • N:Novel 轻小说

在日本,内容类产品的改编路径在早些时候是 N->C->A->G

但是近年来会发现逐步跳过了 C 的阶段,变成了 N->A->C->G

意味着一本热门的轻小说会被直接改编成动画之后才会同步成为漫画作品,这可能和动画产业的产能提高和产业链完善有关。

N

N 即为轻小说,是一种在日本年轻人中非常流行的内容形态,主要的特点为:

  • 轻量纸的纸质书本
  • 每页没有多少的文字
  • 文字大多为剧中人的对话
  • 在关键场景和核心人设上采用漫画的方式来固定感觉,更有冲击力,但是同时文字的生产效率要比漫画高

以上 4 个特点使得轻小说在阅读的过程中,读者感觉非常轻松,唰唰唰地就翻完了一本书,阅读目标感明确,阅读成就感倍增。其主要的写作题材也多为魔幻、校园、恋爱等青少年喜闻乐见的题材。生产的过程一般就是作者一个人拼命写,有极少部分采用作者团的机制,但是成型的模型并没有被很好的开发出来。

C

C 为漫画,这个就比较好理解了,90年 代初的时候大部分中国的书报亭和书店都有售各类的黑白漫画书。当前在中国有以下几种形式:

  • 黑白漫画,日本的大部分故事类漫画,国内《漫友》、《漫画行》上的作品多是传统的黑白故事漫画
  • 彩色四拼一漫画,《知音漫客》和《漫画世界》上大开本周刊上面的基本是这些漫画
  • 四格漫画,比如像老夫子之类的,多是幽默类型的超小短篇。
  • 条漫,顾名思义,长条状的漫画,在移动平台上多见,微博上现在很多

漫画比小说就是画面感更强,冲击力更好,但就是生产成本高,内容积累慢。

一般漫画的生产过程中涉及到几种角色,漫画家(主笔),漫画助手,漫画编辑。漫画家一般是创意(包括故事人物世界观等等)的源头,漫画助手是帮助漫画家提升效率的核心,漫画编辑是漫画面向市场和受众的比较重要的开口。

A

A 为动画,这个就更好理解了。

一般谈论到动画在 “中二” 的年龄明显把人群隔成了两拨人,14 岁以下的内容被称为子供向动画,之上的内容被称为少年(少女)向动画。

顾名思义,子供向动画的特点是题材低幼。由于受众年龄小,所以播出渠道往往选择在电视台。后端商业模式单一,一个是玩具,一个是文具。玩具做起来的动漫公司上市公司最好的例子就是奥飞动漫,上市的文具公司就是晨光文具,他们也投资了一家漫画公司。

但是子供向市场最大的问题就是小孩长得太快,而且每年长大都会鄙视从前的自己,抛弃从前的内容。付费也都是家长口袋里掏,所以是个非常难伺候的市场。

少年(少女)向动画就不同了,由于都是在中二青春期自主意识非常强的时候开始喜欢的内容,非常容易狂热地爱上一辈子,因为这种内容消费定义了 “自己”。像我还深刻的记得当年自己一遍遍看 EVA 的场景。少年少女向的漫画无论是周边产品、影视剧、游戏,开发的空间都很大,后端变现模式多,前端的内容就可以多投入,产量和品质就可以提升。

G

G 为游戏,也更好理解了。这就不多说了,游戏制作,游戏发行,游戏渠道,都各有门道。

创新工场,顺着这条链子,每个环节都有布局,比如 8kana(不可能的世界),橙光 66rpg,有妖气(已出售给奥飞),翻翻动漫,卢恒宇与李姝洁工作室,绘梦文化等公司。在这个系列文章的最后会有每家公司的公司志,大家可以去翻看。

动漫和二次元是两个东西!

在这章的末尾,需要谈一谈的是一个非常重要的纠偏点:动漫和二次元是有区别的:

动漫作为一种内容表现形式,它的地位是应该和小说、电影、电视剧等内容形式齐平的。其上可以承载的故事和所要表达的精神内核是可以多种多样的。

国内以前的状况是动画的播放都只在电视台,受严厉监管,所以国家定位动漫为低幼类内容,很多内容不能用这种形式表现。网络视频平台,特别是像 AB 站这样的专门平台的发展,使在网络上播放原创动漫内容成为可能,很多青少年向和成人向的内容有了展示的空间。

从国产动画和漫画的质量和数量来讲,中国的动漫产业还有长足的发展,空间还非常大。所以,多多关注动漫内容生产端的机会,一定会有很多收获。

而二次元是作为当前主流的动漫内容(大部分是日漫和日本动画)所衍生出来的一种文化,这中间的用户是存在一道转化的,不是所有的动漫内容的消费者都是二次元用户。观察市面上大部分的产品,内容消费类产品如 Bilibili,布卡漫画,布丁动画,腾讯动漫,基本上的日活跃量级都在百万以上,但是社区社群类产品,特别是二次元向的社区类产品,日活跃基本都是百万以下,第一个坎是过 10 万,然后是 30 万,然后是 50 万,50 万日活的产品非常少。

所以内容消费,是动漫领域的最底层需求;基于内容消费,其上才能构筑文化和社群。

抛弃内容消费谈社群,都是扯淡。

无数人问我这个问题,按照 “传统” 的 VC 逻辑,我们不应该去投上游的内容生产,既耗时费力、没有持续性还很难规模化。但是我想说,这是基于我们对于目前整个中国内容产业链的特殊状况作出的判断。我来分三点来回答:

1. VC们到底投资于什么?

我想,应该是投资于可能产生垄断的机会,垄断是基于某个产业链环节的市场份额来说的。垄断也是大公司基业长青的保证,基于高市场份额的垄断公司可以制定行业标准,拥有更高的利润率,从而在未来的竞争中也同样占有先机。

所以 VC 们不是一定要投渠道和平台,只是因为在渠道和平台端,由于靠用户最近,在 C 端的传播扩散更容易,网络效应更容易产生,导致垄断形态的产生概率更高而已。

VC 们本质投资的是垄断。

但是垄断并不一定产生于渠道和平台环节,考察海外大型传媒公司的发展路径,Disney、NewsCorp、Viacom 等,有好几家是从内容生产端先产生了更大规模的垄断之后向下收购和自建发行、营销、渠道端做起来的。垂直整合的前提是在当前产业链环节做到足够大的垄断规模,这样对环节上下游就产生了更大的议价优势。

2. 中国的内容产业链(特别是视频类内容)现在的状况是什么样子?

经过多年的渠道乱战,上方是相当分散的各种内容提供方,图中左下是线上渠道的情况,图中右下是线下渠道的情况。线上优土背后是阿里,爱奇艺背后是百度,腾讯视频是腾讯自己的,乐视是家千亿市值的上市公司。线下 4 家卫视和后面的同类拉开了巨大的差距(广告收入和收视率上)。视频目前是中国互联网流量的必争之地,所以这样的寡头垄断局面短期内看来不会有终结的迹象。

那我们就来思考一个可能性,有没有可能上游出现一个更大的垄断形态的内容制作或者内容发行公司,利用现在的市场博弈窗口,获得较大的市场份额呢?内容制作和发行端是没有机会的吗?目前就我们了解到的流量结构,流量向头部内容的集中程度还是相当明显的,这可能归功于常年视频渠道端烧钱购买版权的状况,把上游养肥了。

在美国和日本,Youtube 作为 UGC 的温床,Netflix 作为高清点播的渠道,Niconico 作为弹幕视频的代表,在其所在的每个市场几乎都是垄断的。所以上游的大型内容生产和发行公司很难做大,尽管出现了 MCN 这类的运营公司,由于可选择的平台太少,只能作为平台的寄生。但中国的视频产业格局是明显不同的,故而内容端的机会也不一样。

当然大家也会问,平台会不会整合上游的制作力量,那回过头来,整合也是好事,VC 们的投资,就有了一个好的出路。

3. 基础设施下沉

再谈得更泛一些的话,中国的网络内容产业正在进入一个 “基础设施下沉” 的阶段。而内容端在这个 “基础设施下沉” 的年代,本质上成为了流量入口。

“基础设施下沉” 这种现象,其实发生于诸多历史上的新兴行业,比如早年的铁路网络、电网、有线电视网络、电信网络、互联网。可以看到,大部分是平台型的机会。

平台和渠道型的公司,网络效应较好,市场最终往往会被垄断或者寡头垄断。但又由于本身服务的泛用性较广,多是比拼效率,所以差异化空间必然小,利润空间也会在竞争过程中逐步挤压,最后都会逐步成为基础设施下沉。然后基于这些较好的基础设施,其上的商品、服务、内容可以脱颖而出,其中有一些会具有较好的利润空间。有一些,发展成未来的渠道和平台。

像现如今的电子商务,O2O,互联网金融,互联网教育等等,莫不如是,大家有没有发现有很多 O2O 平台已经渐渐成为基础设施开始下沉了?

这么看来内容端,无论是点播形态的大型视频网站,还是直播形态的 9158、YY、斗鱼等,如果短期内不能迅速垄断市场,都会面临上游大内容 CP 的议价和挤压。事实上,秀场业务被多家演艺公会把持多年,业内没有道破罢了。

当今的视频平台之争,也是因为当年优土合并没有一下子垄断市场,乐视网上市、爱奇艺携百度的巨量资本直接参战。

归根结底,靠资本推起来的壁垒(外购版权和流量),只要土豪加入战斗,壁垒不攻自破。视频平台的核心差异化点早已不是产品和技术了,不然芒果 TV 不会在 1年 半的时间内异军突起。壁垒应该是自己产生独家内容的能力,不管是 PGC 还是 UGC。在受众心里树立起品牌和差异化的服务,让用户 “爽” 到,才是长久的经营之道。


© 推荐 for 互联网的那点事. | 猛击下载: iPhone客户端猛击下载: Android客户端

做一个好的CEO的建议的笔记

$
0
0

在看这篇文章: 成功的CEO的8条贴士,标注如下:

日历别排的过满

完全同意。当你在公司的时候,其实很难思考公司的事情。当你离开一段的时候,反而可以想得更清楚。每个人都需要足够长的安静的没有打断的时间来思考。进入思考的状态就跟进入睡眠的状态很像,需要一段时间的安静,才会进入。每隔帮个小时有人来说一句话是绝对睡不着的。思考也一样。CEO很需要思考,而思考需要空白的时间。37Signals的工作方式从这句话看来我是同意的。

把自己泡在数据中

不同意。虽然数据很重要,比数据更重要的是用户洞察。用户洞察来自于直觉和与用户交流。数据能告诉一些东西,但是过于依赖数据会容易陷入局部最大化的窘境。越是大的决定越不能只依靠数据。

走动管理

同意。通过走动,和相关的人聊天,不断的重复战略,不断的让每个人理解为什么我们要做某一件事情,是保持一个公司的方向的最好方式。通过持续做这件事情,可以让公司这个社区变得更加透明。沟通不会发生,除非你设计它发生。

少看邮件

现在这个问题应该变成少看微信朋友圈,少漫无目的的看网页。这一条其实在我看来不是非常有深度的一个tip,忽略吧。

自己接电话

公司大了以后人会变的不那么个体。这是一个问题。我认为这绝对是一个问题。一个公司需要多大才可以把founder或CEO藏起来呢?需要腾讯那么大吗?美国那么大吗?看到罗胖的PPT里的一个现象,很多的中国老字号和世界的知名品牌都是人名(张小泉,Dell,还有说这句话的Essie Cosmetics)保持人性化在现在这个时代比以前更加重要。

聘请信任的人,放手让他们干活

他说他通过别人做所有的事情。我认为这一定是夸张,为了表明某一个观点的夸张的修辞手法。但它背后表达的意思我是同意的。通过让有能力的人放手去做,一个人的确可以做到比自己的能力大得多的事情。宏观的思考问题,把问题简化成:第一步打开冰箱,第二步放进大象,第三步关上冰箱是一种能力。但同时,辩证的看这个问题,很多的细节就是在放进大象这一步。如何Trust but verify是做好这件事情的关键。

看什么都要想着自己的生意 / 面试的时候问关于处理压力的问题

这两个我觉得深度不够。第一条我表示反对,不是所有的时候都想着自己的生意是最好的使用时间的方法。很多的灵感多出现在不想自己的生意的时候。第二条我没有感觉到这个问题的重要性。有很多比这重要得多的问题。

 

Mahout中相似度计算方法介绍

$
0
0

(转自: http://www.cnblogs.com/dlts26/archive/2012/06/20/2555772.html)

 

在现实中广泛使用的推荐系统一般都是基于协同过滤算法的,这类算法通常都需要计算用户与用户或者项目与项目之间的相似度,对于数据量以及数据类型不 同的数据源,需要不同的相似度计算方法来提高推荐性能,在mahout提供了大量用于计算相似度的组件,这些组件分别实现了不同的相似度计算方法。下图用 于实现相似度计算的组件之间的关系:

1

图1、项目相似度计算组件

2

图2、用户相似度计算组件

下面就几个重点相似度计算方法做介绍:

皮尔森相关度

类名:PearsonCorrelationSimilarity

原理:用来反映两个变量线性相关程度的统计量

范围:[-1,1],绝对值越大,说明相关性越强,负相关对于推荐的意义小。

说明:1、 不考虑重叠的数量;2、 如果只有一项重叠,无法计算相似性(计算过程被除数有n-1);3、 如果重叠的值都相等,也无法计算相似性(标准差为0,做除数)。

    该相似度并不是最好的选择,也不是最坏的选择,只是因为其容易理解,在早期研究中经常被提起。使用Pearson线性相关系数必须假设数据是成对地从正态 分布中取得的,并且数据至少在逻辑范畴内必须是等间距的数据。Mahout中,为皮尔森相关计算提供了一个扩展,通过增加一个枚举类型 (Weighting)的参数来使得重叠数也成为计算相似度的影响因子。

欧式距离相似度

类名:EuclideanDistanceSimilarity

原理:利用欧式距离d定义的相似度s,s=1 / (1+d)。

范围:[0,1],值越大,说明d越小,也就是距离越近,则相似度越大。

说明:同皮尔森相似度一样,该相似度也没有考虑重叠数对结果的影响,同样地,Mahout通过增加一个枚举类型(Weighting)的参数来使得重叠数也成为计算相似度的影响因子。

余弦相似度

类名:PearsonCorrelationSimilarity和UncenteredCosineSimilarity

原理:多维空间两点与所设定的点形成夹角的余弦值。

范围:[-1,1],值越大,说明夹角越大,两点相距就越远,相似度就越小。

说明:在数学表达中,如果对两个项的属性进行了 数据中心化,计算出来的余弦相似度和皮尔森相似度是一样的,在 mahout中,实现了数据中心化的过程,所以皮尔森相似度值也是数据中心化后的余弦相似度。另外在新版本中,Mahout提供了 UncenteredCosineSimilarity类作为计算非中心化数据的余弦相似度。

Spearman秩相关系数

类名:SpearmanCorrelationSimilarity

原理:Spearman秩相关系数通常被认为是排列后的变量之间的Pearson线性相关系数。

范围:{-1.0,1.0},当一致时为1.0,不一致时为-1.0。

说明:计算非常慢,有大量排序。针对推荐系统中的数据集来讲,用Spearman秩相关系数作为相似度量是不合适的。

曼哈顿距离

类名:CityBlockSimilarity

原理:曼哈顿距离的实现,同欧式距离相似,都是用于多维数据空间距离的测度

范围:[0,1],同欧式距离一致,值越小,说明距离值越大,相似度越大。

说明:比欧式距离计算量少,性能相对高。

Tanimoto系数

类名:TanimotoCoefficientSimilarity

原理:又名广义Jaccard系数,是对Jaccard系数的扩展,等式为

范围:[0,1],完全重叠时为1,无重叠项时为0,越接近1说明越相似。

说明:处理无打分的偏好数据。

对数似然相似度

类名:LogLikelihoodSimilarity

原理:重叠的个数,不重叠的个数,都没有的个数

范围:具体可去百度文库中查找论文《Accurate Methods for the Statistics of Surprise and Coincidence》

说明:处理无打分的偏好数据,比Tanimoto系数的计算方法更为智能。



已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



GPS卫星定位平台漏洞成灾,用户位置信息告急

$
0
0

近日,新闻中曝光了多起通过GPS定位设备跟踪绑架事件。通过对市面上一些GPS定位设备进行研究,发现这些GPS定位系统后台采用的是一套通用程序,其云平台上存在多个高危漏洞,攻击者利用漏洞可定位到使用该设备的任意用户或车辆的当前位置,历史轨迹,甚至可远程切断行驶车辆的油电。

一、简介

我们在淘宝上搜索gps定位装置,发现绝大多数卖家销售的主流gps定位系统均为同一套程序,均受到漏洞影响。

该系统的大致原理和架构如下:

在GPS定位装置里装有一张3G手机卡,定位装置获取到当前位置坐标后通过3g网络传输到云监控平台,用户通过pc或者移动设备登录监控平台,即可定位绑定在自己账号下的设备位置。

二、漏洞详情

以下面这套月成交8000+,累计评价超过22000的定位装置为例。

其云平台使用.NET开发,登录界面如下:

对于经销商,输入账号密码可控制其账号下所有设备,对于一般用户,选择输入IMEI和密码可定位单一的设备位置。

通过研究发现,在其云平台上,存在大量可未授权访问的webservice接口,我们通过协议规范调用这些接口,可获取任意用户的信息,修改其密码,甚至定位其位置。

通过接口将管理员的密码初始化,然后登录查看可以看到,仅仅这一个平台,就有超过25万的设备,当前在线设备就有2.7万。

可以直接定位到这些设备的具体地理位置

可以获取到使用该设备的车辆及人员的具体信息(电话、车牌号、姓名等)

可以定位到其车辆当前的具体位置:

还可以通过历史数据分析车辆的行驶轨迹:

甚至可以直接远程切断行驶车辆的油电:

通过进一步的研究我们发现,该系统的webservice接口还存在有sql注入漏洞,通过在soap消息中插入恶意数据,我们甚至可直接控制该服务器。

三、漏洞影响

研究发现,这套商业化的GPS定位程序使用量非常大,用户遍布中国、欧洲、中东、非洲、东南亚等多个地区。

还包括一些中东地区,战乱地区都比较喜欢用GPS跟踪。这里就体现出GPS的应用场景了。

而且我们发现这套gps定位程序不仅仅被用于车辆定位,还衍生出了儿童手表、人员定位器甚至宠物定位等多个版本。

人员定位器

儿童手表

宠物定位

我们从淘宝销售的gps定位装置中选择了多个销量较大的商家测试,发现绝大多数平台都存在漏洞,总数超过了100万台,以下是做的部分统计:

www.tourrun.net  总设备数量:496805
www.zg666gps.com  总设备数量:253426
www.indlifelocate.com  总设备数量:252980
ry.i365gps.com 总设备数量:93638
www.gpsjm.com 总设备数量:55451
gps.zg002gps.com 总设备数量:42993
www.mkcx.net 总设备数量:41894
www.aika168.com总设备数量:40586
www.xmsyhy.com 总设备数量:12645
www.twogps.com总设备数量:3587
www.lkgps.net 总设备数量:3434
ec-dbo.cn总设备数量:2961

四、安全建议

如何发现自己的车辆有没有被人装上定位器?

很多人看到新闻都产生了顾虑,生怕自己的车辆是否被装上了定位器。这里可以告诉大家几个思路去排除,首先这类定位器是装有强磁铁的,所以车上除了这个定位器以外不会有其它的强磁设备,可以去一些磁力检测仪来检测。第二种方法是GPS定位系统是需要用GPS信号的定位车辆的,可以在一个信号屏蔽的环境下检测车辆是否有GPS信号。第三个就是通过利用云平台的漏洞检测自己的车辆轨迹是否被跟踪,这也是没有办法中的办法了。

以后如何选用GPS定位平台?

GPS定位的需求很多,因为GPS定位一方面是为了保障用户,但是存在漏洞的被不法分子利用的话,就成了暴露用户位置信息的一条路径,往往需要GPS定位的都是有价值的东西,这就成了攻击者的一块福地。对于GPS产品应当选用可靠的,大品牌的产品。购买前应当在网上搜索一下有没有相关的安全漏洞。如果购买了产品发现有漏洞,建议用户停止使用,等待厂商更新平台漏洞。

*作者:360安全卫士(企业账号),转载请注明来自FreeBuf黑客与极客(FreeBuf.COM)

Viewing all 11804 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>