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

万达腾讯百度三巨头联合成立电商公司 三年投资50亿元

$
0
0

万达联手百度腾讯成立万达电商 腾讯占股15%

8月29日上午11点,万达集团、腾讯、百度在深圳举行战略合作签约仪式,宣布共同出资成立万达电子商务公司。万达集团董事长王健林、腾讯公司董事会主席兼首席执行官马化腾、百度公司董事长兼首席执行官李彦宏共同出席签约仪式。

据介绍,万达电商计划在三年时间内一期投资人民币50亿元,第一年投资10亿元,万达集团持有70%股权,百度、腾讯各持15%股权。

万达电商CEO董策表示,线上线下融合是未来商业终端和电商公司发展的必然趋势,万达拥有全球最大的线下商业平台,通过腾讯、百度两大巨头合作,万达电商将成为全球最大的O2O电商平台,真正实现O2O落地,为行业探索O2O发展的模式。

万达电商今年将在全国开业的107个万达广场开通电商服务,2015年开通万达所有广场、酒店、度假地的电商服务,实现对万达消费终端的全面覆盖,今年试运行期间,万达电商会员将超过4000万,明年将超过1亿。万达电商上线后,将与万达金融版块合作,推出一系列互联网创新金融服务,还将推出万达会员权益积分及多账户管理“一卡通”、统一积分联盟、百联网众筹投资业务筹新平台、新业务、新服务。

董策还透露,万达电商已注册一个很酷的新名字,将在万达电商全面上线之日公布。

万达集团是中国最大的文化旅游企业、全球最大的电影院线运营商,预计2014年到万达广场、酒店、度假区的消费者将超过15亿人次,到2020年,每年到万达的消费者将超过50亿人次,届时万达将成为全球最大的线下消费平台。

腾讯拥有用户规模最大、活跃度最高的众多互联网产品,截至2014年6月30日,旗下即时通信服务QQ月活跃账户达到8.29亿,微信和Wechat合并月活跃账户数达到4.38亿。

百度作为全球最大中文搜索引擎,每日响应搜索请求超过60亿次,LBS定位服务月均日PV超过100亿次。

三家在各自领域绝对领先的企业,将强强联合,充分发挥各自优势,进行对应产品的深度整合,共同开创全球领袖的O2O电子商务模式。

在签约仪式上,李彦宏称,O2O的大趋势是融合,是两边往中间靠,不是单纯的线上和线下。

李彦宏表示,整个实体经济拥抱互联网和移动互联网变化太慢,大企业拥抱才是标志。O2O趋势刚刚开始,这就要求互联网公司,如百度腾讯,和实体万达紧密结合。

最后,李彦宏强调,怎样提升运营效率,是O2O的机会。

在签约仪式上,王健林称,O2O是最大的电商蛋糕,但很多东西无法放到线上卖,目前还没看到一个大的平台出现。

王健林还表示,现在的机会对所有公司来说都是均等的,尤其是相对其他电商平台来说,O2O都是刚刚起步,现在还看不到真正有价值的平台。

王健林还透露,新的电商公司已经搭建了半年,不是卖商品,而是卖服务。

自:腾讯科技

您可能也喜欢的文章:

详解腾讯537亿并购的80家公司

工信部:2012年中国互联网企业Top100 腾讯网易百度列前三

百度数据中心:腾讯关注度占比进一步上升

腾讯财报:2014年Q2腾讯利润25.41亿美元 同比增长62%

百度数据:2012年百度游戏风云榜 腾讯网易盛大继续位居三甲
无觅

Kafka编程实例

$
0
0

 编程

    Producer是一个应用程序,它创建消息并发送它们到Kafka broker中。这些producer在本质上是不同。比如,前端应用程序,后端服务,代理服务,适配器对于潜在的系统,Hadoop对于的Producer。这些不同的Producer能够使用不同的语言实现,比如java、C和Python。下面的这部图表解释了消息producer的Kafka API.


下面将详细介绍如果编写一个简单的Producer和Consumer应用程序。

发送简单消息给Kafka broker,Producer端编写类ClusterProducer。

public classClusterProducer extends Thread {
    private static final Log log =LogFactory.getLog(ClusterProducer.class);
    public void sendData() {
        Random rnd = new Random();
        Properties props =PropertiesParser.getProperties(PropertiesSettings.PRODUCER_FILE_NAME);
        if (props == null) {
            log.error("can't loadspecified file " + PropertiesSettings.PRODUCER_FILE_NAME);
           return;
        }
        //set the producer configurationproperties
        ProducerConfig config = newProducerConfig(props);
        Producer<String, String> producer= new Producer<String, String>(config);
        //Send the data
        int count = 1;
        KeyedMessage<String, String>data;
        while (count < 100) {
            String sign = "*";
            String ip = "192.168.2."+ rnd.nextInt(255);
            StringBuffer sb = newStringBuffer();
            for (int i = 0; i < count; i++){
                sb.append(sign);
            }
            log.info("set data:" +sb);
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            data = new KeyedMessage<String,String>(PropertiesSettings.TOPIC_NAME, ip, sb.toString());
            producer.send(data);
            count++;
        }
        producer.close();
    }
    public void run() {
        sendData();
    }
    public static void main(String[] args) {
        new ClusterProducer().sendData();
    }
}


定于Consumer获取端,获取对应topic的数据:

public class Consumerextends Thread {
    private static final Log log =LogFactory.getLog(Consumer.class);
    private final ConsumerConnector consumer;
    private final String topic;
    public Consumer(String topic) {
        consumer =kafka.consumer.Consumer.createJavaConsumerConnector(
                createConsumerConfig());
        this.topic = topic;
    }
    private static ConsumerConfigcreateConsumerConfig() {
        Properties props = new Properties();
       props.put("zookeeper.connect", KafkaProperties.zkConnect);
        props.put("group.id",KafkaProperties.groupId);
       props.put("zookeeper.session.timeout.ms", "400");
       props.put("zookeeper.sync.time.ms", "200");
       props.put("auto.commit.interval.ms", "1000");
        return new ConsumerConfig(props);
    }
    public void run() {
        Map<String, Integer>topicCountMap = new HashMap<String, Integer>();
        topicCountMap.put(topic, newInteger(1));
        Map<String,List<KafkaStream<byte[], byte[]>>> consumerMap =consumer.createMessageStreams(topicCountMap);
        KafkaStream<byte[], byte[]>stream = consumerMap.get(topic).get(0);
        ConsumerIterator<byte[], byte[]>it = stream.iterator();
        while (it.hasNext()) {
            log.info("+message: " +new String(it.next().message()));
        }
    }
    public static void main(String[] args) {
        Consumer client = new Consumer("cluster_statistics_topic");
        client.

     辅助类:

public interface PropertiesSettings {

    final static String CONSUMER_FILE_NAME = "consumer.properties";
    final static String PRODUCER_FILE_NAME = "producer.properties";
    final static String TOPIC_NAME = "cluster_statistics_topic";
    final static String TOPIC_A = "cluster_statistics_topic_A";
}


package com.kafka.utils;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

/**
 * @author JohnLiu
 * @version 0.1.0
 * @date 2014/8/27
 */
public class PropertiesParser {

    private static final Log log = LogFactory.getLog(PropertiesParser.class);
    /* properties file type */
    Properties props = null;

    /* constructor method*/
    public PropertiesParser(Properties props) {
        this.props = props;
    }

    /**
     * Get the trimmed String value of the property with the given
     * <code>name</code>.  If the value the empty String (after
     * trimming), then it returns null.
     */
    public String getStringProperty(String name) {
        return getStringProperty(name, null);
    }

    /**
     * Get the trimmed String value of the property with the given
     * <code>name</code> or the given default value if the value is
     * null or empty after trimming.
     */
    public String getStringProperty(String name, String def) {
        String val = props.getProperty(name, def);
        if (val == null) {
            return def;
        }

        val = val.trim();

        return (val.length() == 0) ? def : val;
    }

    private Properties loadPropertiesFile() {
        Properties props = new Properties();
        InputStream in;
        ClassLoader cl = getClass().getClassLoader();
        if (cl == null)
            cl = findClassloader();
        if (cl == null)
            try {
                throw new ProcessingException("Unable to find a class loader on the current thread or class.");
            } catch (ProcessingException e) {
                e.printStackTrace();
            }
        in = cl.getResourceAsStream(PropertiesSettings.CONSUMER_FILE_NAME);
        try {
            props.load(in);
        } catch (IOException ioe) {
            log.error("can't load " + PropertiesSettings.CONSUMER_FILE_NAME, ioe);
        }
        return props;
    }

    private ClassLoader findClassloader() {
        // work-around set context loader for windows-service started jvms (QUARTZ-748)
        if (Thread.currentThread().getContextClassLoader() == null && getClass().getClassLoader() != null) {
            Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
        }
        return Thread.currentThread().getContextClassLoader();
    }

    public static Properties getProperties(final String fileName) {
        Properties props = new Properties();
        InputStream in = Thread.currentThread().getContextClassLoader()
                .getResourceAsStream(fileName);
        try {
            props.load(in);
        } catch (IOException ioe) {
            log.error("can't load " + fileName, ioe);
        }
        return props;
    }
}

      配置参数文件consumer.properties:

zookeeper.connect=bigdata09:2181,bigdata08:2181,bigdata07:2181
group.id=cluster_group
zookeeper.session.timeout.ms=400
zookeeper.sync.time.ms=200
auto.commit.interval.ms=1000



      配置参数文件producer.properties:

metadata.broker.list=bigdata09:9092,bigdata08:9092,bigdata07:9092
serializer.class=kafka.serializer.StringEncoder
#partitioner.class=com.kafka.producer.SimplePartitioner
request.required.acks=1


     分别执行上面的代码,可以发送或者得到对应topic信息。

     Enjoy yourself!(*^__^*) ……

作者:GreatElite 发表于2014-8-29 10:15:40 原文链接
阅读:85 评论:0 查看评论

java监测工具之jstat

$
0
0

 

 

用以判断JVM是否存在内存问题呢?如何判断JVM垃圾回收是否正常?一般的top指令基本上满足不了这样的需求,因为它主要监控的是总体的系统资源,很难定位到java应用程序。

Jstat是JDK自带的一个轻量级小工具。全称“Java Virtual Machine statistics monitoring tool”,它位于java的bin目录下,主要利用JVM内建的指令对Java应用程序的资源和性能进行实时的命令行的监控,包括了对Heap size和垃圾回收状况的监控。可见,Jstat是轻量级的、专门针对JVM的工具,非常适用。由于JVM内存设置较大,图中百分比变化不太明显

一个极强的监视VM内存工具。可以用来监视VM内存内的各种堆和非堆的大小及其内存使用量。

jstat工具特别强大,有众多的可选项,详细查看堆内各个部分的使用量,以及加载类的数量。使用时,需加上查看进程的进程id,和所选参数。

执行:cd $JAVA_HOME/bin中执行jstat,注意jstat后一定要跟参数。

 

jstat :对VM内存使用量进行监控。
    jstat工具特别强大,有众多的可选项,详细查看堆内各个部分的使用量,以及加载类的数量。使用时,需加上查看进程的进程id,和所选参数。以下详细介绍各个参数的意义。
    jstat -class pid:显示加载class的数量,及所占空间等信息。
    jstat -compiler pid:显示VM实时编译的数量等信息。
    jstat -gc pid:可以显示gc的信息,查看gc的次数,及时间。其中最后五项,分别是young gc的次数,young gc的时间,full gc的次数,full gc的时间,gc的总时间。
    jstat -gccapacity:可以显示,VM内存中三代(young,old,perm)对象的使用和占用大小,如:PGCMN显示的是最小perm的内存使用量,PGCMX显示的是perm的内存最大使用量,PGC是当前新生成的perm内存占用量,PC是但前perm内存占用量。其他的可以根据这个类推, OC是old内纯的占用量。
    jstat -gcnew pid:new对象的信息。
    jstat -gcnewcapacity pid:new对象的信息及其占用量。
    jstat -gcold pid:old对象的信息。
    jstat -gcoldcapacity pid:old对象的信息及其占用量。
    jstat -gcpermcapacity pid: perm对象的信息及其占用量。
    jstat -util pid:统计gc信息统计。
    jstat -printcompilation pid:当前VM执行的信息。
    除了以上一个参数外,还可以同时加上 两个数字,如:jstat -printcompilation 3024 250 6是每250毫秒打印一次,一共打印6次,还可以加上-h3每三行显示一下标题。


语法结构:

Usage: jstat -help|-options

       jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]

 参数解释:

Options — 选项,我们一般使用 -gcutil 查看gc情况

vmid    — VM的进程号,即当前运行的java进程号

interval– 间隔时间,单位为秒或者毫秒

count   — 打印次数,如果缺省则打印无数次

S0  — Heap上的 Survivor space 0 区已使用空间的百分比
S1  — Heap上的 Survivor space 1 区已使用空间的百分比
E   — Heap上的 Eden space 区已使用空间的百分比
O   — Heap上的 Old space 区已使用空间的百分比
P   — Perm space 区已使用空间的百分比
YGC — 从应用程序启动到采样时发生 Young GC 的次数
YGCT– 从应用程序启动到采样时 Young GC 所用的时间(单位秒)
FGC — 从应用程序启动到采样时发生 Full GC 的次数
FGCT– 从应用程序启动到采样时 Full GC 所用的时间(单位秒)
GCT — 从应用程序启动到采样时用于垃圾回收的总时间(单位秒)

实例使用1:

[root@localhost bin]# jstat -gcutil 25444

  S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT

 11.63   0.00   56.46  66.92  98.49 162    0.248    6      0.331    0.579

实例使用2:(25444是java的进程号,ps -ef | grep java)

[root@localhost bin]# jstat -gcutil 25444 1000 5

  S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT

 73.54   0.00  99.04  67.52  98.49    166    0.252     6    0.331    0.583

 73.54   0.00  99.04  67.52  98.49    166    0.252     6    0.331    0.583

 73.54   0.00  99.04  67.52  98.49    166    0.252     6    0.331    0.583

 73.54   0.00  99.04  67.52  98.49    166    0.252     6    0.331    0.583

 73.54   0.00  99.04  67.52  98.49    166    0.252     6    0.331    0.583

我们可以看到,5次young gc之后,垃圾内存被从Eden space区(E)放入了Old space区(O),并引起了百分比的变化,导致Survivor space使用的百分比从73.54%(S0)降到0%(S1)。有效释放了内存空间。绿框中,我们可以看到,一次full gc之后,Old space区(O)的内存被回收,从99.05%降到67.52%。

图中同时打印了young gc和full gc的总次数、总耗时。而,每次young gc消耗的时间,可以用相间隔的两行YGCT相减得到。每次full gc消耗的时间,可以用相隔的两行FGCT相减得到。例如红框中表示的第一行、第二行之间发生了1次young gc,消耗的时间为0.252-0.252=0.0秒。

常驻内存区(P)的使用率,始终停留在98.49%左右,说明常驻内存没有突变,比较正常。

如果young gc和full gc能够正常发生,而且都能有效回收内存,常驻内存区变化不明显,则说明java内存释放情况正常,垃圾回收及时,java内存泄露的几率就会大大降低。但也不能说明一定没有内存泄露。

GCT 是YGCT 和FGCT的时间总和。

以上,介绍了Jstat按百分比查看gc情况的功能。其实,它还有功能,例如加载类信息统计功能、内存池信息统计功能等,那些是以绝对值的形式打印出来的,比较少用,在此就不做介绍。

[root@localhost bin]# ps -ef | grep java

root     25917     1  2 23:23 pts/2    00:00:05 /usr/local/jdk1.5/bin/java -Djava.endorsed.dirs=/usr/local/jakarta-tomcat-5.0.30/common/endorsed -classpath /usr/local/jdk1.5/lib/tools.jar:/usr/local/jakarta-tomcat-5.0.30/bin/bootstrap.jar:/usr/local/jakarta-tomcat-5.0.30/bin/commons-logging-api.jar -Dcatalina.base=/usr/local/jakarta-tomcat-5.0.30 -Dcatalina.home=/usr/local/jakarta-tomcat-5.0.30 -Djava.io.tmpdir=/usr/local/jakarta-tomcat-5.0.30/temp org.apache.catalina.startup.Bootstrap start

jstat -class pid:显示加载class的数量,及所占空间等信息。

实例使用3:

[root@localhost bin]# jstat -class 25917

Loaded  Bytes  Unloaded  Bytes     Time

2629    2916.8       29   24.6     0.90

jstat -compiler pid:显示VM实时编译的数量等信息。

实例使用4:

[root@localhost bin]# jstat -compiler 25917

Compiled Failed Invalid   Time   FailedType FailedMethod

     768      0       0   0.70            0

jstat –gccapacity :可以显示,VM内存中三代(young,old,perm)对象的使用和占用大小,如:PGCMN显示的是最小perm的内存使用量,PGCMX显示的是perm的内存最大使用量,PGC是当前新生成的perm内存占用量,PC是但前perm内存占用量。其他的可以根据这个类推, OC是old内纯的占用量。

[root@localhost bin]# jstat -gccapacity 25917

NGCMN       640.0

NGCMX       4992.0

NGC         832.0

S0C         64.0

S1C         64.0

EC          704.0

OGCMN       1408.0

OGCMX       60544.0

OGC         9504.0

OC          9504.0                  OC是old内纯的占用量

PGCMN       8192.0                  PGCMN显示的是最小perm的内存使用量

PGCMX       65536.0                 PGCMX显示的是perm的内存最大使用量

PGC         12800.0                 PGC是当前新生成的perm内存占用量

PC          12800.0                 PC是但前perm内存占用量

YGC         164

FGC         6

jstat -gcnew pid: new对象的信息

[root@localhost bin]# jstat -gcnew 25917

 S0C    S1C    S0U    S1U   TT MTT  DSS      EC       EU     YGC     YGCT

 64.0   64.0   47.4   0.0   2  15   32.0    704.0    145.7    168    0.254

jstat -gcnewcapacity pid: new对象的信息及其占用量

[root@localhost bin]# jstat -gcnewcapacity 25917

 NGCMN  NGCMX   NGC   S0CMX  S0C   S1CMX  S1C   ECMX    EC      YGC   FGC

640.0  4992.0  832.0 64.0   448.0 448.0  64.0   4096.0  704.0  168     6

jstat -gcold pid: old对象的信息。

[root@localhost bin]# jstat -gcold 25917

   PC       PU        OC          OU       YGC    FGC    FGCT     GCT

 12800.0  12617.6     9504.0      6561.3   169     6    0.335    0.591

jstat -gcoldcapacity pid:old对象的信息及其占用量。

[root@localhost bin]# jstat -gcoldcapacity 25917

OGCMN      OGCMX        OGC         OC       YGC   FGC    FGCT     GCT

1408.0     60544.0      9504.0      9504.0   169     6    0.335    0.591

jstat -gcpermcapacity pid: perm对象的信息及其占用量。

[root@localhost bin]# jstat -gcpermcapacity 25917

PGCMN      PGCMX       PGC         PC      YGC   FGC    FGCT     GCT

8192.0    65536.0    12800.0    12800.0   169     6    0.335    0.591

jstat -printcompilation pid:当前VM执行的信息。

[root@localhost bin]# jstat -printcompilation -h3  25917 1000 5

每1000毫秒打印一次,一共打印5次,还可以加上-h3每三行显示一下标题。

Compiled  Size  Type Method

     788     73    1 java/io/File <init>

     788     73    1 java/io/File <init>

     788     73    1 java/io/File <init>

Compiled  Size  Type Method

     788     73    1 java/io/File <init>

     788     73    1 java/io/File <init>

 

 



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


ITeye推荐



移动端的数据可视化呈现Top 25案例

$
0
0

每天都会有大量的信息向我们迎面扑来,其中包含了大量的图表和数据。一方面,枯燥繁杂的数据会让用户感到烦闷纠结,而设计师的巧妙设计能化腐朽为神奇,让数据以用户易于理解的方式呈现出来。

另一方面,数据图表也有着文字无法比拟的表现力,大量的数据以可以浓缩到一个简单的图表中呈现出来,说明问题。它们可以应用于呈现股市波动,可以反映天气变化,可以呈现网站访问状况,可以反映人体健康。合理地使用图表,化繁为简,下面的25个图表设计的案例,应该能给你不少启发~

Stats iPhone UI by Unity

URL:  https://dribbble.com/shots/1218212-Stats-iPhone-UI

GLEIS7 ENTERTRAINMENT APP by Claudia Eggimann

URL:  https://www.behance.net/gallery/GLEIS7-ENTERTRAINMENT-APP/11073203

App Analytics by Sergey Zolotnikov

URL:  https://dribbble.com/shots/1209235-App-Analytics

Weathertron by Ryan Lucas

URL:  https://www.behance.net/gallery/Weathertron/9787065

My IT Expert IOS Flat app design by UI Kreative

URL:  https://www.behance.net/gallery/My-IT-Expert-IOS-Flat-app-design/10802643

Weather app by Anu Raveendran

URL:  https://www.behance.net/gallery/15687727/Weather-app

Stats iOS 7 style by David Cristian

URL:  https://dribbble.com/shots/1207855-Stats-iOS-7-style-free-Fireworks-png

GLEIS7 ENTERTRAINMENT APP by Claudia Eggimann

URL:  https://www.behance.net/gallery/GLEIS7-ENTERTRAINMENT-APP/11073203

Step Counter app by Marusa Novak

URL:  http://designwebkit.com/showcases/30-mobile-app-designs-featuring-counters-graphs/

Management App – Mauve by Ismail MESBAH

URL:  https://www.behance.net/gallery/10267413/Management-App-Mauve

Pillow: Smart Sleep Cycle Alarm Clock by Neybox Interactive

URL:  https://www.behance.net/gallery/17697691/Pillow-Smart-Sleep-Cycle-Alarm-Clock-

Android App Concept Calendar View by Alek Manov

URL:  https://dribbble.com/shots/1261886-Android-App-Concept-Calendar-View

Electric bike dashboard by Romina Kavcic

URL:  https://dribbble.com/shots/1028419-Electric-bike-dashboard

BISPECK – UI/UX DESIGN by Scott Henderson

URL:  https://www.behance.net/gallery/BISPECK-UIUX-DESIGN/10091019

Graph screen (WIP) by Zeki

URL:  https://dribbble.com/shots/1069083-Graph-screen-WIP

EM by Seven

URL:  https://dribbble.com/shots/1169335-EM

W2B Drive App, Statistics page by Oleg Toptalov (4EPIKart)

URL:  https://dribbble.com/shots/964969-W2B-Drive-App-Statistics-page

Expenses manager app by DSEEER Kate

URL:  https://www.behance.net/gallery/Expenses-manager-app/8637505

Smart stats by Romina Kavcic

URL:  https://dribbble.com/shots/1201422-Smart-stats

RIGID STATS : A statistics App by Jagadish Thanki

URL:  https://www.behance.net/gallery/RIGID-STATS/14895069

Focus Statistics by Iris

URL:  https://dribbble.com/shots/1488721-Focus-Statistics

Dashboard UI by Vitaly Rubtso

URL:  https://dribbble.com/shots/1543973-Dashboard-UI

iPhone Data App by Octav Design

URL:  https://dribbble.com/shots/1071376-Iphone-Data-App

Plano UI Kit v.1 – Flat UI Kit by Edwin “Eddie” Diaz

URL:  https://dribbble.com/shots/1244496-Plano-UI-Kit-v-1-Flat-UI-Kit

Nameless app by Nicolas Bussière

URL:  https://dribbble.com/shots/1518860-Nameless-app

自:优设网


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

技术团队看板方法实践的难点分析

$
0
0

  CTO俱乐部看板研修班开课! 北京、上海、深圳三站火热报名中!感兴趣的朋友可扫描左侧二维码加入看板公开课与路宁、何勉两位讲师直接沟通!

成功加入 CTO俱乐部会员并 免费开通企业会员,即可 获赠6个月《程序员》iPad/Android版电子刊。会员权益:个人主页、定期餐叙、最新周刊、折扣优惠、《程序员》杂志、大会门票、人才招聘、每月赠书等, 查看详情


随着互联网行业的发展,以及目前市场和业务变化的速度,对业务敏捷性的要求也越来越高。随着敏捷开发方法逐步实践推广,互联网公司的产品开发能力也在逐步提升。

如何引导团队从产品开发视角关注到业务价值快速交付的视角,是未来需要在互联网公司去实践的方向,通过限制在制品数量以及度量价值流,拉动团队关注价值流动的速度以实现业务的快速响应,是很多公司下一步希望达到的目标。百度工程效率部资深敏捷教练姜丽芬在谈及看板方法未来的发展时说到“看板方法在未来几年会是支持互联网时代业务敏捷性要求的一个很重要的方法”。

姜丽芬在采访中分享了自己所理解的看板思想核心:通过限制在制品数量形成拉动系统以暴露系统问题和瓶颈,度量价值流动以发现改进机会;并通过团队的协作,不断改进和演化出合适的流程、方法,实现高效、顺畅的产品开发价值流,最终实现组织业务的敏捷性。

看板带来四类变革

通过理解看板方法,并在组织中付诸实践,姜丽芬认为看板方法的引入能带来多方面的变革。

  • 对人的影响。

    对于关注价值流动这件事情,很多团队还无法做到,很多团队更多地还在关注和应对具体的一件件事情上,他们会接很多的事情,并行很多工作,缺少目标感;看板方法的引入可以改变人对自己做的事情有合理的理解和认识,建立价值交付的视角,对组织实现业务的快速交付会有很大的帮助。

  • 管理方面的影响。

    每个人所在的组织中都有一定的管理规则和机制,每个技术团队也有自己的管理方法,但是大家对于这些规则的理解和认识是不同的,通过看板方法将这些管理规则和约束可视化出来,并且让团队中的每个人认识和理解这规则背后的意义,对提升管理的效率以及拉动团队中每个人的主动协作,相互配合会产生积极正向的影响。

  • 流程方面的影响。

    虽然大家都理解流程是为业务服务的,有时候流程的定义会偏离这个方向,我们使用看板方法将价值流可视化出来,并且通过看板系统和WIP拉动系统暴露出流程问题和瓶颈,通过度量Lead Time来有效识别和发现改进机会,会使得流程越来越符合业务的需要,将流程的作用真正发挥出来实现业务的快速交付。

  • 业务方面的影响。

    当组织中的人、管理和流程都关注在业务价值交付上,那整个组织的目标会达成统一,团队和部门之间的协作效率自然会有效改进,在这种情况下不只是某个团队所营造的系统,整个组织系统都在以业务敏捷性为导向的情况下运作,对于业务的影响和促进也就会自然发生。



在姜丽芬目前的团队中,一直在逐步尝试引入看板方法的各方面实践:

可视化方面

  • 使用物理墙将团队中的工作项包括业务Story、技术优化、线上问题、技术调研采用不用的颜色区分开;

  • 将价值流程从输入开始到发布上线整个过程阶段显示出来;

  • 将工作项遇到的问题和阻碍也在看板中做可视化;将过程阶段的流转规则在看板中显示出来,比如开发完成转入测试的规则,测试完成可以上线的规则。



度量方面

“我们也尝试在在卡片上记录每张开始和结束时间,也并行使用系统记录价值流动的LeadTime,计算观察LeadTime的分布,找到异常点,分析原因,逐步优化改进价值流动提高流程的可预测性等。”姜丽芬介绍说。

通过引入这些实践,”姜丽芬介绍说团队可以自发的发现流程中的问题,能拉动团队进行自组织的优化改进流程,同时也会引导团队关注团队共同的价值产出而不只是关注自己是否完成了自己的工作,团队的自组织能力以及协助能力上会有明显的改进提高。

技术团队实践看板方法的难点

虽然看板方法适合任何类型的产品开发项目,但一开始在组织试点看板方法时需要选择具有合适场景的团队,比如团队当前遇到的问题和看板方法的核心思想和实践有较好的匹配,在这点上还是会有些困难。

  • 在已经实施Scrum的团队引入看板方法,如何让团队了解看板方法和Scrum有什么不同是个难点,如何在Scrum实施成熟的团队中再引入看板方法可以给团队带来更深入的改进收益这点也较为困难;

  • 看板方法强调从现状出发,一开始可视化出目前团队开发流程的所有现状是个挑战;

  • 产品的需求有大有小,大部分团队习惯用工作量做估算来决定发布周期频率内做多少工作量的需求而非需求个数,所以让团队使用WIP来限制在制品数量较困难;

  • 另外看板方法关注价值流动,通过识别瓶颈和改进机会,拉动团队协作提升流程效率,但也同时提出了对团队的每个人的能力要求相对均衡,并且可以随时解决团队遇到的问题,有时候团队中的每个个体能力发展的方向会有所不同,这需要和管理达到较好的平衡也会是个挑战。



对于其他想深入接触和学习看板方法的人,姜丽芬也分享了自己的建议和提醒。“学习看板方法首先需要了解看板方法产生的背景和历史,了解当初看板方法的使用场景以及当时希望解决的问题和达到的目标,并且理解为什么在那样的场景下看板方法可以产生作用。”她介绍道。

对看板希望深入接触和学习的同学,熟读《看板方法》这本书以及参加看板方法的培训课程是非常必要的;如果可以实地看到或听到一些看板实践的案例会更好。“假如希望把看板方法引入到自己所在的组织和团队的时候,建议大家要事先清晰地了解所在组织和团队的环境和上下文,包括组织的文化,管理机制,产品特点等,这些环境清晰了解之后,还需要明确通过看板方法达想实现什么目标,解决什么问题,希望给团队带来哪些影响和促进等等,再选择一个团队进行试点实践。” 姜丽芬建议说。


CTO俱乐部是目前国内最有影响力、规模最大的技术管理者分享与交流平台,由全球最大中文IT社区CSDN创办。CTO俱乐部实行会员免费申请、实名认证的加入机制。自2009年创办以来,已有注册会员13000余名,覆盖国内数千家IT公司和各行业企业研发部门的CTO、技术副总裁、首席架构师、技术总监、工程总监等高级技术管理者。更多精彩分享与交流机会,欢迎加入CTO俱乐部、关注CTO俱乐部微信号csdn-cto。


atlas+lvs+keepalived mysql多主复制负载均衡搭建

$
0
0
基于mysql的负载均衡有很多种方式,如haproxy,前面一篇博客有介绍,还可以用更高效lvs做负载均衡,下面是基于percona xtradb cluster的三个节点的多主复制+atlas的lvs负载均衡,其实这里是不需要用atlas的,因为atlas是用来做连接池和读写分离的,而多主架构是不需要读写分离的(如果是基于mysql replication的就需要atlas做负载均衡了),但为了测试atlas能不能用lvs做负载均衡,就顺便做了下实验。

1.节点规划
1.1 mysql数据节点:
db169
db172
db173
三个节点为xtradb cluster节点。
 
1.2 keepalived节点:
db162
db163
虚拟ip为192.168.1.201 
haproxy节点(仅为了对比lvs的性能才安装的):db169(部署在xtradb cluster的一个节点上)

1.3 atlas节点:和xtradb cluster节点部署在一起,也为三个节点
注意:atlas和mysql要部署在一个节点上,如果不在一个节点上则不能用lvs dr模式负载均衡

1.4 客户端测试节点:db55
ip地址为192.168.1.*  ,节点名为db+ip地址末位

2.安装lvs及keepavlied(db162、db163上)
2.1安装依赖包
yum -y install kernel-devel make gcc openssl-devel libnl*
下载并连接linux kernel文件,注意版本要一致(uname -a)
[root@db163 ~]# ln -s /usr/src/kernels/2.6.32-358.el6.x86_64/ /usr/src/linux
安装keepalived、lvs
[root@db162 ~]# yum install ipvsadm
[root@db162 ~]# yum install keepalived
[root@db163 ~]# yum install ipvsadm
[root@db163 ~]#  yum install keepalived

2.2.配置keepavlied,注意lvs不需要单独配置,在keepalived里配置就行了
[root@db162 ~]# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived

global_defs {
   router_id MySQL_LB1
}

vrrp_sync_group VSG {
    group {
        MySQL_Loadblancing
    }
}

vrrp_instance MySQL_Loadblancing {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 101
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 123456
    }
    virtual_ipaddress {
        192.168.1.201
    }
}

virtual_server 192.168.1.201 1234 {
    delay_loop 6
    lb_algo rr
    lb_kind DR
    # nat_mask 255.255.255.0
    #persistence_timeout 50
    protocol TCP

    real_server 192.168.1.169 1234 {
        weight 3
        TCP_CHECK {
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 3
            connect_port 1234
        }
    }
    real_server 192.168.1.172 1234 {
        weight 3
        TCP_CHECK {
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 3
            connect_port 1234
        }
    }
real_server 192.168.1.173 1234 {
        weight 3
        TCP_CHECK {
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 3
            connect_port 1234
        }
    }
}
 
备机上的keepalived配置 
[root@db163 ~]# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived

global_defs {
   router_id MySQL_LB2
}

vrrp_sync_group VSG {
    group {
        MySQL_Loadblancing
    }
}

vrrp_instance MySQL_Loadblancing {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 123456
    }
    virtual_ipaddress {
        192.168.1.201
    }
}

virtual_server 192.168.1.201 1234 {
    delay_loop 6
    lb_algo rr
    lb_kind DR
    # nat_mask 255.255.255.0
    #persistence_timeout 50
    protocol TCP

    real_server 192.168.1.169 1234 {
        weight 3
        TCP_CHECK {
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 3
            connect_port 1234
        }
    }
    real_server 192.168.1.172 1234 {
        weight 3
        TCP_CHECK {
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 3
            connect_port 1234
        }
    }
real_server 192.168.1.173 1234 {
        weight 3
        TCP_CHECK {
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 3
            connect_port 1234
        }
    }
}


3.realserver(数据节点)上的配置
分别在三个数据节点db169、db172、db173上安装如下脚本:
[root@db172 ~]# cat /etc/init.d/lvsdr.sh 
#!/bin/bash
VIP=192.168.1.201                     
. /etc/rc.d/init.d/functions                     
case "$1" in
start)
    /sbin/ifconfig lo down  
    /sbin/ifconfig lo up        
    echo "1" >/proc/sys/net/ipv4/conf/lo/arp_ignore    
    echo "2" >/proc/sys/net/ipv4/conf/lo/arp_announce    
    echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore    
    echo "2" >/proc/sys/net/ipv4/conf/all/arp_announce    
    /sbin/sysctl -p >/dev/null 2>&1
    /sbin/ifconfig lo:0 $VIP netmask 255.255.255.255 up
    /sbin/route add -host $VIP dev lo:0  
    echo "LVS-DR real server starts successfully.\n"                    
    ;;    
stop)    
    /sbin/ifconfig lo:0 down    
    /sbin/route del $VIP >/dev/null 2>&1    
    echo "0" >/proc/sys/net/ipv4/conf/lo/arp_ignore    
    echo "0" >/proc/sys/net/ipv4/conf/lo/arp_announce    
    echo "0" >/proc/sys/net/ipv4/conf/all/arp_ignore    
    echo "0" >/proc/sys/net/ipv4/conf/all/arp_announce    
    echo "LVS-DR real server stopped." 
    ;;
status)
    isLoOn=`/sbin/ifconfig lo:0 | grep "$VIP"`
    isRoOn=`/bin/netstat -rn | grep "$VIP"`
    if [ "$isLoOn" == "" -a "$isRoOn" == "" ]; then
       echo "LVS-DR real server has to run yet."
    else
       echo "LVS-DR real server is running."
    fi
    exit 3
    ;;
*)    
    echo "Usage: $0 {start|stop|status}" 
    exit 1    
esac                     
exit 0
增加x权限:chmod +x /etc/init.d/lvsdr.sh 
增加开机自启动:echo "/etc/init.d/lvsdr.sh start" >> /etc/rc.local

4.分别在三个数据节点db169、db172、db173上安装atlas
下载atlas,并yum安装
yum install -y Atlas-2.1.el6.x86_64.rpm 
配置atlas
[root@db172 ~]# cat /usr/local/mysql-proxy/conf/test.cnf 
[mysql-proxy]

#带#号的为非必需的配置项目

#管理接口的用户名
admin-username = admin

#管理接口的密码
admin-password = 123456

#Atlas后端连接的MySQL主库的IP和端口,可设置多项,用逗号分隔
proxy-backend-addresses = 192.168.1.173:3306

#Atlas后端连接的MySQL从库的IP和端口,@后面的数字代表权重,用来作负载均衡,若省略则默认为1,可设置多项,用逗号分隔
proxy-read-only-backend-addresses = 192.168.1.169:3306@1,192.168.1.172:3306@1

#用户名与其对应的加密过的MySQL密码,密码使用PREFIX/bin目录下的加密程序encrypt加密,下行的user1和user2为示例,将其替换为你的MySQL的用户名和加密密码!
pwds = usr_test:/iZxz+0GRoA=, usr_test2:/iZxz+0GRoA= ,root:/iZxz+0GRoA=

#设置Atlas的运行方式,设为true时为守护进程方式,设为false时为前台方式,一般开发调试时设为false,线上运行时设为true
daemon = true

#设置Atlas的运行方式,设为true时Atlas会启动两个进程,一个为monitor,一个为worker,monitor在worker意外退出后会自动将其重启,设为false时只有worker,没有monitor,一般开发调试时设为false,线上运行时设为true
keepalive = true

#工作线程数,对Atlas的性能有很大影响,可根据情况适当设置
event-threads = 10

#日志级别,分为message、warning、critical、error、debug五个级别
log-level = message

#日志存放的路径
log-path = /usr/local/mysql-proxy/log

#SQL日志的开关,可设置为OFF、ON、REALTIME,OFF代表不记录SQL日志,ON代表记录SQL日志,REALTIME代表记录SQL日志且实时写入磁盘,默认为OFF
#sql-log = OFF

#实例名称,用于同一台机器上多个Atlas实例间的区分
#instance = test

#Atlas监听的工作接口IP和端口
proxy-address = 0.0.0.0:1234

#Atlas监听的管理接口IP和端口
admin-address = 0.0.0.0:2345

#分表设置,此例中person为库名,mt为表名,id为分表字段,3为子表数量,可设置多项,以逗号分隔,若不分表则不需要设置该项
#tables = person.mt.id.3

#默认字符集,设置该项后客户端不再需要执行SET NAMES语句
#charset = utf8

#允许连接Atlas的客户端的IP,可以是精确IP,也可以是IP段,以逗号分隔,若不设置该项则允许所有IP连接,否则只允许列表中的IP连接
#client-ips = 127.0.0.1, 192.168.1

#Atlas前面挂接的LVS的物理网卡的IP(注意不是虚IP),若有LVS且设置了client-ips则此项必须设置,否则可以不设置
#lvs-ips = 192.168.1.1

5.启动数据节点(分别在三个数据节点上db169、db172、db173)
5.1 启动mysql数据库
5.2 启动atlas :  /usr/local/mysql-proxy/bin/mysql-proxyd test start
5.3 启动lvs脚本: /etc/init/lvsdr.sh start

6.启动keepalived(db162、db163上)
/etc/init.d/keepalived start

7.验证:
启动keepalived后,主节点为db162,查看vip是不是启动了:
[root@db162 ~]# ip ad
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:1d:7d:a8:40:d9 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.162/24 brd 192.168.1.255 scope global eth0
    inet 192.168.1.201/32 scope global eth0
    inet6 fe80::21d:7dff:fea8:40d9/64 scope link 
       valid_lft forever preferred_lft forever
验证此节点没有1234端口监听:
[root@db162 ~]# netstat -anp|grep 1234
此处无输出

在192.168.1.55(db55)上连接192.168.1.201(注意此节点没有1234端口在监听,发来的连接会被路由到真正的数据节点)
[root@db55 ~]# mysql -h 192.168.1.201 -P1234 -uroot -p123456
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1871354501
Server version: 5.0.81-log Percona XtraDB Cluster binary (GPL) 5.6.19-25.6, Revision 824, wsrep_25.6.r4111

Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| dd                 |
| mcldb              |
| mysql              |
| mysqlslap          |
| performance_schema |
| test               |
+--------------------+
7 rows in set (0.00 sec)
数据是正确的

8.监控lvs
使用sysbench压力测试,然后监控线程分布:
[root@topdb soft]# sysbench --test=oltp --num-threads=100 --max-requests=100000  --oltp-table-size=1000000 --oltp-test-mode=nontrx --db-driver=mysql --mysql-db=dd --mysql-host=192.168.1.201 --mysql-port=1234 --mysql-user=root --mysql-password=123456 --oltp-nontrx-mode=select --oltp-read-only=on --db-ps-mode=disable run
sysbench 0.4.12:  multi-threaded system evaluation benchmark

Running the test with following options:
Number of threads: 100

Doing OLTP test.
Running non-transactional test
Doing read-only test
Using Special distribution (12 iterations,  1 pct of values are returned in 75 pct cases)
Using "BEGIN" for starting transactions
Using auto_inc on the id column
Maximum number of requests for OLTP test is limited to 100000
Threads started!
Done.

OLTP test statistics:
    queries performed:
        read:                            100033
        write:                           0
        other:                           0
        total:                           100033
    transactions:                        100033 (13416.81 per sec.)
    deadlocks:                           0      (0.00 per sec.)
    read/write requests:                 100033 (13416.81 per sec.)
    other operations:                    0      (0.00 per sec.)

Test execution summary:
    total time:                          7.4558s
    total number of events:              100033
    total time taken by event execution: 744.5136
    per-request statistics:
         min:                                  0.71ms
         avg:                                  7.44ms
         max:                                407.23ms
         approx.  95 percentile:              28.56ms

Threads fairness:
    events (avg/stddev):           1000.3300/831.91
    execution time (avg/stddev):   7.4451/0.00
[root@db162 ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.1.201:1234 rr
  -> 192.168.1.169:1234           Route   3      0          33        
  -> 192.168.1.172:1234           Route   3      0          34        
  -> 192.168.1.173:1234           Route   3      0          34        
    
可以看出负载均衡在了三个节点。
另外可以自己关机测试下keepalived的故障转移。

注意点:
1.atlas和mysql数据节点要放在一台机器上,如果atlas在别处搭建,则lvs会无法使用。
2.keepavlied最好和数据节点不在同一台机器上,否则可能会有问题。
3.最好有真机测试,虚拟机上之前一直没捣鼓好。
4.keepalived配置最好根据示例文件修改,如果有空格、tab键不规范,可能造成无法争取读取配置,并且不给出错误提示。
  

该到理性看待微信的时候了!

$
0
0

锐评:微信已经神话了太久,虽然“船票论”已经过去,但微信如今仍是众人崇拜的“入口”级产品。这其中又有多少O2O人希望借此建功立业。但事实上,微信真的如此值得我们崇拜吗?诞生3年后,微信该再次经受用户的检阅。(by,宋宣)

文/谭拯

8月28日,微信支付公布了“微信智慧生活”全行业解决方案,业界又是一片叫好。正好,借此机会来谈谈微信,挑挑骨头,泼点冷水。

各界声音

1、不少朋友对我说,我开了个微信小号,你加吧,出现在我这个号的,都是对我很重要的人。

2、越来越多的朋友们开了微信公众帐号,然后又停止了运营。他们说:时间长了,没新鲜感。玩来玩去没劲!更郁闷的是,想开个菜单,微信还这样限制那样限制。干脆不玩了。

3、一个做电商的朋友告诉我,开个微信小店好难,支付认证一大堆。我的公众号都几万关注者了,淘宝的好多交流活动都请我去分享,微信完全没有动静,除了几场大的宣讲,他们似乎不知道怎么做运营。

4、好多朋友说,我现在还弄不清服务号和订阅号的区别。难道就是发多发少吗?

5、朋友告诉我,打车我还是用独立的滴滴打车软件,网购还是上微淘。“微信打车啊?太麻烦了!” …

现实正离初衷越来越远

两年前,你问张小龙,微信是什么,他会告诉你,微信是一套信息系统,是一款简单的社交工具,是一种生活方式,“关键的使命是沟通”。

两年后呢?

微信起源于kik——一款始终保持简洁的手机通信录社交软件。它在中国的第一个版本是“米聊”,然后便是“微信”——这个后来被称为移动互联网的第一张船票、“万能入口”的大神级产品…

两年来,微信改变了我们的工作生活,给我们展现了移动互联网更多的想象与精彩。而微信也一直努力保持笨拙,保持简洁。他的缔造者张小龙要“再小的个体,也有自己的品牌”,要构建失控的生态,在自然生长中涌现出惊喜。这位哲学艺术范的伟大缔造者,要让“万物相连”,缔造一个通天的“巴别塔”,营造一个洞悉人性、陀螺永不停转的“梦境”。

初衷是美好的,但两年多的发展,却让微信在赞誉与光环中,出现越来越多的与初衷不相协调的杂音。我们看到的现实是:

1、朋友圈正在变成微博。

微信源于kik,并在简洁的聊天信息流中创造性的加入了朋友圈的概念,而这同样源于另一款私密社交软件path。只是,微信的好友数没有限制(path限制50人)。在kik、path依然保持初衷的简洁发展下,朋友圈却越来越笨重:各种信息泛滥,以至于好多人不得不另外开小号交流;关系链也开始变得松散,逐渐掺杂进客户、营销伙伴、甚至陌生人;一些人们开始离开微信,并逐渐转移到更真实有用的垂直细分的APP上:诸如陌陌、小恩爱、辣妈帮、妈妈圈等。

为了保持良好的用户体验,微信开始不停的封杀朋友圈的营销,封杀心灵鸡汤,但都费力不讨好。
其实这些举措都是治表。我们更关心的是,这里是否存在更深层次的原因?这真是我们所要的“人性”吗?

2、公众帐号体系逻辑混乱。

微信一直强调,公众帐号不是营销工具,而重在服务,并将订阅号折叠起来,弱化其营销属性对用户的影响。但近来,微信却在每篇图文消息后增加了阅读与点赞数,这是分明要微博化媒体化的节奏。
但微信的态度仍然是摇摆不定的,在公开阅读数据后,却依然不显示“转发量”等更具潜力的数据,不提供“评论互动”等更深入的功能(一个移动互联网的交流工具,评论还要到电脑后台才能看到),而这不过是五十步笑百步而已,如此扭扭捏捏,是要闹那样?

再回头看看微信一直强调的服务能力——“给企业和组织提供更强大的业务服务与用户管理能力”。
微信只塑造了广州交警、南方航空之类的标杆案例。而中小企业、以及更为广大的个体经营者,他们对做好微信公众帐号的服务,做好与用户的互动更有强烈的需求,但是鲜见微信有扶持引导的举措与计划,认证难、开菜单难、开店难、咨询难,门槛太高,让很多微信运营者丧失了信心。

微信的杀伐倒是很厉害,出来混都不容易。微信不在自我规则的制定上找原因,老是拿屁民开刀又有何用?

3、我们玩微信,到底是在玩什么?

我们玩微信,到底是在玩什么?除了聊天,刷朋友圈,其他功能你还使用多少?

微信一如既往的希望保持简洁,“在不增加复杂度的情况下让功能自然出现”,两年来,非常克制的增加了“购物”、“团购”、“打车”等功能。

这些功能有用吗?当然有。只是打开几率较低,而这些功能,也正在使微信变得越来越重,而微信原本可以有更多精力去做更多有利于生态成长的事情。

微信对于普遍用户,核心功能还是IM,还是沟通。这或许就是宿命。

4、电商,在中心化平台和群体生态之间徘徊,正在错失良机。

一方面,微信把大量的时间和精力都投在了对京东这样的PC电商巨头的收购与资本运作上。最后给了京东的微信一级入口。把PC商城搬上微信,建立了一个“中心化”的购物平台。

另一方面,微信一直想做一个“去中心化”的生态,那就是对个体的扶持,让“再小的个体,也有自己的品牌”。

但是,到目前为止,微信,却对“中心化”的电商平台投入有余,而对“去中心化”的生态关注不足。目前泛义上的微店概念混乱,微商城、微盟、微店、微信商城、微信小店、口袋通、口袋购物…种类繁多;微信入住门槛高,流程复杂,咨询更是无从开口;真正需要品牌的中小企业无所适从。而对于这个生态的培育,比如组织交流、活动、宣讲、培训、示范、如何开店,如何发挥公众帐号的功能,则似乎根本就没有这门心思。

平台化还是020,PC商城的延伸还是群体生态的建立,有这么纠结吗?想到了乙川弘文给乔布斯的那句话:“所有这些问题都是幻象。你把所有东西都分了类。天才与傻瓜,好与坏。如果你见到任何事物都要做评判,就不会理解设计与空的意义”

还有谁说过,微信对淘宝是降维攻击,是三维对二维?这样下去,还是吗?

5、蹒跚前进的微信支付。

春节我在《何不顺着微信红包破微信的局》一文表达过,微信红包只是给人们打了鸡血,而微信支付是不可能那么容易普及,线下场景的培育不是一朝一夕,看看支付宝这么多年的努力就造了。
微信红包只是让支付宝虚惊了一场。而对线下支付场景的打造,对于金融的理解,支付宝依然走在前面。而另一方面,微信的支付安全也普遍让人担心,更郁闷的是,也没有人提供服务或者咨询,于是很多人保守的选择了观望。

6、微信搜索,你要干哪样?

5.4版本一发布,微信搜索一出来,很多人又奔走呼告了:微信搜索来了,百度完了。大有当年微信支付来了,支付宝要去死了的气势。

微信搜索真能挑战百度?反正我是不信,在一个封闭的系统内,缺乏完善的生态基础,微信搜索能干哪样呢?

7、失败的广点通。
这个广告体系,有充分的大数据技术支撑,并充分运用了分布式的精神,在机制设计上无可挑剔。只是广点通的点击率低,单价收益低,根本问题还是如前面一样,缺乏一个有价值的公众帐号生态,如何玩转?

乱象背后的原因

以上种种乱象,根本原因可能只有一个 :中央集权破坏了社群生态。

现在的发展,在逐渐偏离微信的初衷,它正在越来越变为一个商业运作平台,一个资本博弈的空间,成为世人眼中的万能流量入口,在逐渐成为一个中心化的集权,而不是一个失控的生态。

这一切,或许都源于微信成长太快了,移动互联网有价值的产品太少了。于是微信一枝独秀,成为人们眼中万能的流量入口,希望一入微信便化龙。于是各种资本、收购、利益都向微信涌来,扰乱了发展的节奏,恐怕早已不是微信的本意。

于是,最基本的信息系统流畅性越来越存在问题。而这样做下去,情况可能会更糟。

1、这套信息系统,是关于连接的,整个生态的设计,也应该是连接的延伸,关于人、物、商品,应该是有机统一的。

连接的起点,是基于通信录的交流,继而延伸出在此基础上的朋友圈;即便是后面的游戏,也与连接相关。而购物等模块的加入,更像是资本博弈的结果,缺乏必然的逻辑递进关系,这与微信的信息流体验是割裂的。这样的设计与体验,不利于生态的成长。

2、入口从来不止一个。IM就是IM、购物就是购物,用户的习惯是难以改变。

“从京东618期间的数据也可以显示:“腾讯旗下的各种入口为其导流,发出了10亿红包,移动端订单比例也不过是从18%升至25%。即便是以京东3天50亿流水来计算,手机QQ和微信两大入口的贡献恐怕也不过3亿上下,单纯归到微信身上可能更小。”

“同样的问题也出在大众点评和同程身上,两者分别拥有团购和机票入口,但是前者5月在团购市场整体环比增长12.8%的情况下,仅有8.3%的增长,和美团的差距进一步拉大(29.06亿:12.05亿),甚至不及百度糯米的8.8%环比增长,微信入口作用并未能体现出来。后者更是在上线之后再无消息。”
这样下去,没有体现出入口价值的微信就有些危险了。而更要命的是,原本应该建设的生态跟不上,微信的机会,正在失去。

3、而微信存在的问题,除了产品,更见于运营。

腾讯以产品见长,但运营却一再显现出短板。财付通、拍拍网等,做一个死一个,除了领域不同,可能与基因也是相关联的。腾讯擅长产品,微信团队对人性的研究更是通透得无以复加。他们专注于做产品,却没将产品之外的的社群生态运营起来。相比淘宝天猫,在商家的指引、培训交流、组织运营、规则制定、生态培育等方面有天壤之别。 或许,梦境正酣的微信是时候回归初心了。

如何回归极简

而微信至今,依然是伟大的产品。以上论调,不过是班门弄斧,鸡蛋里挑骨头。只是觉得,微信更应该向信息系统回归,向简单回归,有所为有所不为。

1、朋友圈、公众帐号体系要重新审视,或许需要从根本考虑,而不是修修补补:

(1)朋友圈规则的重新审视。例如:我们真需要无节制的加好友?能不能对好友进行圈层划分,辅助我们对好友进行管理? 现实中的我们总是生在无数个圈子,各个圈子有不同规则。为什么到了微信的生态系统,就要在一起大杂烩而毫无限制?或许这是为了简洁,或者是其他社交工具的使命。但是,有微博的前车之鉴,越来越重的朋友圈是不是该重新审视一下起点?在极速前进时,回头看看path、kik,他们的极致与简洁如何保持?

(2)公众账号体系是未来微信生态建设的根本,对于帐号体系,或许不是折叠或者封杀就可以了事的。

对于公众帐号,乃至一些探索性的功能,微信是否可以放开相关限制,譬如分等级赋予不同权限区分对待?譬如对于一些开菜单、开微店等“正常的需求”,提供一些“便捷性”的基础工具,帮助个体用户运营和成长,而不是一棍子打死、全部拒绝?

这样,多花些耐心和精力,才能更好的给运营者更多的信心,有助于微信生态的建设和成长。

2、坚定做好“去中心化”的社群电商

京东购物,其实是对pc时代淘宝模式的抄袭,是一种跟随策略,这样的做法是无法超越的;而且,移动互联网有自身的特征,与pc端的玩法完全不一样。 微信要做的,不是照搬淘宝、京东、pc模式。而是要在移动端构建一个完全不同的、全新的、基于信息系统流转的电商生态圈,实现人、物、商品等的万物相连。这是一个全新的世界,一个全新的电商系统,这才是微信的王道。

“微信背后电商的生态基础是人流和资讯流,在此基础上实现商品流,但淘宝、天猫的生态基础是商品流,在此基础上实现人流。商品为中心的时代,将过渡到以人为中心的时代。换句话说,淘宝和天猫是以货架为主导的集市生态,微信公众号是以粉丝经营为主导的全新品牌专营店。”

微信就是要做这样的生态。移动互联网的世界,是小而美的世界;移动互联网的世界,是社群崛起的世界。移动社交加上口碑营销的效应在社群电商里是最理想的商业形态,这个形态,是失控的,是去中心化的。

这个生态需要制定全新的规则,而不是百度的竞价排名,不是阿里的直通车。微信应该完全改变一种思维逻辑。微信的根本,就是一个个的小而美的个体,这些个体,大多对于流量的需求量并不大,甚至只为一小部分人服务;“微信的最大特点是把每一个新客户变成老客户,并把老客户变成长期的付费用户,这是微信公众号和其他电商体系最大的不同之处。”微信的使命,应该充分运用移动互联网的分布式架构,构建一套机制,让他们涌现出来。

或许,微信电商的方向在于pagerank、adwords等类似的机制,而不是竞价排名、流量直通车、商城等老一套的逻辑。

3、不仅仅做产品,更要做好运营。

现在微信官方的服务从认证、开通支付、微信小店等远远跟不上需求;微信做到这个阶段,应该把服务与产品技术同等对待。要重视用户的声音,真正帮助帐号运营者,为用户和商户解决服务问题的能力。不仅仅技术上提供接口,服务上也要提供“接口”,让服务和宣传模块化和标准化,激励和帮扶广大的“小个体”梳理品牌、产生连接、构建生态。

4、让搜索引擎为生态服务。

微信搜索不是一个入口,也不是另一个门户,它只应是微信生态的辅助性配置。只有基础生态完善了,各种帐号体系成长了,搜索引擎才有价值。包括后续的智能硬件、物联网等一系列将出现的功能,都应该是为了整个生态服务。

就在今日(8月28日),微信支付公布了“微信智慧生活”全行业解决方案,以微信公众号+微信支付为基础,帮助传统行业将原有商业模式“移植”到微信平台。“这预示着微信再次加大商业化开放步伐,为合作伙伴提供更强大的连接能力”。

这是O2O去中心化社群生态的向前一步。只是,微信从来都不缺乏这样超前创新的产品理念,而公众帐号体系从一开始也为这样的生态奠定了基础。更关键在于:“只怕微信建设太慢”,又重产品轻运营,期间还被资本等各种因素干扰,以至分心、犹豫、模凌两可。

但我仍然相信,微信能为我们带来一座通天的“巴别塔”,构建一个陀螺永不停转的梦境。只是,梦境正在醒来,留给微信的时间不多了。

责编:宋宣

本文原载于钛媒体,原文标题为:智慧微信?它正变得我们越来越看不懂

circumrent:社会化租赁能取代贪婪的房屋中介吗?

$
0
0

circumrent

从十几年前来北京租房到现在,找中介支付高昂佣金的模式一直就没有改变过。互联网改变了所有的领域,好像就是撼动不了租房市场格局。而且中介化程度越来越高。至少十几年前你花心思去找,还能找到房东直租的机会,现在几乎就找不着了。

这个问题也困扰两位去纽约创业的年轻人,“从被房屋中介骗,到花上几个星期寻找不收其他费用的理想公寓来省钱,可以说我们为了在纽约租下一间公寓受尽了磨难。”两位20多岁的公司创始人尼基尔·格雷格(Nikhil Gregg)和凡西·加特拉加达(Vamsi Katragadda)写道。于是他们创办了 Circumrent,其运作方式是:目前的租户在社交网络上分享他打算搬走的计划,然后合格的租户先来看房。这样业主和租户可以省下中介费,而前任租户也可获得回报(在社交网络分享公寓信息可以获得报酬)。这样做不仅节省成本,还能找到合格的租户。尼基尔介绍说,纽约的公寓平均每年要空置28天,这一成本需要业主承担。因此及时找到租户能够让业主早点收取租金,同时还能减少空置率。

你觉得这个方法如何?他们能改变现在的租房市场吗?

网站:http://circumrent.com/

猜您喜欢:

Restolib’在巴黎崛起 租赁业务创新模式分析

汽车租赁创新:Silvercar为何只提供单一品牌型号及颜色的车?

创业家特稿:“去中介化”将成行业趋势

社会化C2C网站Yardsellr

3个社会化电视应用
无觅

本文版权属于- 商业不靠谱 Bukop.com -转载请务必保留版权信息。
商业不靠谱(bukop.com)致力于汇聚全球新兴的商业模式与创新趋势,在全球范围内整合优秀商业创意和案例,并将这些好点子提供给具有企业家头脑的创业者,以及对创新和挖掘新商机有兴趣的朋友。


项目之路-敏捷开发菜鸟版

$
0
0

    一晃就又是一个月过去了,到了管理端,心里想的就是如何把乱七八糟的事情有序排列,让团队持续地的产出。虽说基本不用敲代码,但同时参与3个项目,感觉略累,这是一场马拉松,要么走过终点吐口气,要么走火入魔。

    经过大概一个月的准备,8月份一个正式的创业项目终于确定下来,进入开发阶段。

    该项目虽然技术难度不高,属于是垂直领域的产品,但大大的挑战还是有的。

     我们的优势:

    线下运营团队已经实战两年,并且有过万的客户量,领头大哥也有强悍的市场地推能力。

    技术成员有2个,并且熟悉该业务;具备国际视野的设计师有1个。

    我们的挑战:

    我们是学生团队。技术不够强悍,对外招聘又不现实。

    解决方案:

    我出面找有比较有能力的学生参与进来,最终项目成员有7人;一人设计,一人APP界面实现,一人APP整合,一人APP交互,一人web前端,一人java后端,而我来做架构&项目管理。

    OK,简单的前期铺垫就到这里,接下来进入本文主题,按敏捷开发宣言的路线走。

     敏捷开发宣言:

个体和交互 胜过   过程和工具

团队合作的最大难度不是技术,而是人。对于我们这个立马从外部拉起,立马开工的团队,敏捷开发适合我们吗?要知道,敏捷开发最重要的就是团队默契,其次是个人综合能力,最后就是专长。
在这个点上,有一个比较成熟的套路,那就是每天几分钟的站立会议,大家来交心,昨天做了什么,今天要做什么,遇到什么问题&解决思路。但这个套路我们用不了,因为我们工作时间太过自由(不是公司制度)。
一开始是这样的,我跟大家说,我们每天下午一起到机房工作如何?其它时间就自由安排。但只有3人说可以做到这样。缘由就不说了,没问题的,有时需要集结,再一起过来就行了。
敏捷开发的话,团队协作工具是为沟通&交互的。
我们技术部组建了QQ群,可以及时发布,大家测试&交流;我加了其他所有人飞信,需要集合的适合,会群发短信给大家;然后使用了worktile,进行工作分配。
worktile
 目前的主要个体交互点是这样的:设计&APP界面实现;APP整合&APP交互;web前端&java后端;我&所有人;但没有极限编程的元素。

可以工作的软件 胜过   面面俱到的文档

我们只有简陋版的文档,用word表格画的界面,标志其关联的数据库表。


我也只通过processon.com做了简单的概念架构图等,把每个模块说明清楚,具体设计&实现就交由相关负责人(当然不是丢过去就是了~)


事实证明,我们在开发过程中,需求还是在改动的,有时是减法,有时是改进,因为能力有限,没办法预先拿出最佳方案。

可以工作的软件,不一定是整合完的,不同人不同时间做出来的模块,都是“可以工作的软件”,软件出来了,思考点马上就清晰了。当然每周任务交付,也不是那么容易实现的,我设计的第一次迭代任务,就完成不了了,所以现在的话,提早进入了大乱斗阶段,整合工作放后,增强沟通,防止战场分散得太厉害。

客户合作 胜过   合同谈判

我们是为自己开发的,当然也有客户,因为项目不是我们技术团队主导的,而是市场运作人员。但即使是内部人员,也无法在一起工作,他们经常要跑动,我们不想出宿舍。开发人员一般也不喜欢开会,所以,每周我会跟客户碰面两次,讨论进展&各种情况,回来可能会调整下载工作计划。

响应变化 胜过   遵循计划

虽说这一点是敏捷开发的好处,但谁愿意听到“变化”这两个字?需要“变化”,是谁的错?

一次完整的开发,就是一场战争,一鼓作气,再而衰,三而竭!

所以响应变化,只能出现在我这个环节。开发前要把各主要系统独立开来,在第一次迭代的过程中,就得与客户确定第二次迭代的内容,当然客户是不懂的设计迭代的内容的,所以由我来安排优先序,最不确定的,最可能改变的,就先不做。(一般是建议最重要,最简单的先做,但我会加多考虑,是否是容易变化的)。

结论

敏捷开发第一建议,团队都要坐到一起,旁边要有白板贴纸……
而这第一小步,我们就没做到了,但开发进度还是可以推动的,虽然不快,我也不知道算不算敏捷,但目前还算顺利,没什么大bug出现。
计划9月15号完成项目初期工作,9月25号发布……
作者:wowkk 发表于2014-8-30 9:14:06 原文链接
阅读:79 评论:0 查看评论

一些常被你忽略的CSS小知识

$
0
0

  1.CSS的color属性并非只能用于文本显示

     对于CSS的color属性,相信所有Web开发人员都使用过。如果你并不是一个特别有经

验的程序员,我相信你未必知道color属性除了能用在文本显示,还可以用作其它地方。它

可以把页面上的所有的东西都变颜色。比如:

      无法显示的图片的alt文字、 list元素的边框、无序list元素前面的小点、有序list元素前面的数字和hr元素等


<span style="font-size:14px;"> 1: <html>

   2: <head>

   3:     <meta http-equiv="content-type" content="text/html;charset=utf-8">

   4:     <style type="text/css">

   5:         #div1

   6:         {

   7:             width: 375px;

   8:             height: 265px;

   9:             border: 1px solid blue;

  10:         }

  11:     </style>

  12: </head>

  13: <body>

  14: <div id="div1">

  15:      <img src="test.jpg" alt="图片加载失败" style="color:blue">

  16:     <ol style="color:red;">

  17:         <li style="border: 1px solid">一</li>

  18:         <li>二</li>

  19:         <li>三</li>

  20:     </ol>

  21:     <hr style="color:red" />

  22: </div>

  23: </body>

  24: </html></span>

有图为证:

1

 

    2.CSS里的visibility属性有个collapse属性值:collapse

 

       对于CSS里的visibility属性,相信你用过不下几百次。大多时候,你会把它的值设置

成visible(这是所有页面元素的缺省值),或者是hidden。后者相当于display: none,但仍

然占用页面空间。其实visibility可以有第三种值,就是collapse。


2



    3.CSS的background简写方式里新增了新的属性值

     在CSS2.1里,background属性的简写方式包含五种属性值 – background-color, background-

image,background-repeat, background-attachment, and background-position。从CSS3开始,又增加了3个新的属性值,加起来一共8个。下面是按顺序分别代表的意思:

background: [background-color] [background-image] [background-repeat] [background-attachment]

[background-position] / [ background-size] [background-origin] [background-clip];注意里面的反斜杠,它

更font和border-radius里简写方式使用的反斜杠的用法相似。反斜杠可以在支持这种写法的浏览器里在

position后面接着写background-size。除此之外,你开可以增加另外两个描述它的属性值: background-

origin 和 background-clip.它的语法用起来像下面这个样子:


   1: .example {

   2: background: aquamarine url(img.png)

   3: no-repeat

   4: scroll

   5: center center / 50%

   6: content-box content-box;

   7: }

    4.CSS的clip属性只在绝对定位的元素上才会生效

        在style中加入

   1: img

   2:  {

   3:     width: 200px;

   4:     height: 200px;

   5:     clip: rect(0px 50px 200px 0px)

   6:  }

       在HTML中

1: <img src="bei.jpg" alt="图片加载失败" style="color:blue">
     

     发现并没有裁剪

     3

       对img进行绝对定位


   1: img

   2:     {

   3:         width: 200px;

   4:         height: 200px;

   5:         position: absolute;

   6:         clip: rect(0px 50px 200px 0px)

   7:     }

      clip有效:

4


    5.元素竖向的百分比设定是相对于容器的宽度,而不是高度

         当按百分比设定一个元素的宽度时,它是相对于父容器的宽度计算的,但是,对于一些表示竖向距离的属性,例如padding-top,padding-bottom,margin-top,margin-bottom等,当按百分比设定它们时,依据的也是父容器的宽度,而不是高度。给图片增加一个padding-top:

 1: padding-top: 10%;

    根据效果和估算的距离即可证明是根据宽度来算的

5


    6.border-width属性可以使用预定义常量值

       除了可以使用标准宽度值(例如5px或1em)外,border-width属性可以接受预定义的常量值:medium, thin, 和 thick事实上,如果你不给border-width属性赋值,那它的缺省值是“medium”。

6


    7、你知道table里的empty-cells属性吗?

         css里的empty-cells属性是所有浏览器都支持的,甚至包括IE8,它的用法是下面这个样子:

 1: table { empty-cells: hide;}

估计你从语义上已经猜出它的作用了。它是为HTML table服务的。它会告诉浏览器,当一个table单元格里没有东西时,就隐藏它。

  7 

但是,empty-cells仅用于“分离边框”模式,即:border-collapse:separate;


    8、font-style的oblique属性值

         对与css的font-style属性,我估计大家每次见到的都是使用“normal”或 “italic”两个属性值。但事实上,你还可以让它赋值为“oblique”。


    9、word-wrap和overflow-wrap是等效的

         word-wrap并不是一个很常用的CSS属性,但在特定的环境中确实非常有用的。我们经常使用的一个例子是让页面中显示一个长url时换行,而不是撑破页面。在原本的div中添加一个子div,设置word-wrap属性

 

   1: <div style="width:250px;height:250px;border:1px solid red;word-wrap:break-word">

   2:          My father was a self-taught mandolin player.

   3:     He was one of the best string instrument players in our town.

   4:     He could not read music, but if he heard a tune a few times,

   5:     he could play it. When he was younger,

   6:  </div>

效果

8

没有对长单词进行裁剪,而是将长单词作为整体另起一行显示。将word-wrap替换为overflow-wrap,效果一样。

但是,需要注意的是word-break属性,其会对长单词进行裁剪


   1: <div style="width:250px;height:250px;border:1px solid red;word-break:break-all">

   2:          My father was a self-taught mandolin player.

   3:     He was one of the best string instrument players in our town.

   4:     He could not read music, but if he heard a tune a few times,

   5:     he could play it. When he was younger,

   6:     </div>

效果

      9

 

附:word-wrap取值:

10

word-break取值:

11

原文: http://www.ido321.com/450.html











作者:u011043843 发表于2014-8-30 9:00:42 原文链接
阅读:52 评论:0 查看评论

Redis集群方案及实现

$
0
0

之前做了一个Redis的集群方案,跑了小半年,线上运行的很稳定
差不多可以跟大家分享下经验,前面写了一篇文章  数据在线服务的一些探索经验,可以做为背景阅读

应用

我们的Redis集群主要承担了以下服务:
1. 实时推荐
2. 用户画像
3. 诚信分值服务

集群状况

集群峰值QPS 1W左右,RW响应时间999线在1ms左右
整个集群:
1. Redis节点: 8台物理机;每台128G内存;每台机器上8个instance
2. Sentienl:3台虚拟机

集群方案


Redis Node由一组Redis Instance组成,一组Redis Instatnce可以有一个Master Instance,多个Slave Instance

Redis官方的cluster还在beta版本,参看 Redis cluster tutorial
在做调研的时候,曾经特别关注过KeepAlived+VIP 和 Twemproxy
不过最后还是决定基于Redis Sentinel实现一套,整个项目大概在1人/1个半月

整体设计

1. 数据Hash分布在不同的Redis Instatnce上
1. M/S的切换采用Sentinel
2. 写:只会写master Instance,从sentinel获取当前的master Instane
3. 读:从Redis Node中基于权重选取一个Redis Instance读取,失败/超时则轮询其他Instance
4. 通过RPC服务访问,RPC server端封装了Redis客户端,客户端基于jedis开发
5. 批量写/删除:不保证事务

RedisKey

public class RedisKey implements Serializable{
	private static final long serialVersionUID = 1L;
	//每个业务不同的family
	private String family;
	
	private String key;
		
	......	
	//物理保存在Redis上的key为经过MurmurHash之后的值
	private String makeRedisHashKey(){
		return String.valueOf(MurmurHash.hash64(makeRedisKeyString()));
	}
	
	//ReidsKey由family.key组成
	private String makeRedisKeyString(){
		return family +":"+ key;
	}

	//返回用户的经过Hash之后RedisKey
	public String getRedisKey(){
		return makeRedisHashKey();
	}
	.....
}


Family的存在时为了避免多个业务key冲突,给每个业务定义自己独立的Faimily
出于性能考虑,参考Redis存储设计,实际保存在Redis上的key为经过hash之后的值

接口

目前支持的接口包括:
public interface RedisUseInterface{
	/**
	 * 通过RedisKey获取value
	 * 
	 * @param redisKey
	 *           redis中的key
	 * @return 
	 *           成功返回value,查询不到返回NULL
	 */
	public String get(final RedisKey redisKey) throws Exception;
	
	/**
	 * 插入<k,v>数据到Redis
	 * 
	 * @param redisKey
	 *           the redis key
	 * @param value
	 *           the redis value
	 * @return 
	 *           成功返回"OK",插入失败返回NULL
	 */
	public String set(final RedisKey redisKey, final String value) throws Exception;
	
	/**
	 * 批量写入数据到Redis
	 * 
	 * @param redisKeys
	 *           the redis key list
	 * @param values
	 *           the redis value list
	 * @return 
	 *           成功返回"OK",插入失败返回NULL
	 */
	public String mset(final ArrayList<RedisKey> redisKeys, final ArrayList<String> values) throws Exception;
	/**
	 * 从Redis中删除一条数据
	 * 
	 * @param redisKey
	 *           the redis key
	 * @return 
	 *           an integer greater than 0 if one or more keys were removed 0 if none of the specified key existed
	 */
	public Long del(RedisKey redisKey) throws Exception;
	
	/**
	 * 从Redis中批量删除数据
	 * 
	 * @param redisKey
	 *           the redis key
	 * @return 
	 *           返回成功删除的数据条数
	 */
	public Long del(ArrayList<RedisKey> redisKeys) throws Exception;
	/**
	 * 插入<k,v>数据到Redis
	 * 
	 * @param redisKey
	 *           the redis key
	 * @param value
	 *           the redis value
	 * @return 
	 *           成功返回"OK",插入失败返回NULL
	 */
	public String setByte(final RedisKey redisKey, final byte[] value) throws Exception;
	
	/**
	 * 插入<k,v>数据到Redis
	 * 
	 * @param redisKey
	 *           the redis key
	 * @param value
	 *           the redis value
	 * @return 
	 *           成功返回"OK",插入失败返回NULL
	 */
	public String setByte(final String redisKey, final byte[] value) throws Exception;
	
	/**
	 * 通过RedisKey获取value
	 * 
	 * @param redisKey
	 *           redis中的key
	 * @return 
	 *           成功返回value,查询不到返回NULL
	 */
	public byte[] getByte(final RedisKey redisKey) throws Exception;
	
	/**
	 * 在指定key上设置超时时间
	 * 
	 * @param redisKey
	 *           the redis key
	 * @param seconds
	 * 			 the expire seconds
	 * @return 
	 *           1:success, 0:failed
	 */
	public Long expire(RedisKey redisKey, int seconds) throws Exception;
}

写Redis流程

1. 计算Redis Key Hash值
2. 根据Hash值获取Redis Node编号
3. 从sentinel获取Redis Node的Master
4.  写数据到Redis
		//获取写哪个Redis Node
		int slot = getSlot(keyHash);
		RedisDataNode redisNode =  rdList.get(slot);

		//写Master
		JedisSentinelPool jp = redisNode.getSentinelPool();
		Jedis je = null;
		boolean success = true;
		try {
			je = jp.getResource();
			return je.set(key, value);
		} catch (Exception e) {
			log.error("Maybe master is down", e);
			e.printStackTrace();
			success = false;
			if (je != null)
				jp.returnBrokenResource(je);
			throw e;
		} finally {
			if (success && je != null) {
				jp.returnResource(je);
			}
		}



读流程

1. 计算Redis Key Hash值
2. 根据Hash值获取Redis Node编号
3. 根据权重选取一个Redis Instatnce
4.  轮询读
		//获取读哪个Redis Node
		int slot = getSlot(keyHash);
		RedisDataNode redisNode =  rdList.get(slot);

		//根据权重选取一个工作Instatnce
		int rn = redisNode.getWorkInstance();

		//轮询
		int cursor = rn;
		do {			
			try {
				JedisPool jp = redisNode.getInstance(cursor).getJp();
				return getImpl(jp, key);
			} catch (Exception e) {
				log.error("Maybe a redis instance is down, slot : [" + slot + "]" + e);
				e.printStackTrace();
				cursor = (cursor + 1) % redisNode.getInstanceCount();
				if(cursor == rn){
					throw e;
				}
			}
		} while (cursor != rn);



权重计算

初始化的时候,会给每个Redis Instatnce赋一个权重值weight
根据权重获取Redis Instance的代码:
	public int getWorkInstance() {
		//没有定义weight,则完全随机选取一个redis instance
		if(maxWeight == 0){
			return (int) (Math.random() * RANDOM_SIZE % redisInstanceList.size());
		}
		
		//获取随机数
		int rand = (int) (Math.random() * RANDOM_SIZE % maxWeight);
		int sum = 0;
	
		//选取Redis Instance
		for (int i = 0; i < redisInstanceList.size(); i++) {
			sum += redisInstanceList.get(i).getWeight();
			if (rand < sum) {
				return i;
			}
		}
		return 0;
	}



作者:yfkiss 发表于2014-8-30 17:20:08 原文链接
阅读:75 评论:0 查看评论

华为设计总监:如何做设计决策

$
0
0

yoyo-make-design-decisions-

设计师最苦恼的一个问题,也许就是设计决策。

为什么苦恼?为什么难?

有一种说法。现在很多公司都非常注重用户体验设计,这是好事。但是大部分公司最终做产品用户体验设计决策的人,都不是设计出身。这不是坏事,但是这是一个问题,问题在于,不同的专业背景带来的思考维度总是略有差别。设计师如何能做出设计决策,或者说辅助上级做出合理有效的设计决策,是非常关键的。

例如一个市场出身的老板,也许更关注的是营收;一个技术出身的老板,可能更关注的是技术创新;一个品牌出身的老板,关注产品的品牌效应可能多一些。

那纯粹从用户体验的唯一角度出发去评判产品设计的优劣,是否合理呢?

我个人觉得那是理想状态。

理想状态是什么呢?例如:

网上购买火车票打1折。
海量免费信息类网站没有一条广告。
玩网络游戏道具全部免费。
音乐产品没有VIP用户,大家都可以不花钱享受一样的服务。
机场候机楼的VIP厅谁都可以进去休息。
做一个非常理想化的设计稿,然后让开发兄弟永无止境地去实现,甚至是一些近期无法实现的功能也要一直尝试下去。
产品设计生命周期没有时间点、没有资源限制、没有技术评审、没有成本控制。

当然,理想状态很难存在。真实状态是,一个产品设计的结果,是用户期望、市场策略、品牌战略、商业诉求、营收压力、技术瓶颈、资源投入成本、时间、公司价值取向、领导风格、团队文化等很多因素在影响。

所以设计师要做有效的设计决策,首先就要理解这样的不理想,或者说不完美的状态,是常态。

接下来,从这样不完美的状态中去找平衡,找突破。

第一点,懂别人。

例如讨论一个产品设计点,一个很看重点击量和曝光的产品经理在和你讨论你的设计会影响他的KPI的时候,你不一定就要坚强地就着用户体验第一、用户喜欢才是王道这个逻辑往下说,而是应该从产品经理的角度去思考问题,想想,能否有方法让量的KPI也能保持甚至提升,同时也能提升用户体验质量。诚然,在没有完美平衡的时候,会有妥协和沮丧。但是从互换思考来考量一个设计决策,至少是开了一个好头,也会赢得合作同事的尊重和信任。

懂别人,带来的要求就是设计师需要有一定的广度。

我们可以不懂用JS如何编程实现一个动态效果,但是我们至少要知道现在主流产品的动态效果趋势,要知道一个效果可行度、成本、对技术平台的要求和压力。

我们可以不懂一个产品页面要实现多少经济利益,一个广告位应该是卖100万还是150万,但是我们要懂得这个页面的价值分为两个,一个是为了用户,一个是为了广告商,那如何取舍取决于我们对产品商业价值的理解,从用户和广告商两个角度来思考问题后带来的综合解决方案。

再细节一点,交互设计师可以不懂如何一笔一笔画一个图标,但是要懂得整个图标在界面中展现的意义是否达到产品设计的预期、商业的预期、交互逻辑的预期。

知识面的广度有一个积累过程,缓慢且痛苦,但是突然爆发的价值是让人吃惊的。

第二点,够专业。

真正强大的设计师,是在无视他的职位、背景的情况下,一样能有权利有信用去做一个设计决策的人。

在整个大环境里,设计师年轻人居多,我们很难以人生阅历、经验论来说服很多合作同事,所以我们靠的是够专业。

专业体现在每个环节。

举一个简单的例子。你是一个交互设计师,做一个页面设计。你肯定会根据业务诉求和自己的专业准则,做一个页面布局。你会设计清楚每个模块放哪儿,每个模块放什么内容,图片和文字的排列组合等。

你的这个设计稿拿出来给大家评审之前,一定要保证你经得住所有问题的拷问。

这里并不是说,你的设计稿需要是完美的,但是你要保证你的设计稿每个地方都是经过思考的。

合作的同事会问很多问题:

为什么图片放左边?
为什么这个位置图片放2个,那个位置图片放3个?
为什么这个文字段落的字体要加粗?
为什么轮播是3个内容块,而不是4个?
为什么广告位要出现在第一屏的最末而不是第二屏的开始?

你不需要每个问题都回答正确,或者说这些问题很多根本没有标准答案。但是你要保证你都思考过,每个问题你都能说出你的逻辑和思考原则。

相信我,在一段项目经验积累后,你的判断会越来越准确。

反过来,如果有任何一个问题,你的答案是:“Sorry,这个问题我没有想过”或者是“啊…… 这个是某某说的让我做的,我不太清楚”,那你的专业度就会受到别人的质疑而大打折扣。

专业度的感染力建立是很直观的。

你第一次做好了,做对了,或者说给别人感觉对了。第二次再做对一次。两次的经验烙印已经能让大部分人相信你。

反言之,如果你第一次的判断就失误,或者给别人不专业的印象,你很难改回你的专业影响。

后面当然有很多可以做的,例如设计师做产品有自己的设计原则、设计文化、宏观思考、微观创新、细节把握等,设计师可以做很多事情来扩大自己的专业感染力。但是每个设计师应该从第一步开始就要做好,一个产品设计的每个细节,都要处处透着设计师的专业。

第三点,够职业。

专业表现你是一个有价值的人,能为产品设计团队提供价值。
职业表现你是一个可以合作的人,能让团队对你放心。

我对毕业生的一个基本要求是:设计稿任何位置不要有一个错别字。这就是一个职业度的细节要求例子。

我们设计师,天生浪漫,性格不羁,是很优美的事情。这些优点会带来一些不合理的地方。现在的职业设计师大多都没有这些问题,不过我也想列举一些设计师特别应该注意的点:

会议上要积极反馈,主动输出设计侧的会议纪要,并列举可执行项。
工作场景外向一点表达,即使你是一个内向的人。
争吵的合理度,该针锋相对的时候针锋相对,该妥协的时候妥协。
不要埋头做事,要学会自我展现和自我表达。
做设计的时候过程要体现出来,不要只给一个结果,有时一个结果不一定能代表你完整的思考过程。
要总结,要沉淀,不能做完一个设计项目就马上进去另一个。
时刻记得工作中,大部分任务是理性的、逻辑的,大部分人不是,所以对事对人要有符合自己性格习惯的应对方法。
有时要急一点。
有时要接受平庸。

第四点,有勇气。

设计师很多时候不能盲目决策,因为他们还没有了解整个产品的形态、商业模式、目标等维度。这个时候如果纯粹从用户体验来决策,也许不会是好结果。

但是当设计师有一定准备度的时候,要有勇气去决策。

当然,决策后结果不对,你肯定会受影响。所以你需要谨慎。

不过当结果是对的时候,正面的价值非常大。

有勇气拍板,一定不要靠一腔热血,而是靠平时对业务的理解、经验的积累、对结果的预判、再加一点点运气。

第五点,有一点点风格。

知识广度有了,专业度也有了,职业度也高,还有热情和勇气。最后你只需要一点点风格了。

这个是设计师特有的东西。

我们不需要像商业人士那样天天西装革履,一本正经。我们可以有很多有趣的工作方式。

有实力作为基础的风格展现,会是一个设计师魅力建设和影响力建设的加分项。

这些风格点会有很多,一些例子:

在严肃激烈的讨论中能讲一些笑话缓和气氛。
和别人大吵一架也不会让别人生气。
能用非常有趣的PPT展现思路。
再生气的时候也能保持微笑耐心讨论。
能快速在白板上用图来表达思路。
合理范围的耳环、纹身、另类发型、炫酷的穿着。
懂得“智者示弱,愚者逞强”的道理。

这些都会成为一个你可能的标签,配合你的基本能力,你整体得到的接受度和记忆点都会不错。

最后回到标题的问题,如何做设计决策?

有了以上五点的积累,你只要不发傻、不耍脾气、讲道理、有自己满意的设计稿,达成一个大家ok你也满意的设计决策还会难么?:)

在这里,读懂尤原庆:

他的成长经历,很有看头:
《推荐阅读!尤原庆的设计之道与成长之路》

他的工作经验,值得参考:
《设计总监尤原庆:我在华为的工作体验》

他的读书方式,值得学习:
《华为设计总监尤原庆:怎样读设计书》

原文地址:设计师尤原庆
作者: @EDC尤原庆

AD18-communication

本文由优设网原创翻译,请尊重版权和译者成果,转摘请附上优设链接,违者必究。谢谢各位编辑同仁配合。

【优设网 原创文章 投稿邮箱:2650232288@qq.com】

================ 关于优设网================
“优设网 uisdc.com“是国内人气最高的网页设计师学习平台,专注分享网页设计、无线端设计以及PS教程。
【特色推荐】
设计师需要读的100本书:史上最全的设计师图书导航: http://hao.uisdc.com/book/
设计微博:拥有粉丝量76万的人气微博 @优秀网页设计,欢迎关注获取网页设计资源、下载顶尖设计素材。
设计导航:全球顶尖设计网站推荐,设计师必备导航: http://hao.uisdc.com
———————————————————–
想在手机上、被窝里获取设计教程、 经验分享和各种意想不到的”福利”吗?
添加 优秀网页设计 微信号:【youshege】优设哥的全拼
您也可以通过扫描下方二维码快速添加:

sdcweixin

优设哥向您推荐:

推荐阅读!尤原庆的设计之道与成长之路(华为设计总监)

设计总监尤原庆:我在华为的工作体验

华为设计总监:如何做好用户研究

Facebook产品设计总监!设计App时的14个必考题

想成为设计总监?先学会如何树立品牌意识
无觅

map-reduce自定义分组自定义排序

$
0
0

 

package group;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.net.URI;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.RawComparator;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.WritableComparable;
import org.apache.hadoop.io.WritableComparator;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
import org.apache.hadoop.mapreduce.lib.partition.HashPartitioner;

/**
#当第一列相同时,求出第二列的最小值
3	3
3	2
3	1
2	2
2	1
1	1
 * @author zm
 *
 * 当第一列相同时,求出第二列的最小值--->  由要求分析如下:
 * 1 必然以 row1来进行分组   
 * 2 必然也是以 row1,row2作为一个整体来进行比较才能有 当第一列相同时,在比较第二列的状态发生
 * 3 mr中,执行流程是 <k0,v0>--><k1,v1>--><k2,v2>--><k3,v3> 
 * 		以 wordcount为例(hello you
 * 					   hello me
 *      <k0,v0>是 行号和当前行内文本
 *      <k1,v1>是经过map()方法后得到的 <hello,1> <you,1> <hello,1> <me,1>
 *      <k2,v2>是经过默认默认排序(以key1的asci码升序排),和默认分组(以key1的asci为基准分组) : <hello,{1,1}>  <me,{1}>  <you,{1}>
 * 		<k3,v3>是经过redecu()方法处理后,真正写出到hdfs文件的最终处理结果
 *     上述流程可知,先执行 map(),执行map()同时根据key执行排序,然后执行分组操作
 *     
 * 结论:
 * 1 基于需要 row1,row2作为一个整体来进行比较,因此自定义 NewK2,重写此类compareTo方法(这里使用升序方式) ,指定排序规则
 * 2 排序后,实现分组时,因为此时的NewK2作为整体,如若用默认规则使用NewK2作为分组基准时,必然分组成6个组,因此指定自定义分组器取代默认规则,注意自定义分组器是对NewK2进行分组
 *  
 *  执行过程中 key value变化:
 *  <k0,v0> --> <k1,v1>----> <k2,v2>---> <k3,v3>:
	<行号,行内容> ---> <(3,3),3> <(3,2),2> <(3,1),1>  <(2,2),2> <(2,2),1> <(1,1),1> --->自定义分组,针对newk2进行分组,
	得到分组结果 <以3为row1的newk2,{3,2,1}> <以2为row1的newk2,{2,1}> <以1为row1的newk2,{1}>--->调用redece,得到<3,1> <2,1> <1,1>
 */
public class MyGroupApp {
	static final String INPUT_PATH = "hdfs://master:9000/hello";
	static final String OUT_PATH = "hdfs://master:9000/out";
	public static void main(String[] args) throws Exception{
		final Configuration configuration = new Configuration();
		final FileSystem fileSystem = FileSystem.get(new URI(INPUT_PATH), configuration);
		if(fileSystem.exists(new Path(OUT_PATH))){
			fileSystem.delete(new Path(OUT_PATH), true);
		}
		final Job job = new Job(configuration, GroupApp.class.getSimpleName());
		//1.1 指定输入文件路径
		FileInputFormat.setInputPaths(job, INPUT_PATH);
		//指定哪个类用来格式化输入文件
		job.setInputFormatClass(TextInputFormat.class);
		
		//1.2指定自定义的Mapper类
		job.setMapperClass(MyMapper.class);
		//指定输出<k2,v2>的类型
		job.setMapOutputKeyClass(NewK2.class);
		job.setMapOutputValueClass(LongWritable.class);
		
		//1.3 指定分区类
		job.setPartitionerClass(HashPartitioner.class);
		job.setNumReduceTasks(1);
		
		//1.4 TODO 排序、分区
		job.setGroupingComparatorClass(MyGroupingComparator.class);
		//1.5  TODO (可选)合并
		
		//2.2 指定自定义的reduce类
		job.setReducerClass(MyReducer.class);
		//指定输出<k3,v3>的类型
		job.setOutputKeyClass(LongWritable.class);
		job.setOutputValueClass(LongWritable.class);
		
		//2.3 指定输出到哪里
		FileOutputFormat.setOutputPath(job, new Path(OUT_PATH));
		//设定输出文件的格式化类
		job.setOutputFormatClass(TextOutputFormat.class);
		
		//把代码提交给JobTracker执行
		job.waitForCompletion(true);
	}

	
	static class MyMapper extends Mapper<LongWritable, Text, NewK2, LongWritable>{
		protected void map(LongWritable key, Text value, Context context) throws java.io.IOException ,InterruptedException {
			final String[] splited = value.toString().split("\t");
			final NewK2 k2 = new NewK2(Long.parseLong(splited[0]), Long.parseLong(splited[1]));
			final LongWritable v2 = new LongWritable(Long.parseLong(splited[1]));
			context.write(k2, v2);
		};
	}
	static class MyReducer extends Reducer<NewK2, LongWritable, LongWritable, LongWritable>{
		protected void reduce(NewK2 k2, java.lang.Iterable<LongWritable> v2s, Context context) throws java.io.IOException ,InterruptedException {
			long min = Long.MAX_VALUE;
			for (LongWritable v2 : v2s) {
				if(v2.get()<min){
					min = v2.get();
				}
			}
			context.write(new LongWritable(k2.first), new LongWritable(min));
		};
	}
	/**
	 * 问:为什么实现该类?
	 * 答:因为原来的v2不能参与排序,把原来的k2和v2封装到一个类中,作为新的k2
	 *
	 */
	static class  NewK2 implements WritableComparable<NewK2>{
		Long first;
		Long second;
		public NewK2(){}
		public NewK2(long first, long second){
			this.first = first;
			this.second = second;
		}
		@Override
		public void readFields(DataInput in) throws IOException {
			this.first = in.readLong();
			this.second = in.readLong();
		}

		@Override
		public void write(DataOutput out) throws IOException {
			out.writeLong(first);
			out.writeLong(second);
		}

		/**
		 * 当k2进行排序时,会调用该方法.
		 * 当第一列不同时,升序;当第一列相同时,第二列升序
		 */
		@Override
		public int compareTo(NewK2 o) {
			final long minus = this.first - o.first;
			if(minus !=0){
				return (int)minus;
			}
			return (int)(this.second - o.second);
		}
		
		@Override
		public int hashCode() {
			return this.first.hashCode()+this.second.hashCode();
		}
		
		@Override
		public boolean equals(Object obj) {
			if(!(obj instanceof NewK2)){
				return false;
			}
			NewK2 oK2 = (NewK2)obj;
			return (this.first==oK2.first)&&(this.second==oK2.second);
		}
	}
	/**
	 * 问:为什么自定义该类?
	 * 答:业务要求分组是按照第一列分组,但是NewK2的比较规则决定了不能按照第一列分。只能自定义分组比较器。
	 */
	static class MyGroupingComparator implements RawComparator<NewK2>{

	// 第一种比较方式:按照对象进行比较
		@Override
		public int compare(NewK2 o1, NewK2 o2) {
			return (int)(o1.first - o2.first);
		}
		// 第二种比较方式: 按照字节进行比较
		/**
		 * @param arg0 表示第一个参与比较的字节数组
		 * @param arg1 表示第一个参与比较的字节数组的起始位置
		 * @param arg2 表示第一个参与比较的字节数组的偏移量
		 * 
		 * @param arg3 表示第二个参与比较的字节数组
		 * @param arg4 表示第二个参与比较的字节数组的起始位置
		 * @param arg5 表示第二个参与比较的字节数组的偏移量
		 */
		@Override
		public int compare(byte[] arg0, int arg1, int arg2, byte[] arg3,
				int arg4, int arg5) {
			return WritableComparator.compareBytes(arg0, arg1, 8, arg3, arg4, 8);
		}
		
	}
}

 



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


ITeye推荐



(转载)Tomcat性能调优方案

$
0
0
一、操作系统调优
对于操作系统优化来说,是尽可能的增大可使用的内存容量、提高CPU的频率,保证文件系统的读写速率等。经过压力测试验证,在并发连接很多的情况下,CPU的处理能力越强,系统运行速度越快。。
【适用场景】 任何项目。
二、Java虚拟机调优
应该选择SUN的JVM,在满足项目需要的前提下,尽量选用版本较高的JVM,一般来说高版本产品在速度和效率上比低版本会有改进。
JDK1.4比JDK1.3性能提高了近10%-20%,JDK1.5比JDK1.4性能提高25%-75%。
因此对性能要求较高的情况推荐使用 JDK1.6。
【适用场景】 任何项目。
三、Apache集成Tomcat
Web 服务器专门处理HTTP请求,应用服务器是通过很多协议为应用提供商业逻辑。虽然Tomcat也可以作web服务器,但其处理静态html 的速度比不上Apache,且其作为web服务器的功能远不如Apache,因此把Apache和Tomcat集成起来,将html和Jsp的功能部分进 行明确分工,让Tomcat只处理Jsp部分,其他的由Apache,IIS等web服务器去处理,由此大大提高Tomcat的运行效率。
如果一个项目中大量使用了静态页面、大量的图片等,并有有较大的访问量,推荐使用Apache集成Tomcat的方式来提高系统的整体性能。
Apache 和Tomcat的整合有三种方式,分别是JK、http_proxy和ajp_proxy.其中JK方式是最常见的方式,JK本身有 两个版本分别是1和2,目前1最新版本是1.2.8,而版本2早已经废弃了。http_proxy是利用Apache自带的mod_proxy模块使用代 理技术来连接Tomcat。Ajp_proxy连接方式其实跟http_proxy方式一样,都是由mod_proxy所提供的功能。只需要把配置中的 http://换成ajp://,同时连接的是Tomcat的AJP Connector所在的端口。
相对于JK的连接方式,后两种在配置上比较简单的,灵活性方面也一点都不逊色。但就稳定性而言不像JK这样久经考验,所以建议采用JK的连接方式。
Apache+JK+Tomcat配置:
使用到的两个配置文件分别是:httpd.conf和mod_jk.conf。其中httpd.conf是Apache服务器的配置文件,用来加载JK模块以及指定JK配置文件信息。mod_jk.conf是到Tomcat服务器的连接定义文件。
【部署步骤】
1.安装Apache服务器
2.部署Tomcat
3.将mod_jk.so拷贝到modules目录下面
4.修改httpd.conf和mod_jk.conf
【适用场景】  大量使用静态页面的应用系统。
四、Apache和Tomcat集群
对 于并发要求很高的系统,我们需要采取负载均衡的方式来分担Tomcat服务器的压力。负载均衡实现大概有四种:第一是通过DNS,但只能简单的 实现轮流分配,不能处理故障;第二是基于MS IIS,windows 2003 server本身就带了负载均衡服务;第三是硬件方式,通过交换机功能或专门的负载均衡设备来实现;第四种是软件的方式,通过一台负载均衡服务器进行,上 面安装软件。使用Apache Httpd Server做负载均衡器,Tomcat集群节点使用Tomcat就可以做到上述第四种方式,这种方式比较灵活,成本相对比较低,另外一个很大的优点就是 可以根据应用情况和服务器的情况做一些灵活的配置。所以推荐使用Apache+Tomcat集群来实现负载均衡。
采 用Tomcat集群可以最大程度的发挥服务器的性能,可以在配置较高的服务器上部署多个Tomcat,也可以在多台服务器上分别部署 Tomcat,Apache和Tomcat整合的方式还是JK方式。经过验证,系统对大用户量使用的响应方面,Apache+3Tomccat集 群> Apache+2Tomcat集群 > Apache集成Tomcat > 单个Tomcat。并且采用Apache+多Tomcat集群的部署方式时,如果一个Tomcat出现宕机,系统可以继续使用,所以在硬件系统性能足够优 越的情况下,需要尽量发挥软件的性能,可以采用增加Tomcat集群的方式。
Apache+Tomcat 集群的方式使用到得配置文件有httpd.conf、mod_jk.conf、 workers.properties。其中mod_jk.conf是对JK信息的配置,包括JK的路径等,workers.properties配置文 件是对Tomcat服务器的连接定义文件。
Apache需要调整运行参数,这样才能构建一个适合相应网络环境的web服务。其中可进行的优化配置如下:
1. 设置MPM(Multi Processing Modules多道处理模块)。ThreadPerChild,这个参数用于设置每个进程的线程数,在Windows环境下默认值是64,最大值是 1920,建议设置为100-500之间,服务器性能高的话值大一些,反之小一些。MaxRequestPerChild表示每个子进程能够处理的最大请 求数。这个参数的值更大程度上取决于服务器的内存,如果内存比较大的话可以设置为很大的参数,否则设置一个较小的值,建议值是3000.
2. 关闭DNS和名字解析   HostnameLookups off
3. 打开UseCanonicalName模块  UseCanonicalName on
4. 关闭多余模块  一般来说,不需要加载的模块有,mod_include.so、mod_autoindex.so、mod_access.so、mod_auth.so.
5. 打开KeepAlive支持
KeepAlive on, KeepAliveTimeout 15 MaxKeepAliveRequests 1000
      根据实际经验,通过Apache和Tomcat集群的方式提高系统性能的效果十分明显,这种方式可以最大化的利用硬件资源,通过多个Tomcat的处理来分担单Tomcat时的压力。
【部署步骤】
1.安装Apache服务器
2.部署Tomcat集群,即多个相同的Tomcat。
3.将mod_jk.so拷贝到modules目录下面
4.修改httpd.conf、mod_jk.conf和workers.properties
【适用场景】  并发用户量及在线使用用户数量比较高的系统。
五、Tomcat自身优化
1. JVM参数调优:-Xms<size> 表示JVM初始化堆的大小,-Xmx<size>表示JVM堆的最大值。这两个值的大小一般根据需要进行设置。当应用程序需要的内存超出堆的 最大值时虚拟机就会提示内存溢出,并且导致应用服务崩溃。因此一般建议堆的最大值设置为可用内存的最大值的80%。在catalina.bat中,设置 JAVA_OPTS='-Xms256m -Xmx512m',表示初始化内存为256MB,可以使用的最大内存为512MB。
2. 禁用DNS查询
  当web应用程序向要记录客户端的信息时,它也会记录客户端的IP地址或者通过域名服务器查找机器名转换为IP地址。DNS查询需要占用网络, 并且包括可能从很多很远的服务器或者不起作用的服务器上去获取对应的IP的过程,这样会消耗一定的时间。为了消除DNS查询对性能的影响我们可以关闭 DNS查询,方式是修改server.xml文件中的enableLookups参数值:
Tomcat4

<Connector className="org.apache.coyote.tomcat4.CoyoteConnector" port="80" minProcessors="5" maxProcessors="75" enableLookups="false" redirectPort="8443" acceptCount="100" debug="0" connectionTimeout="20000" useURIValidationHack="false" disableUploadTimeout="true" />

Tomcat5

<Connector port="80" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" enableLookups="false" redirectPort="8443" acceptCount="100" debug="0" connectionTimeout="20000" disableUploadTimeout="true"/>
3. 调整线程数
通 过应用程序的连接器(Connector)进行性能控制的的参数是创建的处理请求的线程数。Tomcat使用线程池加速响应速度来处理请求。在 Java中线程是程序运行时的路径,是在一个程序中与其它控制线程无关的、能够独立运行的代码段。它们共享相同的地址空间。多线程帮助程序员写出CPU最 大利用率的高效程序,使空闲时间保持最低,从而接受更多的请求。
     Tomcat4中可以通过修改minProcessors和maxProcessors的值来控制线程数。这些值在安装后就已经设定为默认值并且是足够使 用的,但是随着站点的扩容而改大这些值。minProcessors服务器启动时创建的处理请求的线程数应该足够处理一个小量的负载。也就是说,如果一天 内每秒仅发生5次单击事件,并且每个请求任务处理需要1秒钟,那么预先设置线程数为5就足够了。但在你的站点访问量较大时就需要设置更大的线程数,指定为 参数maxProcessors的值。maxProcessors的值也是有上限的,应防止流量不可控制(或者恶意的服务攻击),从而导致超出了虚拟机使 用内存的大小。如果要加大并发连接数,应同时加大这两个参数。web server允许的最大连接数还受制于操作系统的内核参数设置,通常Windows是2000个左右,Linux是1000个左右。
       在Tomcat5对这些参数进行了调整,请看下面属性:
maxThreads    Tomcat使用线程来处理接收的每个请求。这个值表示Tomcat可创建的最大的线程数。
acceptCount    指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理。
connnectionTimeout    网络连接超时,单位:毫秒。设置为0表示永不超时,这样设置有隐患的。通常可设置为30000毫秒。
minSpareThreads    Tomcat初始化时创建的线程数。

maxSpareThreads     一旦创建的线程超过这个值,Tomcat就会关闭不再需要的socket线程。
      最好的方式是多设置几次并且进行测试,观察响应时间和内存使用情况。在不同的机器、操作系统或虚拟机组合的情况下可能会不同,而且并不是所有人的web站点的流量都是一样的,因此没有一刀切的方案来确定线程数的值。
六、APR库使用
Tomcat中使用APR库,其实就是在Tomcat中使用JNI的方式来读取文件以及进行网络传输。可以大大提升Tomcat对静态文件的处理性能,同时如果你使用了HTTPS方式传输的话,也可以提升SSL的处理性能。
一 般在Windows下,可以直接下载编译好的二进制版本的dll库文件来使Tomcat启用APR,一般建议拷贝库文件tcnative- 1.dll到Tomcat的bin目录下。而在Linux下,可以直接解压和安装bin目录下的tomcat_native.tar.gz文件,编译之前 要确保apr库已经安装。
怎么才能判断Tomcat是否已经启用了APR库呢?方法是通过看Tomcat的启动日志:
如果没有启用APR,则启动日志一般有这么一条:
org.apache.coyote.http11.Http11Protocol start
如果启用了APR,则这条日志就会变成:
org.apache.coyote.http11.Http11AprProtocol start
tcnative-1.dll 下载地址:http://tomcat.heanet.ie/native/
    调优综述
       根据以上分析,如果想要Tomcat达到最优的效果,首先要争取使得操作系统以及网络资源达到最优,并且最好使用高版本的JDK。对于有大量静态页面的系 统,采用Apache集成Tomcat的方式,把静态页面交由Apache处理,动态部分交由Tomcat处理,能极大解放Tomcat的处理能力。使用 ARP库也能极大的提高Tomcat对静态文件的处理能力。对于并发要求较高的系统,采用Apache加Tomcat集群的方式,将负载分别分担到多个 Tomcat上,能很大的提高系统的性能,充分利用硬件资源。同时需要对Tomcat自身进行优化,包括增大内存、调节并发线程数等。

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


ITeye推荐



不恰当使用线程池处理 MQ 消息引起的故障

$
0
0

现状

业务部门反应网站访问特别慢,负责运维监控的同事说MQ消息队列积压了,中间件的说应用服务器内存占用很高,GC 一直回收不了内存,GC 线程占了近 100% 的 CPU,其他的基本上都在等待,数据库很正常,完全没压力。没啥办法,线程、堆 dump 出来后,重启吧,然后应用又正常了。

分析

这种故障之前其实也碰到过了,分析了当时 dump 出来的堆后发现,处理 MQ 消息的线程池的队列长度达百万级别,占用了超过 1.3G 内存,这些内存都是没法回收的。

程序的实现目前是这样的:关联系统把消息推送到 MQ 上,我们再从 MQ 上拉消息下来处理;每种类型的消息都有一个线程负责从 MQ 上拉消息,拉下来后封装成线程池的任务提交给相应的线程池去执行。代码可以简化为:

package net.coderbee.mq.demo;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MQListener {
     public ExecutorService executor = Executors.newFixedThreadPool(8);

     public void onMessage(final Object message) {
          executor.execute(new Runnable() {
               @Override
               public void run() {
                    // 耗时且复杂的消息处理逻辑
                    complicateHanlde(message);
               }
          });
     }

     private void complicateHanlde(Object message) {
     }
}

这个实现就是导致故障的根源, Executors.newFixedThreadPool(8)创建的线程池的任务队列是无边界的:

public static ExecutorService newFixedThreadPool(int nThreads) {
     return new ThreadPoolExecutor(nThreads, nThreads,
                                          0L, TimeUnit.MILLISECONDS,
                                          new LinkedBlockingQueue<Runnable>());
}

当时是关联系统出故障了,他们恢复后,往 MQ 里狂推消息,我们系统里面的 MQListener 不断地从 MQ 拉消息下来,直接塞进线程池里,由于线程池处理消息的速度远远慢于消息进入的速度,所以线程池的队列不断增长,直到把所有的堆内存都占用了,这时不断引发 FullGC,但每次 FullGC 都没法回收到内存,应用也就挂死在那了。

之前那次故障也是线程池队列积压导致的,引起的原因是消息处理逻辑调用了外部接口,由于外部接口的响应非常慢,严重拖慢了消息的处理进度,改成异步调用之后好了些。但问题的根源并没有解决,就像昨天关联系统狂推消息后,我们的系统还是挂了。

解决方法

我的思路其实很简单,MQ 是用来系统间解耦的,也是一个缓冲,目前的实现是把处理消息的线程池又用作一个 MQ 了,消息不能不受控地进入线程池的任务队列,所以,要换成使用定长的阻塞队列,队列满了就暂停拉取消息。把线程池替换成:

private int nThreads = 8;
private int MAX_QUEUQ_SIZE = 2000;
private ExecutorService executor = new ThreadPoolExecutor(nThreads,
          nThreads, 0L, TimeUnit.MILLISECONDS,
          new ArrayBlockingQueue<Runnable>(MAX_QUEUQ_SIZE),
          new ThreadPoolExecutor.CallerRunsPolicy());

把线程池队列满的时候直接让调用者(也就是 MQListener)执行任务,这样即延缓了消息拉取的速度,当 MQListener再去拉取消息时,发现线程池有空间时可以提交到线程池,让线程池的工作线程去处理,它继续保持拉取速度。

这样既控制了线程池占用的内存,又可以让消息处理线程池处理不过来时多一个线程处理消息。

由于上面的代码采用调用者执行的方式,那么要考虑消息处理的顺序问题,比如一个订单的处理可能有多个步骤,对应多条 MQ 消息,那么要考虑这些步骤如果乱序了是否可以接受,因为第3步骤的处理消息可能被 MQListener 处理了,而第2步的处理消息还积压在线程池里。


Mysql 慢查询和慢查询日志分析

$
0
0
原链接:http://www.cnblogs.com/wrmfw/archive/2011/09/05/2166929.html
众所周知,大访问量的情况下,可添加节点或改变架构可有效的缓解数据库压力,不过一切的原点,都是从单台mysql开始的。下面总结一些使用过或者研究过的经验,从配置以及调节索引的方面入手,对mysql进行一些优化。
第一步应该做的就是排查问题,找出瓶颈,所以,先从日志入手
开启慢查询日志
mysql>show variables like “%slow%”; 查看慢查询配置,没有则在my.cnf中添加,如下

log-slow-queries = /data/mysqldata/slowquery.log    #日志目录
long_query_time = 1                          #记录下查询时间查过1秒
log-queries-not-using-indexes     #表示记录下没有使用索引的查询
分析日志 – mysqldumpslow
分析日志,可用mysql提供的mysqldumpslow,使用很简单,参数可–help查看

# -s:排序方式。c , t , l , r 表示记录次数、时间、查询时间的多少、返回的记录数排序;
#                             ac , at , al , ar 表示相应的倒叙;
# -t:返回前面多少条的数据;
# -g:包含什么,大小写不敏感的;
mysqldumpslow -s r -t 10  /slowquery.log     #slow记录最多的10个语句
mysqldumpslow -s t -t 10 -g "left join"  /slowquery.log     #按照时间排序前10中含有"left join"的
推荐用分析日志工具 – mysqlsla

wget http://hackmysql.com/scripts/mysqlsla-2.03.tar.gz
tar zvxf mysqlsla-2.03.tar.gz
cd mysqlsla-2.03
perl Makefile.PL
make
make install
mysqlsla /data/mysqldata/slow.log
# mysqlsla会自动判断日志类型,为了方便可以建立一个配置文件“~/.mysqlsla”
# 在文件里写上:top=100,这样会打印出前100条结果。

【说明】
queries total: 总查询次数 unique:去重后的sql数量
sorted by : 输出报表的内容排序
最重大的慢sql统计信息, 包括 平均执行时间, 等待锁时间, 结果行的总数, 扫描的行总数.
Count, sql的执行次数及占总的slow log数量的百分比.
Time, 执行时间, 包括总时间, 平均时间, 最小, 最大时间, 时间占到总慢sql时间的百分比.
95% of Time, 去除最快和最慢的sql, 覆盖率占95%的sql的执行时间.
Lock Time, 等待锁的时间.
95% of Lock , 95%的慢sql等待锁时间.
Rows sent, 结果行统计数量, 包括平均, 最小, 最大数量.
Rows examined, 扫描的行数量.
Database, 属于哪个数据库
Users, 哪个用户,IP, 占到所有用户执行的sql百分比
Query abstract, 抽象后的sql语句
Query sample, sql语句

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


ITeye推荐



[MySQL FAQ]系列 — MySQL复制中slave延迟监控

$
0
0

在MySQL复制环境中,我们通常只根据 Seconds_Behind_Master的值来判断SLAVE的延迟。这么做大部分情况下尚可接受,但并不够准确,而应该考虑更多因素。

首先,我们先看下SLAVE的状态:

yejr@imysql.com [(none)]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
***
Master_Log_File: mysql-bin.000327
Read_Master_Log_Pos: 668711237
Relay_Log_File: mysql-relay-bin.002999
Relay_Log_Pos: 214736858
Relay_Master_Log_File: mysql-bin.000327
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
***
Skip_Counter: 0
Exec_Master_Log_Pos: 654409041
Relay_Log_Space: 229039311
***Seconds_Behind_Master: 3296***

可以看到 Seconds_Behind_Master的值是 3296,也就是SLAVE至少延迟了 3296秒。

我们再来看下SLAVE上的2个REPLICATION进程状态:

yejr@imysql.com [(none)]> show full processlist\G
*************************** 1. row ***************************
Id: 6
User: system user
Host:
db: NULL
Command: ConnectTime: 22005006State: Waiting for master to send event
Info: NULL
*************************** 2. row ***************************
Id: 7
User: system user
Host:
db: NULL
Command: ConnectTime: 3293
State: UpdatingInfo: UPDATE ** SET ** WHERE **

可以看到SQL线程一直在执行UPDATE操作,注意到 Time 的值是 3293,看起来像是这个UPDATE操作执行了3293秒,一个普通的SQL而已,肯定不至于需要这么久。
实际上,在REPLICATION进程中,Time 这列的值可能有几种情况:
1、SQL线程当前执行的binlog(实际上是relay log)中的timestamp和IO线程最新的timestamp的差值,这就是通常大家认为的 Seconds_Behind_Master 值,并不是某个SQL的实际执行耗时;
2、SQL线程当前如果没有活跃SQL在执行的话,Time值就是SQL线程的idle time;

而IO线程的Time值则是该线程自从启动以来的总时长(多少秒),如果系统时间在IO线程启动后发生修改的话,可能会导致该Time值异常,比如变成负数,或者非常大。

来看下面几个状态:

#设置pager,只查看关注的几个status值
yejr@imysql.com [(none)]> pager cat | egrep -i 'system user|Exec_Master_Log_Pos|Seconds_Behind_Master|Read_Master_Log_Pos'

#这是没有活跃SQL的情况,Time值是idle time,并且 Seconds_Behind_Master 为 0
yejr@imysql.com [(none)]> show processlist; show slave status\G
| 6 | system user | | NULL | Connect | 22004245 | Waiting for master to send event | NULL |
| 7 | system user | | NULL | Connect |   13 | Has read all relay log;**
Read_Master_Log_Pos: 445167889
Exec_Master_Log_Pos: 445167889Seconds_Behind_Master: 0
#和上面一样
yejr@imysql.com [(none)]> show processlist; show slave status\G
| 6 | system user | | NULL | Connect | 22004248 | Waiting for master to send event | NULL |
| 7 | system user | | NULL | Connect |   16 | Has read all relay log;**
Read_Master_Log_Pos: 445167889
Exec_Master_Log_Pos: 445167889Seconds_Behind_Master: 0
#这时有活跃SQL了,Time值是和 Seconds_Behind_Master 一样,即SQL线程比IO线程“慢”了1秒
yejr@imysql.com [(none)]> show processlist; show slave status\G
| 6 | system user | | NULL | Connect | 22004252 | Waiting for master to send event | NULL |
| 7 | system user | | floweradmin | Connect |   1 | Updating | update **
Read_Master_Log_Pos: 445182239
Exec_Master_Log_Pos: 445175263Seconds_Behind_Master: 1
#和上面一样
yejr@imysql.com [(none)]> show processlist; show slave status\G
| 6 | system user | | NULL | Connect | 22004254 | Waiting for master to send event | NULL |
| 7 | system user | | floweradmin | Connect |   1 | Updating | update **
Read_Master_Log_Pos: 445207174
Exec_Master_Log_Pos: 445196837Seconds_Behind_Master: 1

好了,最后我们说下如何正确判断SLAVE的延迟情况:
1、首先看 Relay_Master_Log_FileMaster_Log_File是否有差异;
2、如果 Relay_Master_Log_FileMaster_Log_File是一样的话,再来看 Exec_Master_Log_PosRead_Master_Log_Pos的差异,对比SQL线程比IO线程慢了多少个binlog事件;
3、如果 Relay_Master_Log_FileMaster_Log_File不一样,那说明延迟可能较大,需要从MASTER上取得binlog status,判断当前的binlog和MASTER上的差距;

因此,相对更加严谨的做法是:
在第三方监控节点上,对MASTER和SLAVE同时发起 SHOW BINARY LOGSSHOW SLAVE STATUS\G的请求,最后判断二者binlog的差异,以及 Exec_Master_Log_PosRead_Master_Log_Pos的差异。

例如:
在MASTER上执行 SHOW BINARY LOGS的结果是:

+------------------+--------------+
| Log_name | File_size |
+------------------+--------------+
| mysql-bin.000009 | 1073742063 |
| mysql-bin.000010 | 107374193 |
+------------------+--------------+

而在SLAVE上执行 SHOW SLAVE STATUS\G的结果是:

Master_Log_File: mysql-bin.000009 Read_Master_Log_Pos: 668711237
Relay_Master_Log_File: mysql-bin.000009
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
***Exec_Master_Log_Pos: 654409041

***
  Seconds_Behind_Master: 3296
***

这时候,SLAVE实际的延迟应该是:
mysql-bin.000009这个binlog中的binlog position 1073742063和 SLAVE上读取到的binlog position之间的差异延迟,即:

1073742063 - 668711237 = 405030826个binlog event

并且还要加上 mysql-bin.000010这个binlog已经产生的 107374193个binlog event,共

107374193 + 405030826 = 512405019个binlog event

后记更新:

可以在MASTER上维护一个监控表,它只有一个字段,存储这最新最新时间戳(高版本可以采用event_scheduler来更新,低版本可以用cron结合自动循环脚本来更新),在SLAVE上读取该字段的时间,只要MASTER和SLAVE的系统时间一致,即可快速知道SLAVE和MASTER延迟差了多少。不过,在高并发的系统下,这个时间戳可以细化到毫秒,否则哪怕时间一致,也是有可能会延迟数千个binlog event的。

Spring Rmi配置

$
0
0
现在远程调用一般用RPC,webservice或者Rmi,而目前用的比较多的是webservice和Rmi。

webservice和rmi的最主要的区别,rmi的客户端和服务端都必须是java,webservice没有这个限制,webservice是在http协议上传递xml文本文件。与语言和平台无关,rmi是在tcp协议上传递可序列化的java对象,只能用在java虚拟机上,绑定语言。 RMI是EJB远程调用的基础,仅用RMI技术就可以实现远程调用,使用EJB是为了实现组件,事物,资源池,集群等功能.WebService是通过XML来传输数据,可用http等协议因此可在异构系统间传递,并且可以穿过防火墙,可在公网上远程调用。

以下是spring中配置Rmi的一个简单例子:

1.首先在src下建立一个接口(本人的是com.shinelife.inter):

package com.shinelife.inter;

public interface IBaseServiceRmi {
    public String SayHelloRmi(String name);
}

2.然后实现接口的方法:

package com.shinelife.services;

import com.shinelife.inter.IBaseServiceRmi;

public class BaseServiceRmi implements IBaseServiceRmi {

  public String SayHelloRmi(String name) {
          // TODO Auto-generated method stub
          return "Hello: "+name;
     }

}

3.然后就是配置remote.xml:

在src下面新建一个xml文件然后复制添加以下内容(注:头文件的对象配置很重要,配置不当会报错):

<?xml version="1.0" encoding="UTF-8"?>
<!-- spring 远程服务对象配置-->
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:flex="http://www.springframework.org/schema/flex"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

   <!-- 远程对象暴露  开始 -->
   
        <bean id="BaseServiceRmiExporter" class="org.springframework.remoting.rmi.RmiServiceExporter">
         <!-- 调用Service --> 
        <property name="service">
            <ref bean="BaseServiceRmi" />
        </property>
        <!-- 客户端调用时使用的名字 -->
        <!-- value值是给用户调用 --> 
        <property name="serviceName">
            <value>BaseServiceRmi</value>
        </property>
        <!-- service 接口 -->
        <property name="serviceInterface">
            <value>com.shinelife.inter.IBaseServiceRmi
            </value>
        </property>
        <!-- 注册端口号 --> 
        <property name="registryPort">
            <value>6100</value>
        </property>
        <property name="servicePort">
            <value>7100</value>
        </property>
    </bean>
  <!-- 远程对象暴露  结束 -->
</beans>

4.本人以上的例子是自己建立的一个remote.xml文件,而一般都是直接把这些配置到spring的配置文件applicationContext.xml里,而这种在这里就不研究了。主要说说外部配置Rmi的方式。

光是添加了一个remote.xml是不够的,还需要在spring的applicationContext.xml里面注入:

<bean id="BaseServiceRmi" class="com.shinelife.services.BaseServiceRmi"></bean>

这样spring才能找到并加载这个bean。

5.由于本人的是webservice项目,所以启动服务是用的配置web.xml,也可以用main入口函数加载,对于main加载,就不讲述了,这里讲述web.xml配置,以下是web.xml的部分内容:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    version="2.5"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee  
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

<context-param>
       <param-name>contextConfigLocation</param-name>
       <param-value>/WEB-INF/classes/applicationContext.xml,classpath:remote.xml
       </param-value>
    </context-param>

</web-app>

以上是服务端方面的配置,下面是客户端:

6.将com.shinelife.inter整个包拷贝到客户端下(注意服务端与客户端的包名保持一致)

7.在客户端的src下面新建一个Rmi.xml的文件,配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN"
  "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
   
    <bean id="BaseServiceRmi" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">       
         <!-- BaseService是调用服务端serviceName的value --> 
        <property name="serviceUrl">
            <value>rmi://127.0.0.1:6100/BaseServiceRmi</value>
        </property>
         <!-- service接口 --> 
        <property name="serviceInterface">
            <value>com.shinelife.inter.IBaseServiceRmi</value>
        </property>
    </bean>
</beans>

8.然后建立一个main函数测试Rmi服务:

import org.apache.xbean.spring.context.ClassPathXmlApplicationContext;
import com.shinelife.inter.IBaseServiceRmi;

public class testRmi {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:Rmi.xml"); 
        IBaseServiceRmi baseService = (IBaseServiceRmi) context.getBean("BaseServiceRmi");
        System.out.println( baseService.SayHelloRmi("Joker"));
    }
}

9.测试结果:Hello: Joker

10.总结:Rmi是一个比较高效的远程调用方式,可以将整个函数方法作为参数进行远程调用,达到通信的目的,利用Rmi也可以减少很多的工作量。当然,在其他方面本人就不做结论,本人这也是分享一下搭建Rmi的方法。以便以后学习。

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


ITeye推荐



雅虎宣布停止开发YUI

$
0
0
雅虎官方博客宣布终止开发开源的JavaScript工具库Yahoo User Interface library (YUI)。雅虎开发者解释说,行业趋势发生了改变。过去几年,Web平台经历了激烈变革,相比以前如今的JavaScript几乎是无处不在。Node.JS的出现允许JavaScript在服务器端使用, 以及新的包管理器如npm,构建工具如Grunt,应用程序框架,测试工具等的出现,使得YUI之类的大型JavaScript工具库不再像以前那样受到社区的关注。今天大多数开发者将大型JavaScript库视为他们不想被锁定的围墙花园,结果是过去几年雅虎收到的问题报告和pull请求都日渐稀少,许多YUI的核心模块都没有活跃的维护者,检查递交补丁的评审人员也非常少。雅虎只能做出艰难的决定终止开发,但雅虎仍然会维护现有的程序,修复严重bug。






马云为什么开除了95%的MBA高材生?

$
0
0

小白叨一叨:MBA的高材生们一直是受名企欢迎的香饽饽,而马云却不这么认为。在2000年的互联网泡沫末期,那个阶段的阿里巴巴核心高管团队里,一共有12个人。除了马云,其他人全部来自名校商学院MBA.但是在短短几年,这些哈佛、斯坦福等知名院校的MBA纷纷被马云“劝退”了。

u=199986331,2601770012&fm=23&gp=0

 

实际上,马云开除MBA们的理由很简单:企业家不是商学院能够培养得出来的。如何培养出企业家,一是来自大量失败的实践,二是来自大量的对口跟踪研究,除此之外,别无他法。

在2000年,互联网泡沫的末期,马云拿到了软银孙正义的投资,这时,马云认为公司进入了全新的大企业阶段,之前的创业人员的历史使命已经快结束了。他觉得当时的创业人员只能担任连长以下的职位,而团长级以上必须由MBA担任。

在那个阶段的阿里巴巴核心高管团队里,一共有12个人。除了马云,其他人全部来自名校商学院MBA.但是在短短几年,这些哈佛、斯坦福等知名院校的MBA纷纷被马云“劝退”了。马云对这些人的评价是:口才一流,执行力末流,讲起理念来头头是道,但是这些道理马云自己可以讲得更头头是道,需要他们发挥价值,比如企业应该加强管理的地方,这些MBA却往往无从下手。

这是很多迷信MBA的企业家走过的类似弯路。早年的草根企业家多半会对那些背景华丽的商学院学生心怀艳羡,但是在初创和早期发展阶段,企业还是要靠真正有执行力的人来推动——能真正将学院经典理论转化为执行力的人又有多少呢?

经验比理论重要?

在2000年前后,马云的“开除”并非是刻意搞逆向思维,而是实事求是:做事做不来的MBA们,必须被开除,否则,阿里巴巴会完蛋了。务实一向是马云的长处,他这么干,是对当年国内重视学历、轻视能力的主流趋势的一种鞭挞。好在这些年来,国内形势已经改变了,现在顶着众多名校桂冠的人,没有经验依然很难找到如意的工作。即使是海归,在国内找工作也会比较困难——因为他们没有任何国内实际经验。

事实上,商学院的课程大多只能告诉MBA学生该做什么,但如何去做,却要靠有实践经验的学生在理论指导下不断摸索。马云所看重的“做事”,其实就是一种经验和理论互相推动下的执行能力,一般而言,这种能力一定是在实际工作中积累而来的。所以马云曾经说过,履历卖相再好的职业经理人,如果是一架飞机的引擎用在拖拉机上,最终还是飞不起来。

在理论框架下完全靠悟性、天赋参透执行和日常管理的细节,这样的人在美国也只有乔布斯等寥寥数人,在中国可能更罕见。

所以一旦某人担任过某企业的总经理,那么,同行业的企业就可很愿意挖角了。挖一个有实践管理经验的总经理等于直接复制了一套管理方法——该总经理肯定知道在细节和大局上该如何逐一着手“做事”。当然,如果这个有经验的总经理去读了EMBA,则会更进一步,从知道要怎么做,变成了知道为什么要这样做——这样的人才更加厉害……

马云认为适用的才是人才,金庸给马云办公室有一幅题字:“善用人才为大领袖要旨,此刘邦、刘备之所以创大业也。愿马云兄常勉之。”所以阿里巴巴内部的企业氛围是,谁能够在自己的位置上做出成绩的就是人才,否则顶着再多的MBA、EMBA、博士、博导等等都没用。

为什么MBA不靠谱?因为这些带着各种桂冠的所谓的人才,并没有任何实际经验,甚至也没有太多对口研究经验:国内的高校里面是笼统学习;而国外的商学院研究的多年以前的案例,或者都是一些高精尖的超前理论,而非针对某个行业,进行有基础和扎实的系统化学习。

如果从人力资源的角度来看,如果要为企业做中层干部储备,找一些专业学科毕业生从头培养,反而会比找一些拿着名校商学院MBA履历的人要强很多,因为这些人的知识基础更加扎实,心态也更平和。所以你会发现,现在大学本科里的管理学越来越不受青睐了,因为学了很难找到工作,比较有前途的是工作几年,知道自己哪里缺乏理论,或者哪里需要提升高度了 ,再有的放矢去读个管理学的研究生,这样会比较有前途。

商学院培养不出来企业家

中国企业在过去30年是粗放型发展,竞争对手不多;现在是精细型发展,竞争对手多如牛毛。生意越来越难做,只有通过创新、提升技术含量、营销扩大和升级,才能提升企业发展空间。但是,中国很多企业家无法适应这一新形势,他们还在凭过去打江山的本事来应付当下的过度竞争。这样一来,不但企业家自己很累,发展也出现了瓶颈,有的还走了下坡路。

如今,光靠能“干事”的人来做好做大企业也遇到了问题。多数行业产能过剩,很多拥有实际管理和操作经验的人才都不再具有明显优势了。因为这些人不是行业研究专家,不具备研究行业突围方向和思考战略的能力。他们的强项是把管理经验复制、拷贝过来——而由于重复竞争,他们拷贝过来的东西在竞争激烈时就变得同质化了。

企业家们现在面临的问题包括:自己的老方法不适用于现在的环境了;用了同质化的职业经理人也无效;再用咨询公司合伙人仍然无效。比如李宁公司就是如此。为什么咨询公司合伙人加盟救不了李宁公司?那是因为,咨询公司合伙人并非是服装、运动鞋的专业研究战略专家,如果仅仅靠分析行业数据和写报告,恐怕是没办法治理企业的。

从企业的发展趋势看,企业家需要找的是对口从业者和具有专业研究能力的人才,来辅助企业进行自我突破和多元化发展。

我们前面已经说过,同质化的管理经验已经不能挽救陷入激烈竞争的企业,只有对口研究并且是综合性跨界研究专才,才能为企业找到突围困境的战略,让企业有效创新、有效提升品牌竞争力、有效提升利润率等等。一个好的对口研究专才,能够找到企业最短板最烂的地方,也知道最先从哪里下手改造:他知道轻重缓急,知道发展治理步骤。当然,也知道通过如何治理,让企业的经济效益迅速飙升。

实际上,几乎所有的西方经济学教授都说过,企业家不是商学院能够培养得出来的。那么如何培养出企业家呢,一是来自大量失败的实践,二是来自大量的对口跟踪研究。除此之外,别无他法。

本文作者:@文化生产力;转载自: 中人网


(关注更多人人都是产品经理观点,参与微信互动(微信搜索“人人都是产品经理”或“woshipm”)

Viewing all 15843 articles
Browse latest View live


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