精华内容
下载资源
问答
  • 两款硬件代理服务器产品之比较

    千次阅读 2014-05-19 19:14:29
    两款硬件代理服务器产品之比较  (NETAPP \ BLUECOAT)  Network Appliance 产品为您提供易于管理的、业界领先的、最灵活、最可靠、可扩展性最好的存储解决方案,并且其内建冗余为您提供最大的数据可用性和数据...

     

     

    两款硬件代理服务器产品之比较
                                            (NETAPP \ BLUECOAT) 
    Network Appliance 产品为您提供易于管理的、业界领先的、最灵活、最可靠、可扩展性最好的存储解决方案,并且其内建冗余为您提供最大的数据可用性和数据保护。用于整个网络的可扩展内容分发工具。(NETAPP1200 可以安装3块硬盘,实现数据的RAID 安全保护)。
    企业及服务提供商都面临一对互相矛盾的目标:在网络上运行更多应用,同时降低设备成本和运行费用。这个难题通常还伴随着带宽费用降低问题、应用兼容性问题、服务器瓶颈问题、生产率低的问题以及最终用户不满意问题
    Network Appliance 能够帮助您解决这些难题,使用可靠、灵活、经济的解决方案来简化数据管理和内容分发,协调互相竞争的目标。NetCache 是我们的可扩展内容的分发设备,已经证明它能够解决当今网络中最复杂的内容分发问题。
    利用 NetCache 设备能够实现对企业应用(例如ERP 和CRM 系统) 远程访问、在线培训、执行视频广播、大型视频点播服务等下一代网络服务。这些设备能够缩短网络等待时间,从而改善电子商务客户、企业内部网用户以及外部供应商和合作伙伴的生产率及总体Web 感受。
    一、设备外观比较
    NetApp 2300外观

     

    BlueCoat内部结构

    二、NETAPP主要特点

    最低总拥有成本
    通过同时分发流、 HTTP、NNTP
    新闻组、FTP、JavaTM applet 等,
    在同一台设备上运行多个应用程序。
    无限扩展
    可以轻松地把高速缓存存储从 36GB 扩展到数百GB。
    全面的流媒体支持
    支持RealNetworks®、
    RealSystemTM、Microsoft®
    Windows MediaTM 及Apple®
    QuickTimeTM 的视频点播及实况分流。
    最高的性能
    具有业界最佳的流媒体性能。
    易于管理
    NetApp “appliance”的体系结构能够保证部署简单、可靠性及易于管理性。
    为丰富的内容分发提供最高的可扩展性
    NetCache 设备的丰富功能、存储容量及增值服务使这些解决方案能够轻松的扩展已有网络,不需要速度很慢、代价高昂的带宽扩展和基础设施扩展,也不需要增加人员。
    灵活性和合并
    NetCache 解决方案把对HTTP、FTP、NNTP 等所有主要流媒体格式的支持合并到
    台内容设备上,因而提高了灵活性。另外,NetCache 支持ICAP 等开放式标准
    以确保与最新应用的集成。
    管理简单
    我们的设备体系结构使得使用非常方便,从而降低了管理费用和所有者总成本。这种设备体系结构是基于 NetApp® Data ONTAPTM 和 WAFL® 软件的,可以提供 99.99+%
    的正常运行时间。 NetApp 的多系统管理应用和日志报表工具使得能够集中进行设备管理、分析和报表。
    安全
    NetCache 设备有一个安全的体系结构和许多先进的安全功能,它可以保护机密信息和网络运行不受网络内部或外部入侵者的侵袭。
    三、 产品特性比较(NETAPP /BLUECOAT)
    1. 策略生成
    NetCache安全策略可以通过手工编辑策略文件,操作比较简单
    BLUECOAT可以图示化的管理策略。
    2. 互联网应用级的控制
     NetApp对流媒体的控制方面更加的完善。支持 RealNetworks®、 RealSystemTM、 Microsoft®Windows MediaTM 及 Apple® QuickTimeTM 的视频点播及实况分流。
    3.Proxy 完整性
    Blue Coat提供了SOCKS4、SOCK5的代理支持
    但现在很多软件都可以通过HTTP 代理来实现SOCKS的功能
    4. 在数据安全性方面
    NetCache配置三块72G硬盘,来存储数据。通过RAID技术满足用户对数据安全的需求。
    BLUECOAT 面向对象的存储,非文件系统,磁盘I/O 专用系统(CACHE数据安全无法保障)。
    5. 在用户认证方面
    除了通过使用内部数据库、LDAP、NTLM 和 RADIUS 平台,支持用户和组验证Blue Coat 还支持Certificate authentication(证书认证)
    6. 在策略制定方面
    Blue Coat 除了基于用户、用户组、时间、地点、网络地址、浏览器类型等属性实施细粒度的Web访问策略,还可以实现内容转换 – 限制、剥除、或替换内容报头信息,拦截广告的设置,使用可视化编辑菜单)。
    NetCache基于用户、用户组、时间、地点、网络地址、浏览器类型等实现访问策略的制定(使用简单的脚本语句编辑)
    三、Proxy特性比较列表(NETAPP 1200/BLUECOAT 800)
    下表是详细的功能对比:

    产品属性
    Network Appliance NetCache
    Bluecoat Systems ProxySG
     
     
     
    Microsoft Windows 2000 服务器
     
     
    基于 Linux OS 的服务器
     
     
    基于 Solaris OS 的服务器
     
     
    基于其它 UNIX OS 的服务器
     
     
    缓存专用设备
    l
     
    Proxy 专用设备
    l
    l
    Proxy 服务
     
     
    HTTP
    l
    l
    HTTPS
    l
    l
    FTP
    l
    l
    Tunnel service
    l
    l
    Windows Media
    l
    l
    RTSP (Real and QuickTime)
    l
    l
    DNS
    l
    l
    NNTP
    l
     
    Gopher
    l
     
    Telnet
     
     
    QuickTimeTM 的视频点播及实况分流。
    l
     
    用户认证
     
     
    NTLM
    l
    l
    Active Directory
    l
    l
    Certificate authentication
     
    l
    LDAP
    l
    l
    Radius
    l
    l
    本地用户认证
                      l
    l
    多认证域支持
    l
    l
    多认证域搜索序列
    l
    l
    透明认证
    l
    l
    无需 Client 端特殊软件
    l
    l
    策略中源的定义
     
     
    IP 和子网
    l
    l
    用户和用户组
    l
    l
    Proxy 端口号
    l
    l
    协议
    l
    l
    策略中的目的定义
     
     
    IP/ 子网
    l
    l
    端口号
    l
    l
    URL
    l
    l
    内容过滤类型
    l
    l
    策略的 Services 定义
     
     
    Protocol 类型
    l
    l
    Protocol 方法
     
    l
    IM 关键字搜索
     
    (中文还不支持)
    客户化定义 Services
     
    l
     
     
    l
    策略的时间定义
     
     
    根据时间启动策略
    l
    l
     
     
     
    策略操作
     
     
    Allow
    l
    l
    Authenticate
    l
    l
    Deny
    l
    l
    Bypass Cache
    l
    l
    返回客户化提示及出错信息
                       l
    l
    重写 Host
    l
    l
    屏蔽 Headers 信息
    l
    l
    控制请求的 Header 信息
    l
    l
    控制应答的 Header 信息
    l
    l
    剔除动态内容
    l
    l
    ICAP 提示页面
                       l
    l
    屏蔽弹出式广告
    通过第三方软件 Webwasher实现
    l
     
     
     
    事件跟踪和提示
     
     
    E-mail
    l
    l
    SNMP
    l
    l
    Event Log
    l
    l
    Tracing
     
    l
    组合跟踪和提示
     
     
    l
    数据图形化显示(不同)
    l
     
    内容过滤
     
     
    SmartFilter on Box
    l
    l
    SmartFilter 反向域名搜索的支持
     
    l
    SurfControl On-box
     
    l
    Webwasher On-Box
    l
     
    WebSense On-box (w/WS Reporter)
     
    l
    Websense Off-Box
     
    l
    本地定义类型列表
     
    l
    定制的策略引擎
    l
    l
    仅使用内容过滤数据库
    l
    l
    访问日志
     
     
    多访问日志(由策略控制)
     
    l
    HTTP/HTTPS
    l
    l
    FTP
    l
    l
    Streaming
    l
    l
    可定制的访问日志域
    l
    l
    安全的日志上传
    l
    l
    实时日志
                      l
    l
    日志后处理
    l
    l
    外置的 Services
     
     
    Websense Off-Box
                      l
    l
    ICAP
    l
    l
    群集
    l
    l
    转发
     
     
    层次化的缓存和安全控制
    l
    l
    SSL
     
     
    Web 服务器的 SSL 终结
    l
    l
    Web 服务器的 SSL 发起
    l
    l
    HTTP HTTPS 协议转换
    l
    l
    证书导入
    l
    l
    SSL 数据缓存
    l
    l
    CDN/ 内容管理
     
     
    WMT 流媒体支持
    l
    l
    RTSP 流媒体支持
    l
    l
    流媒体的分播
    l
    l
    流媒体缓存
    l
    l
    内容推送
    l
    l
    内容定存
    l
    l
    请求路由
    l
    Blue Coat Director
    网络
     
     
    群集
    l
    WCCP 或 Layer 7
    容错 (Active/Passive)
    l
    l
    WCCP
    l
    l
    管理服务
     
     
    HTTP HTTPS 管理界面
    l
    l
    Telnet
    l
    l
    SSHv2
    l
    l
    多台设备的集中配置
                      l
    l
    图示化策略编辑
     
    l
    维护和监控
     
     
    SNMP
    l
    l
    Event Logs
    l
    l
    实时统计
    l
    l
    数据安全
     
     
    支持 RAID
    l
     
    硬盘扩容
    l
     

     

    本文出自 “李晨光原创技术博客” 博客,谢绝转载!

    展开全文
  • 动态代理

    千次阅读 2018-08-30 19:06:38
    1.代理模式深入学习(一)——动态代理的实现及解析 原文链接:https://blog.csdn.net/wangyy130/article/details/48828595 一、代理模式 分为静态和动态代理。静态代理,我们通常都很熟悉。有一个写好的代理类...

    1.代理模式深入学习(一)——动态代理的实现及解析

    原文链接:https://blog.csdn.net/wangyy130/article/details/48828595

    一、代理模式

        分为静态和动态代理。静态代理,我们通常都很熟悉。有一个写好的代理类,实现与要代理的类的一个共同的接口,目的是为了约束也为了安全。
        具体不再多说。
    
        这里主要想说的是关于动态代理。我们知道静态代理若想代理多个类,实现扩展功能,那么它必须具有多个代理类分别取代理不同的实现类。
        这样做的后果是造成太多的代码冗余。那么我们会思考如果做,才能既满足需求,又没有太多的冗余代码呢?——————动态代理。
        它通过在运行时创建代理类,来适应变化。主要用到的是Reflec中的Proxy和InvocationHandler类。
        先通过一段代码来理解一下动态代理模式的实现过程:
    

     

    public class LogHandler implements InvocationHandler {
    
        private Object targetObject; //将要代理的对象保存为成员变量
        //将被代理的对象传进来,通过这个方法生成代理对象
        public Object newProxyInstance(Object targetObject) {
            this.targetObject = targetObject;
            return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
                                   targetObject.getClass().getInterfaces(), this);
        }
        //代理模式内部要毁掉的方法
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            System.out.println("start-->>" + method.getName());//方法执行前的操作
            for (int i=0; i<args.length; i++) {
                System.out.println(args[i]);
            }
            Object ret = null;
            try {
                //调用目标方法,如果目标方法有返回值,返回ret,如果没有抛出异常
                ret = method.invoke(targetObject, args);
                System.out.println("success-->>" + method.getName()); //方法执行后操作
            }catch(Exception e) {
                e.printStackTrace();
                System.out.println("error-->>" + method.getName());//出现异常时的操作
                throw e;
            }
            return ret;
        }
    
    }

     

    //客户端调用
    public static void main(String[] args) {
            LogHandler logHandler = new LogHandler();
            UserManager userManager = (UserManager)logHandler.newProxyInstance(new UserManagerImpl());
            //userManager.addUser("0001", "张三");
            String name = userManager.findUser("0001");
            System.out.println("Client.main() --- " + name);
        }

    代码解析

    首先我们要了解一下类的加载机制,在每创建一个Java类时,都会生产一个.class文件,在内存中对应也会生成一个class对象,来表示该类的类型信
    息,我们可以用.class来获取这个类的所有信息,也可以通过getClass()方法来读取这个类的所有信息,比如
    getClass().getInterfaces()获取类的接口信息等。在Java类加载时,要通过一个类加载器classloader来将生成的Java类加载到JVM
    中才能执行。
    
        理解了类的加载机制后,我们再看代码中的newProxyInstance方法,在这个方法中,我们将被代理对象传进来后,通过
        Proxy.newProxyInstance这个方法来动态的创建一个被代理类的一个代理类的实例。
    

    在Proxy.newProxyInstance方法中,共有三个参数:

        1、targetObject.getClass().getClassLoader()目标对象通过getClass方法获取类的所有信息后,调用getClassLoader()
        方法来获取类加载器。获取类加载器后,可以通过这个类型的加载器,在程序运行时,将生成的代理类加载到JVM即Java虚拟机中,以便运行时需要!
        2、targetObject.getClass().getInterfaces()获取被代理类的所有接口信息,以便于生成的代理类可以具有代理类接口中的所有方法。
        3、this:我们使用动态代理是为了更好的扩展,比如在方法之前做什么,之后做什么等操作。这个时候这些公共的操作可以统一交给代理类去做。
        这个时候需要调用实现了InvocationHandler 类的一个回调方法。由于自身变实现了这个方法,所以将this传递过去。
    

    invoke方法的参数

        1、Object proxy生成的代理对象,在这里不是特别的理解这个对象,但是个人认为是已经在内存中生成的proxy对象。
        2、Method method:被代理的对象中被代理的方法的一个抽象。
        3、Object[] args:被代理方法中的参数。这里因为参数个数不定,所以用一个对象数组来表示。
    

    执行过程

        在执行过程中,由于被代理的方法可能有返回值,可能直接就是void来表示,那么为了适应于所有方法,所以定义一个返回值,将返回的值
        通过ret来接收,当然会抛出异常。ret = method.invoke(targetObject, args);就是调用被代理对象的方法,来执行最原始的方法。在执行完后,
        进行额外的处理操作。
    
        以上就是在学习代理模式中自己的一些理解。代理模式是一个很重要的模式,也是一个很实用的模式,利用它可以实现事务的封装,不用我们每次
        需要事务操作时,都要进行手动去写,直接调用代理就好了,具体见下篇博客。

    2.深入剖析ThreadLocal

    原文链接:https://www.cnblogs.com/dolphin0520/p/3920407.html

    探讨下ThreadLocal的使用方法和实现原理。首先,本文先谈一下对ThreadLocal的理解,然后根据ThreadLocal类的源码分析了其实现原理和使用需要注意的地方,最后给出了两个应用场景。

      以下是本文目录大纲:

      一.对ThreadLocal的理解

      二.深入解析ThreadLocal类

      三.ThreadLocal的应用场景

      若有不正之处请多多谅解,并欢迎批评指正。

      请尊重作者劳动成果,转载请标明原文链接:

       http://www.cnblogs.com/dolphin0520/p/3920407.html

    一.对ThreadLocal的理解

      ThreadLocal,很多地方叫做线程本地变量,也有些地方叫做线程本地存储,其实意思差不多。可能很多朋友都知道ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。

      这句话从字面上看起来很容易理解,但是真正理解并不是那么容易。

      我们还是先来看一个例子:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    class ConnectionManager {

         

        private static Connection connect = null;

         

        public static Connection openConnection() {

            if(connect == null){

                connect = DriverManager.getConnection();

            }

            return connect;

        }

         

        public static void closeConnection() {

            if(connect!=null)

                connect.close();

        }

    }

       假设有这样一个数据库链接管理类,这段代码在单线程中使用是没有任何问题的,但是如果在多线程中使用呢?很显然,在多线程中使用会存在线程安全问题:第一,这里面的2个方法都没有进行同步,很可能在openConnection方法中会多次创建connect;第二,由于connect是共享变量,那么必然在调用connect的地方需要使用到同步来保障线程安全,因为很可能一个线程在使用connect进行数据库操作,而另外一个线程调用closeConnection关闭链接。

      所以出于线程安全的考虑,必须将这段代码的两个方法进行同步处理,并且在调用connect的地方需要进行同步处理。

      这样将会大大影响程序执行效率,因为一个线程在使用connect进行数据库操作的时候,其他线程只有等待。

      那么大家来仔细分析一下这个问题,这地方到底需不需要将connect变量进行共享?事实上,是不需要的。假如每个线程中都有一个connect变量,各个线程之间对connect变量的访问实际上是没有依赖关系的,即一个线程不需要关心其他线程是否对这个connect进行了修改的。

      到这里,可能会有朋友想到,既然不需要在线程之间共享这个变量,可以直接这样处理,在每个需要使用数据库连接的方法中具体使用时才创建数据库链接,然后在方法调用完毕再释放这个连接。比如下面这样:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    class ConnectionManager {

         

        private  Connection connect = null;

         

        public Connection openConnection() {

            if(connect == null){

                connect = DriverManager.getConnection();

            }

            return connect;

        }

         

        public void closeConnection() {

            if(connect!=null)

                connect.close();

        }

    }

     

     

    class Dao{

        public void insert() {

            ConnectionManager connectionManager = new ConnectionManager();

            Connection connection = connectionManager.openConnection();

             

            //使用connection进行操作

             

            connectionManager.closeConnection();

        }

    }

       这样处理确实也没有任何问题,由于每次都是在方法内部创建的连接,那么线程之间自然不存在线程安全问题。但是这样会有一个致命的影响:导致服务器压力非常大,并且严重影响程序执行性能。由于在方法中需要频繁地开启和关闭数据库连接,这样不尽严重影响程序执行效率,还可能导致服务器压力巨大。

      那么这种情况下使用ThreadLocal是再适合不过的了,因为ThreadLocal在每个线程中对该变量会创建一个副本,即每个线程内部都会有一个该变量,且在线程内部任何地方都可以使用,线程之间互不影响,这样一来就不存在线程安全问题,也不会严重影响程序执行性能。

      但是要注意,虽然ThreadLocal能够解决上面说的问题,但是由于在每个线程中都创建了副本,所以要考虑它对资源的消耗,比如内存的占用会比不使用ThreadLocal要大。

    二.深入解析ThreadLocal类

      在上面谈到了对ThreadLocal的一些理解,那我们下面来看一下具体ThreadLocal是如何实现的。

      先了解一下ThreadLocal类提供的几个方法:

    1

    2

    3

    4

    public T get() { }

    public void set(T value) { }

    public void remove() { }

    protected T initialValue() { }

       get()方法是用来获取ThreadLocal在当前线程中保存的变量副本,set()用来设置当前线程中变量的副本,remove()用来移除当前线程中变量的副本,initialValue()是一个protected方法,一般是用来在使用时进行重写的,它是一个延迟加载方法,下面会详细说明。

      首先我们来看一下ThreadLocal类是如何为每个线程创建一个变量的副本的。

      先看下get方法的实现:

      

       第一句是取得当前线程,然后通过getMap(t)方法获取到一个map,map的类型为ThreadLocalMap。然后接着下面获取到<key,value>键值对,注意这里获取键值对传进去的是  this,而不是当前线程t。

      如果获取成功,则返回value值。

      如果map为空,则调用setInitialValue方法返回value。

      我们上面的每一句来仔细分析:

      首先看一下getMap方法中做了什么:

      

      可能大家没有想到的是,在getMap中,是调用当期线程t,返回当前线程t中的一个成员变量threadLocals。

      那么我们继续取Thread类中取看一下成员变量threadLocals是什么:

      

      实际上就是一个ThreadLocalMap,这个类型是ThreadLocal类的一个内部类,我们继续取看ThreadLocalMap的实现:

      

      可以看到ThreadLocalMap的Entry继承了WeakReference,并且使用ThreadLocal作为键值。

      然后再继续看setInitialValue方法的具体实现:

      很容易了解,就是如果map不为空,就设置键值对,为空,再创建Map,看一下createMap的实现:

      

      至此,可能大部分朋友已经明白了ThreadLocal是如何为每个线程创建变量的副本的:

      首先,在每个线程Thread内部有一个ThreadLocal.ThreadLocalMap类型的成员变量threadLocals,这个threadLocals就是用来存储实际的变量副本的,键值为当前ThreadLocal变量,value为变量副本(即T类型的变量)。

      初始时,在Thread里面,threadLocals为空,当通过ThreadLocal变量调用get()方法或者set()方法,就会对Thread类中的threadLocals进行初始化,并且以当前ThreadLocal变量为键值,以ThreadLocal要保存的副本变量为value,存到threadLocals。

      然后在当前线程里面,如果要使用副本变量,就可以通过get方法在threadLocals里面查找。

      下面通过一个例子来证明通过ThreadLocal能达到在每个线程中创建变量副本的效果:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    public class Test {

        ThreadLocal<Long> longLocal = new ThreadLocal<Long>();

        ThreadLocal<String> stringLocal = new ThreadLocal<String>();

     

         

        public void set() {

            longLocal.set(Thread.currentThread().getId());

            stringLocal.set(Thread.currentThread().getName());

        }

         

        public long getLong() {

            return longLocal.get();

        }

         

        public String getString() {

            return stringLocal.get();

        }

         

        public static void main(String[] args) throws InterruptedException {

            final Test test = new Test();

             

             

            test.set();

            System.out.println(test.getLong());

            System.out.println(test.getString());

         

             

            Thread thread1 = new Thread(){

                public void run() {

                    test.set();

                    System.out.println(test.getLong());

                    System.out.println(test.getString());

                };

            };

            thread1.start();

            thread1.join();

             

            System.out.println(test.getLong());

            System.out.println(test.getString());

        }

    }

       这段代码的输出结果为:

      

      从这段代码的输出结果可以看出,在main线程中和thread1线程中,longLocal保存的副本值和stringLocal保存的副本值都不一样。最后一次在main线程再次打印副本值是为了证明在main线程中和thread1线程中的副本值确实是不同的。

      总结一下:

      1)实际的通过ThreadLocal创建的副本是存储在每个线程自己的threadLocals中的;

      2)为何threadLocals的类型ThreadLocalMap的键值为ThreadLocal对象,因为每个线程中可有多个threadLocal变量,就像上面代码中的longLocal和stringLocal;

      3)在进行get之前,必须先set,否则会报空指针异常;

          如果想在get之前不需要调用set就能正常访问的话,必须重写initialValue()方法。

        因为在上面的代码分析过程中,我们发现如果没有先set的话,即在map中查找不到对应的存储,则会通过调用setInitialValue方法返回i,而在setInitialValue方法中,有一个语句是T value = initialValue(), 而默认情况下,initialValue方法返回的是null。

      

      看下面这个例子:

      

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    public class Test {

        ThreadLocal<Long> longLocal = new ThreadLocal<Long>();

        ThreadLocal<String> stringLocal = new ThreadLocal<String>();

     

        public void set() {

            longLocal.set(Thread.currentThread().getId());

            stringLocal.set(Thread.currentThread().getName());

        }

         

        public long getLong() {

            return longLocal.get();

        }

         

        public String getString() {

            return stringLocal.get();

        }

         

        public static void main(String[] args) throws InterruptedException {

            final Test test = new Test();

             

            System.out.println(test.getLong());

            System.out.println(test.getString());

     

            Thread thread1 = new Thread(){

                public void run() {

                    test.set();

                    System.out.println(test.getLong());

                    System.out.println(test.getString());

                };

            };

            thread1.start();

            thread1.join();

             

            System.out.println(test.getLong());

            System.out.println(test.getString());

        }

    }

       在main线程中,没有先set,直接get的话,运行时会报空指针异常。

      但是如果改成下面这段代码,即重写了initialValue方法:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    public class Test {

        ThreadLocal<Long> longLocal = new ThreadLocal<Long>(){

            protected Long initialValue() {

                return Thread.currentThread().getId();

            };

        };

        ThreadLocal<String> stringLocal = new ThreadLocal<String>(){;

            protected String initialValue() {

                return Thread.currentThread().getName();

            };

        };

     

         

        public void set() {

            longLocal.set(Thread.currentThread().getId());

            stringLocal.set(Thread.currentThread().getName());

        }

         

        public long getLong() {

            return longLocal.get();

        }

         

        public String getString() {

            return stringLocal.get();

        }

         

        public static void main(String[] args) throws InterruptedException {

            final Test test = new Test();

     

            test.set();

            System.out.println(test.getLong());

            System.out.println(test.getString());

         

             

            Thread thread1 = new Thread(){

                public void run() {

                    test.set();

                    System.out.println(test.getLong());

                    System.out.println(test.getString());

                };

            };

            thread1.start();

            thread1.join();

             

            System.out.println(test.getLong());

            System.out.println(test.getString());

        }

    }

       就可以直接不用先set而直接调用get了。

    三.ThreadLocal的应用场景

      最常见的ThreadLocal使用场景为 用来解决 数据库连接、Session管理等。

      如:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    private static ThreadLocal<Connection> connectionHolder

    new ThreadLocal<Connection>() {

    public Connection initialValue() {

        return DriverManager.getConnection(DB_URL);

    }

    };

     

    public static Connection getConnection() {

    return connectionHolder.get();

    }

       下面这段代码摘自:

      http://www.iteye.com/topic/103804

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    private static final ThreadLocal threadSession = new ThreadLocal();

     

    public static Session getSession() throws InfrastructureException {

        Session s = (Session) threadSession.get();

        try {

            if (s == null) {

                s = getSessionFactory().openSession();

                threadSession.set(s);

            }

        catch (HibernateException ex) {

            throw new InfrastructureException(ex);

        }

        return s;

    }

    3.为避免多线程Connection混乱使用ThreadLocal来封装事务

    原文链接:https://blog.csdn.net/wangyy130/article/details/48952371

    上一篇博客总结了动态代理的使用及代码的含义。接下来,继续探究动态代理的实地应用——利用动态代理来封装事务。
        首先,要先来回忆一下最原始的封装好的事务的代码,这里在连接数据库时用到了TheadLocal这个类,通过它可以来保证在执行业务逻辑过程中来
        保证每一次使用的connection的连接对象都执行的是同一个线程内的connection。
    

    事务的封装

    /**
     * 采用ThreadLocal封装Connection
     * @author yanyan
     *
     */
    public class ConnectionManager {
        //声明一个Connection类型的ThreadLocal
        private static ThreadLocal<Connection> connectionHolder=new ThreadLocal<Connection>();
    
        public static Connection getConnection(){
        //通过TheadLocal的get方法来获取当前线程连接对象的实例
            Connection conn=connectionHolder.get();
            if(conn==null){
                try{
                //获取数据库驱动
                    JdbcConfig jdbcConfig=XmlConfigReader.getInstance().getJdbcConfig();
                    Class.forName(jdbcConfig.getDriverName());
                    conn=DriverManager.getConnection(jdbcConfig.getUrl(),jdbcConfig.getUserName(),jdbcConfig.getPassword());
                //设置数据库连接对象
                    connectionHolder.set(conn);
                }catch (Exception e) {
                    throw new ApplicationException("系统错误,请联系管理员!");
                }
            }
    
            return conn;
        }
    
        //关闭数据库连接
        public static void closeConnection(){
            Connection conn=connectionHolder.get();
    
            if(conn!=null){
                try{
                    conn.close();
                    //从集合中清除
                    connectionHolder.remove();
                }catch(SQLException e){
                    e.printStackTrace();
                }
            }
        }
    
        /**
         * 手动提交事务
         * @param conn
         */
        public static void beginTransaction(Connection conn){
            try{
                if(conn !=null){
                    if(conn.getAutoCommit()){
                        conn.setAutoCommit(false);
                    }
                }
            }catch(SQLException e){}
        }
    
        /**
         * 
         * 提交事务
         * @param conn
         */
        public static void commitTransaction(Connection conn){
            try{
                if(conn !=null){
                    if(!conn.getAutoCommit()){
                        conn.commit();
                    }
                }
            }catch(SQLException e){}
        }
    
        /**
         * 回滚事务
         * @param conn
         */
        public static void rollbackTransaction(Connection conn){
            try{
                if(conn!=null){
                    if(!conn.getAutoCommit()){
                        conn.rollback();
                    }
                }
            }catch(SQLException e){}
        }
    
        /**
         * 重置connection状态
         * @param conn
         */
        public static void resetConnection(Connection conn){
            try{
                if(conn!=null){
                    if(conn.getAutoCommit()){
                        conn.setAutoCommit(false);
                    }else{
                        conn.setAutoCommit(true);
                    }
                }
            }catch(SQLException e){}
        }
    
    
        //关闭preparedStatement
        public static void close(Statement pstmt){
            if(pstmt !=null){
                try {
                    pstmt.close();
                } catch (SQLException e) {
    
                    e.printStackTrace();
                }
            }
        }
        //关闭ResultSet
        public static void close(ResultSet rs){
            if(rs !=null){
                try {
                    rs.close();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    
    
    
        通过利用ThreadLocal这个类来封装Connection,这样在业务逻辑层获取connection的时候,就会避免了很多麻烦。在遇到多重业务逻辑调用
        多种方法时,调用到的connection会在当前线程中查找获取到connection这个对象进行数据库操作。
        接下来,就该介绍如何利用动态代理来封装事务了,请见下篇博客!

    4.代理模式深入学习(二)——实现动态代理对事务的封装

    原文链接:https://blog.csdn.net/wangyy130/article/details/49228495

    从动态代理的实现衍生原理到threadLocal来封装事务,到最后真正的利用动态代理来封装事务。缺少每一
        步都似乎显得有些冒进了!现在剩下的就只是把先前封装好的事务加进到写好的动态代理类中就好了!
    

    动态代理与事务结合

    package com.bjpowernode.drp.util;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.sql.Connection;
    
    /**
     * 事务的封装,利用动态代理封装事务
     * @author yanyan
     *
     */
    public class TransactionHandler implements InvocationHandler {
        private Object targetObject;
    
        /**
         * 将要代理的类传递给该类,同时在该类中保存这个类的对象
         * @param targetObject
         * @return
         */
        public Object newProxyInstance(Object targetObject){
            this.targetObject=targetObject;
            /**
             * 1/targetObject:要代理的类的对象
             * 2/代理的类所实现的接口,便于生成的代理类去实现这个接口
             * 3/每个生成的代理类要回调一个实现了InvocationHandler的内部函数,这个函数放在这个类里面就是invoke函数,为了适应多种类,要写活
             */
            return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this);
        }
    
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            Connection conn=null;
            Object ret=null; //定义代理的方法返回对象
            try{
                //从ThreadLocal中取得connection
                conn=ConnectionManager.getConnection();//打开连接
                if(method.getName().startsWith("add") || method.getName().startsWith("del") || method.getName().startsWith("modify")){
                    //手动控制事务提交
                    ConnectionManager.beginTransaction(conn);
                }
                //调用目标对象的业务逻辑方法
                ret=method.invoke(targetObject, args);
                if(!conn.getAutoCommit()){
                    //提交事务
                    ConnectionManager.commitTransaction(conn);
                }
    
            }catch(ApplicationException e){
                //回滚事务
                ConnectionManager.rollbackTransaction(conn);
                throw e;
            }catch(Exception e){
                e.printStackTrace();
                if(e instanceof InvocationTargetException){
                    InvocationTargetException ete=(InvocationTargetException)e;
                    throw ete.getTargetException();
                }
                //回滚事务
                ConnectionManager.rollbackTransaction(conn);
                throw new ApplicationException("操作失败!");
            }finally{
                ConnectionManager.closeConnection();
            }
    
            return ret;
        }
    }
    
    

    将动态代理封装的事务嵌进原始调用对象中

    package com.bjpowernode.drp.util;
    
    import java.util.HashMap;
    import java.util.Map;
    
    import org.dom4j.Document;
    import org.dom4j.DocumentException;
    import org.dom4j.Element;
    import org.dom4j.io.SAXReader;
    
    import com.bjpowernode.drp.flowcard.manager.FlowCardManager;
    
    /**
     * 抽象工厂,主要创建两个系列的产品
     * 1、manager系列
     * 2、dao系列
     * @author yanyan
     *
     */
    public class BeanFactory {
    
        private final String beansConfigFile="beans-config.xml";
        private Document doc;
        private static BeanFactory instance=new BeanFactory();
    
        private Map serviceMap=new HashMap();
    
        private Map daoMap=new HashMap();
        private BeanFactory(){
            //装载配置文件
            try {
                doc=new SAXReader().read(Thread.currentThread().getContextClassLoader().getResourceAsStream(beansConfigFile));
            } catch (DocumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                throw new RuntimeException();
            }
    
        }
    
        public static BeanFactory getInstance(){
    
            return instance;
        }
    
        /**
         * 根据产品编号取得service系列产品
         * @param beanId
         * @return
         */
        public synchronized Object getServiceObject(Class c){
            //首先判断是否存在该对象
                    if(serviceMap.containsKey(c.getName())){
                        return serviceMap.get(c.getName());
                    }
                    //如果不存在,则创建一个
                    //  //代表以bean路径结尾的所有元素,用“//” 表示所有路径以"//"后指定的子路径结尾的元素 
                    Element beanElt=(Element) doc.selectSingleNode("//service[@id=\""+c.getName()+"\"]");
                    /*String className=beanElt.getTextTrim();*/
                    String className=beanElt.attributeValue("class");
                    Object service=null;
                    try {
    
                        service=Class.forName(className).newInstance();
                        TransactionHandler transactionHandler=new TransactionHandler();
                        service=transactionHandler.newProxyInstance(service);
                        //将创建好的对象放到map中
                        serviceMap.put(c.getName(), service);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    } 
                    return service;
        }
    
        /**
         * 根据产品编号取得dao系列产品
         * @param beanId
         * @return
         */
        public synchronized Object getDaoObject(Class c){
            //首先判断是否存在该对象
                    if(daoMap.containsKey(c.getName())){
                        return daoMap.get(c.getName());
                    }
                    //如果不存在,则创建一个
                    //  //代表以bean路径结尾的所有元素,用“//” 表示所有路径以"//"后指定的子路径结尾的元素 
                    Element beanElt=(Element) doc.selectSingleNode("//dao[@id=\""+c.getName()+"\"]");
                    /*String className=beanElt.getTextTrim();*/
                    String className=beanElt.attributeValue("class");
                    Object dao=null;
                    try {
                        dao=Class.forName(className).newInstance();
                        TransactionHandler transactionHandler=new TransactionHandler();
                        dao=transactionHandler.newProxyInstance(dao);
                        //将创建好的对象放到map中
                        daoMap.put(c.getName(), dao);
                    } catch (Exception e) {
                        throw new RuntimeException("创建失败");
                    } 
                    return dao;
        }
    }
    

    调用

    private FlowCardDao flowCardDao;
    
    //这里通过构造函数调用的beanFactory实现代码中已经启用了动态代理封装的事务
            this.flowCardDao=(FlowCardDao)BeanFactory.getInstance().getDaoObject(FlowCardDao.class);
        }
    
        public void addFlowCard(FlowCard flowCard) throws ApplicationException {
            //Connection conn=null;
            try{
                //conn=ConnectionManager.getConnection();
                //开始事务
                //ConnectionManager.beginTransaction(conn);
                //生成流向单单号
                String flowCardVouNo=flowCardDao.generateVouNo();
                //添加流向单主信息
                flowCardDao.addFlowCardMaster(flowCardVouNo, flowCard);
                //添加明细信息
                flowCardDao.addFlowCardDetail(flowCardVouNo, flowCard.getFlowCardDetailList());
                //提交事务
                //ConnectionManager.commitTransaction(conn);
            }catch(DaoException e){
                //回滚事务
                //ConnectionManager.rollbackTransaction(conn);
                throw new ApplicationException(e);
    
            }/*finally{
                ConnectionManager.closeConnection();
            }
            */
    
    
        }
        从注释的代码中可以看到,我们利用动态代理封装的事务可以大大减少代码的重复。

     

    展开全文
  • 权益证明生态系统

    万次阅读 2019-05-14 09:22:15
    权益证明如何运作 -图片来自 Christine Roy,取自 Unsplash 网站- 权益证明 (PoS) 对许多人来说仍然是一个陌生的概念,即使在区块链世界也是如此。然而,我们看到大多数下一代协议都采用了 PoS,并且围绕这种...

    权益证明如何运作

    -图片来自 Christine Roy,取自 Unsplash 网站-

    权益证明 (PoS) 对许多人来说仍然是一个陌生的概念,即使在区块链世界也是如此。然而,我们看到大多数下一代协议都采用了 PoS,并且围绕这种工作量证明 (PoW) 的替代方案形成大型生态系统。类似于 PoW 会创造出以挖矿 (ASIC 生产者,矿场和矿池等等) 为中心的数十亿美元的产业,新型网络维护者也有机会出头。

    为了推断市场的走向,我们需要回过头来理解权益证明:主要参与者是谁,他们的激励约束以及不同的 PoS 实现之间的差异。这个系列还没全部写完,本文只是其中第一篇;我们会分析 PoS 生态系统,公开我们过去几个月在 Chorus One 构建自己的权益模型时的所思所想。

    101:权益证明如何运作?

    本系列的第一部分将提供 PoS 的基本介绍以及验证和委托的概念。有些读者可能知道,我已经写过《不同类型的权益证明》这篇文章。而这个“权益证明生态系统”系列将专注于纯粹的 PoS 实现,也就是那些共识过程将直接受权益影响的系统。但是在实际中这样的系统是如何运作的呢?

    验证

    如果我们从抽象的角度看待 PoS ,那么这个概念就非常明确了;该术语指的是一个系统,其中权益的价值是将哪些区块添加到区块链中的主要决定因素。权益证明网络中的参与者会把他们的代币投给他们认为有效的区块,如果他们跟网络中的大部分参与者达成一致,就可以得到奖励;而试图作弊则要冒着失去权益(保证金)的风险,例如同时给两个不同的区块投票。

    在 PoS 中,金钱就是力量;PoS 要求参与者获取并利用网络代币作为安全保证金,使其与网络利益达成一致,而不是要求参与者通过消耗电能 (PoW) 来加固网络安全。

    权益在 PoS 区块链中指的是为了参与维护区块链账本而在智能合约中存入的代币。一旦这些代币 (权益) 在网络中被注册,权益方就需要运行节点、参与共识过程;节点之间会通过接收、签名、和发送(关于区块的)消息来达成共识。这种权益和节点基础设施的组合通常称为验证者。通过这种方式注册的权益数量决定了相关验证者在共识过程中的影响力,以及验证者因工作所获得的奖励。下图说明了这个通常被称为验证的过程。

    -验证的基本流程-

    如果故事到这里就没有下文了,要参与权益证明,则需要 a) 拥有权益代币以及 b) 能够运行参与验证区块链所需的基础设施。但是如果代币持有者希望用他们的代币下注以获得奖励,但不能,或者不想自己执行必需的基础设施验证呢?事实证明,大多数 PoS 协议的开发者已经考虑过这种情况,并想出了一些方法可以让代币持有者不需要自己运行节点,也不需要把币发给验证者,只需要使用一个通常被称为委托的进程,便可获得奖励。

    委托

    委托您的代币意味着将代币计入验证者的权益,以换取获得奖励的份额。实际上,委托人将代币存放在智能合约中,指定他们想要增加哪个验证者对网络的影响力。因此,相关验证者在验证过程中获得的奖励增加了,但不只有验证者收到补偿,奖励会自动在验证者和委托人之间分配;分配的具体情形取决于委托智能合约如何指定,通常是通过应用简单的佣金率来实现,如下图所示。

    请注意,这个过程是 a) 非存托的,即验证者永远不能使用代币持有者质押的加密资产,b) 在任何智能合约平台上都可以被复制,以及 c) 可以通过多种方式扩展,上面的例子仅说明委托背后的理念。

    当人们看到如何在诸如 Tezos、Cosmos、以太坊 (由第三方开发的,例如 Rocket Pool) 等协议中设计 PoS 及委托机制时,b) 和c) 就变得特别明显。这些协议在如何实现委托上有着巨大的差异,特别是支付分配以及如何处理将代币委托给恶意验证者的各方,我将在本系列的最后部分介绍其中的一些差异。

    本系列的下篇文章将关注权益证明生态系统的激励和负面激励因素。我们会列出为什么人们会把代币委托给验证者,而不是自己跑验证者节点或者提供代理操作。

     

    Part-2:守币奴时代的终结

    1

    -图片由 Christine Roy 取自 Unsplash 网站-

    随着分布式网络日趋成熟,从开发转向应用阶段,加密资产的用途也逐渐增多。例如,在权益证明网络中,代币持有者能够通过代币下注参与保护网络,并获得奖励。要想在加密资产投资上实现利益最大化,仅仅持有它并不是最优策略。为了吸引更多参与者,许多网络选择增发代币奖励支持协议的参与者,从而降低未参与网络的守币奴(hodler)的比例。下文将介绍参与权益证明网络决策的经济考虑因素。

    这是“权益证明生态系统”系列的第二篇文章。第一篇文章简要介绍了 PoS 共识算法以及验证和委托的概念,如果您之前没有读过,可以在这里找到该文。本系列的后续文章将详细介绍权益证明网络中的各个参与方,他们的立场和潜在的中心化因素。

    102:守币奴时代的终结

    到目前为止,做一个长期的加密资产投资者是相当简单的:获得想要的加密资产,然后储存好(或放在交易平台)并等待即可。之前大火的“守币奴”段子就是典型的长期投资,与许多加密货币投机者采用的短期交易策略形成鲜明对比。

    现在已经出现了可以使用加密资产的协议,例如在权益证明网络中使用代币下注或放贷,长期投资者的最佳策略不再仅仅是简单的守币(hodl)。

    在下面的分析中,我将重点关注参与权益证明网络的激励机制及其替代性方案,尤其是对比验证和委托两种方案。权益证明加密资产的所有者基本有以下几种投资选择:

    1.) 持币(Hodl),即保持代币流通
    2.) 下注
    委托他人验证
    自己验证
    自己验证并提供代理服务

    3.) 其它使用代币的方式
    借入其它代币(例如 Dharma 或者 Compound
    将代币作为抵押品(例如使用 MakerDAO 的 CDP 智能合约发行稳定币 Dai )
    交易加密资产并尝试获得更高的收益
    等等。

    从经济角度来看,理性投资者应该选择风险调整后收益最高的投资选择。实际上,这意味着代币持有者应该弄清楚这些选择都涉及哪些风险(最好能够予以量化),预期收益(在扣除开销及考虑其他限制因素后)有多少,最后对这些选择进行比较,基于自己的风险预测做出最佳决策。

    要想做好这类分析工作,重点要考虑的是权益证明网络中引入的验证及委托机制的影响因素。它们分别是:

    • 锁定代币作为押注所带来的流动性风险
    • 关于验证者集大小或最小下注余额的限制*
    • 由于罚没而丢失所押代币的风险
    • 下注会带来的预期回报,取决于验证者的表现
    • 构建、运行及维护安全的验证者基础设施所需的成本和专业知识
    • 委托他人验证的预期回报和风险

    流动性风险普遍存在于权益证明协议中;协议通常会规定质押代币的锁定期,以便惩罚作恶者并防止长程攻击。如果没有锁定期,作恶者就可以在攻击网络之后立即取回质押的代币,而不用承担被惩罚的风险。因为权益证明网络是免许可的,任何满足要求(例如质押足够数量代币)的人都可以加入验证者集。这就意味着需要有一种方法来阻止不遵守协议的行为。如果 PoS 网络中的其他参与者发现有人作恶,那么作恶者质押的代币通常会被罚没(即摧毁)。一种常见的作恶行为是给两个处于同一高度的区块签名,也称为双重签名或者模棱两可(Equivocation)。

    此外,权益证明网络的回报取决于验证者的表现。如果节点因为长期处于离线状态而未能提议或验证区块意味着会错过奖励,甚至可能因为活跃度太低而触犯罚没条件。作为相关权益的代表,你需要不间断地签名并发送信息、推动网络共识的达成;这对技术和运营都提出了极高的要求。要想确保验证者基础设施的持续运行,并且避免罚没情况,需要一个具有高度安全性的良好系统架构。对于想要攻击权益证明网络的各方来说,验证者就是活靶子。如果验证者节点被攻陷,攻击者就可以在没有任何成本的情况下对网络进行双花攻击,因为在攻击失败之时,只有验证者(及他的委托人)才会遭受罚没惩罚。在设计验证者的技术架构和密钥管理系统时,需要考虑到很多攻击手段,如 DDoS 攻击,或是验证者私钥被内外部人士恶意窃取。

    这些因素表明,构建并维护一个性能良好且安全的验证者节点需要专业技术知识、时间和一个包括相关工具在内的复杂基础设施。在考虑是否运行一个验证者节点时,应将这些要求考虑在内并计算相关成本。等到 Chorus One 启动之时,我们已经有三个人花了近一年的时间着力搭建 Cosmos 基础设施。当构建和运行验证者基础设施所产生的成本超过外包验证工作需支付的佣金时,理性的代币持有者将选择(一套)专业的代理服务。

    对于核心业务不在安全基础设施和密钥管理范围内的许多组织来说,从成本和风险最小化的角度出发,将代币委托给(一组)专业的验证者可能是正确之选。

    在考虑运行验证者基础设施时,你还可以选择接受委托,从一名验证者转变为代理服务提供者。这样做会将验证变成一项业务,从而产生更高的成本。这些成本涉及到营销、客户支持、业务拓展、法律等方面。可能需要为此组建一个专门的团队,提供服务的质量很大程度上决定了这项业务的成败。

    基于上述所有加密资产投资者可能采取的选择,下表显示了其中最重要的维度和相关特征。

    由于大多数所列选择(目前)彼此排斥,存在一些机会成本,例如选择委托验证而不是借出质押代币。这样一来,质押收益率和借款利率可能将趋于一致(如 CoinFund 的 Jake Brukhman 在这篇文章中所述)。此外,在一些 PoS 协议中,诸如动态变化的奖励之类的其他考虑因素也会影响决策。

    最后,在选择如何参与质押时,可能还需要考虑到很多非经济性目的。例如,想要支持特定组织(这点在协议治理方面尤为重要)、加强网络去中心化、监管政策、利益冲突、用户体验,在多个网络上押注成为验证者的好处以及第三方代理服务提供者可能提供的其他增值服务。

    我希望在阅读这篇文章之后,你可以基本了解权益证明网络中的激励机制,以及代币持有者这在这种环境中可以做出的选择和可能面临的风险。在“权益证明系统”系列的下一篇文章中,我将讨论 PoS 网络中将存在哪些相关方。

    103:权益持有者

    -图片由 Christine Roy 取自 Unsplash 网站-

    质押权益日益成为在无需许可的公有区块链网络中抵抗女巫攻击的方式。委托协议使得任何人都可以持有权益证明 (PoS) 区块链资产以参与保护网络,并因此获得奖励。围绕权益证明生态系统的产业正在形成。低准入门槛意味着任何与代币下注打交道的组织都可能直接或间接地参与到其中。

    在学习了验证和委托,以及权益证明中的激励措施之后,“权益证明生态系统”系列的第三部分将涉及 PoS 网络中的参与者。

    103:权益持有者

    在 PoS 网络中,人们首先想到的第一类权益持有者就是投资者,这些投资者通常分为散户和机构市场。但不只是投资者会持有权益代币;代币中的很大一部分通常会被基金会所持有,并为去中心化网络的发展提供资金。其他持有人包括那些把和加密资产打交道作为其商业活动一部分或者作为其筹资结果的公司。同样,那些将应用程序或资产托管到 PoS 网络中的项目可能会考虑通过参与共识来增强网络安全。

    另一类重要的权益持有者是可以促进购买、交易、储存和访问加密资产的第三方服务。他们需要考虑是否以及如何使他们的客户参与到这种新兴的服务中来。中心化交易所、资产托管人以及钱包都属于这一类。

    PoS 的一个重要部分是所有代币持有者都可以通过第三方基础设施提供商参与验证。这类权益持有者也被称为权益池、质押服务提供商或代理/下注服务。

    最后,区块浏览器、评级网站以及潜在的代理市场会帮助代币持有者通过聚合信息和策划可用代理服务来选择合适的服务提供商,该方式可以通过多种途径完成。下图描述了 PoS 生态系统中潜在参与者的概况:

    正如在本系列的第二部分中所强调的那样,决定是否参与下注的问题将归结为成本和风险与收益的对比分析,这是每个潜在的参与者都需要计算清楚的。虽然一些人可能会选择完全不参与质押权益,但选择参与的人就将面对这样的决定,是自己运行下注基础设施,或者委托给(一组)下注提供商,还是可能两种方式都用。

    接下来我会对每一类权益持有者都分别做简短描述,讨论他们与权益证明的联系,并附带一些例子。

    投资者

    散户投资者

    这是一个由持有权益代币的个体组成的最具多样化的群体,该群体的成员分布之广,从一般的开发者、爱好者一直到老奶奶(孙子把密码学资产当做了圣诞节礼物)都有。散户投资者可能会以多种方式成为权益证明生态系统的一部分,而这得看散户们是如何储存他们的密码学资产的。一些技术爱好者会自己运行验证者节点,以此改善他们所钟意的项目的去中心化程度。其他人可能会决定将资产存到交易所,并在该交易所参与下注。另一些人会根据自己的调查研究,将代币委托给他们喜欢的质押服务提供商,剩下的人则会依靠下注服务策划网站或市场(当下策划网站的例子有 MyTezosBaker, 市场方面的例子有 Rocketpool 或 Vest)所提供的信息。

    机构投资者

    机构投资者所能选择的下注方式与散户投资者的不同,因为这些公司绝大多数都被规章制度和其他限制所束缚,而这些束缚将影响他们如何储存和使用区块链资产。机构投资者包括早期对 PoS 项目进行投资的风投公司、可能拥有可质押密码学资产的对冲基金,以及像家族公司甚至银行等潜在的一大批其他传统投资公司。这些公司可能只是简单地雇佣自己的团队来运行验证者基础设施。另一种选择可以是成为专业服务提供商的合伙人,或者通过他们的托管人(下文将提及)参与下注。最终,机构投资者也可以使用委托协议,并且通过委托,将验证工作外包给下注服务。我们已经开始看到机构投资者们的一些早期案例了,包括运行属于自己的验证者基础设施(例如 Polychain),基金/下注服务提供商的混合架构(例如 Mythos Capital 和 Mythos Services),以及基金和质押服务提供商之间的合作(例如 Bison Trails 和 Notation Capital)。

    区块链公司

    与区块链资产(财务管理)打交道的企业

    这是一个看起来被普遍忽视的群体,但它可能会成为权益证明市场的一个重要组成部分。很多涉足区块链领域的公司和项目都将,或者正在持有可质押的区块链资产。这些资产大多数是通过 ICO 或者奖金筹集到的,比如,一些处理密码学货币支付的公司,就是持有密码学资产的例子。

    建立在权益证明区块链(商业依赖性)之上的应用程序和资产

    与上一个可能持有权益代币(来自筹款过程或商业活动)的群体相同,很多参与到区块链生态系统中的项目和公司可能都会对维护其应用程序或资产所在的 PoS 网络安全感兴趣。通过对网络的原生加密资产下注,此类项目可以帮助提高他们所依赖的网络的攻击难度。一个声称对下注有兴趣的区块链初创公司的例子就是 Gnosis

    基金会

    这是 PoS 网络中最重要且最具争议的参与者之一,因为基金会通常都会控制很大份额的权益代币。参与 PoS 共识会潜在地增加基金会对网络的进一步控制权。另一方面,支持下注的基金会对维护网络安全来说可能是必要的(特别是在早期)。与此同时,质押权益可能会提供一种持续资助去中心化网络发展的方式。委托也提供了一些额外途径来支持各组织发展去中心化网络(例如通过委托给对项目有贡献的验证者)。Tezos 基金会的运作方式可以是一个早期研究案例,我们可借此一窥基金会是如何通过培植生态系统并且降低他们的影响力,来参与权益证明生态系统的。

    第三方服务

    钱包

    在如何将下注机会融合到自身产品方面,有多种选择。一些潜在的趋势包括运行自己的验证者基础设施或者通过与服务提供商合作,向顾客提供质押服务。另一个趋势是只加入委托协议,让用户自己决定如何参与下注。在这里, Balance 关于如何将下注集成到钱包中的早期实验草案走在了前沿。

    交易所

    中心化交易所是另一个引人关注的案例,因为他们基本上控制了客户的资金,并可能潜在地代表他们的用户而参与下注。另一条路可以是在他们的系统中创建一些单独的下注账户类型,或者在交易所自己的界面上集成一个委托的选项。交易所参与下注的早期例子是 gate.io

    托管人

    一些区块链资产所有者需要将他们的资产储存到第三方中,而另一些人不想自己管理私钥,这就是为何密码学资产托管服务的巨大市场已经出现(BitGoCoinbase CustodyPolySign 等)的原因。例如,持有超过 1.5 亿美元管理资产的美国对冲基金需要将他们的资产储存在具备资格的托管人那里。这种情况将托管人置于权益证明经济的潜在的强势地位中。托管人可能会运行他们自己的验证者基础设施,也可以让客户将代币委托给一组经策划的下注提供商合伙人等。因为托管人是一个被严格管制的职业,这些公司是否以及如何参与下注,目前还不是很清晰。

    下注服务提供商

    最后,权益证明生态中最重要的新兴组织之一是专业的下注服务提供商。这些公司专门为委托人和其他合伙人创造安全可靠的验证者基础设施。这些团队可以跟以上介绍的所有相关方一起工作。在这个致力于在多 PoS 网络中提供高质量下注服务的团体中,Chorus One 就是其中的一个例子。其他一些著名的下注提供商则起到了协同推动的作用,并在验证者和权益证明生态系统(包括 Certus OneCryptium LabsFigment NetworksLunamint 及 Staking Facilities)周围培养人才。

     

     


    参考: 

     https://medium.com/chorus-one/proof-of-stake-ecosystem-101-d9230dc2685c

     https://medium.com/chorus-one/proof-of-stake-ecosystem-102-the-end-of-the-hodl-meme-fdb79151480c

     https://blog.chorus.one/proof-of-stake-ecosystem-103/

     

     

     

    展开全文
  • 产品经理的私房菜 - 腾讯产品能力模型(序章)

    万次阅读 多人点赞 2021-04-16 18:41:49
    产品经理的私房菜 - 腾讯产品能力模型(序章) ❝ 编辑导语:为了解决”产品经理“职业成长中,不自信的问题。本系列就围绕”腾讯产品的能力模型“,一起从头梳理,每一个能力项的提升思路。希望大家从梳理过程中,...

    产品经理的私房菜 - 腾讯产品能力模型(序章)

    编辑导语:为了解决”产品经理“职业成长中,不自信的问题。本系列就围绕”腾讯产品的能力模型“,一起从头梳理,每一个能力项的提升思路。希望大家从梳理过程中,找到提升的方向!

    「初稿|木深、木小深」

    「编辑|牟深、Sam、Ella」

    一、开场白

    金三银四,自然而然地就和腾讯的同事,聊到了求职这个话题。我就问她:“面试社招的同学时,会喜欢「务虚」的人,还是「务实」的人呢?”

    她想了想说道:“感觉「务实比较好」。但是实在不等于保守、封闭、唯唯诺诺,还是要体现自己「胆大」「心细」、敢于挑战「创新」”。还说,“务实能体现自己做实事的作风;胆大能体现自己挑战自我的作风;创新能体现自己有想法。她作为面试官,会喜欢这三者合一的人。”

    综上,在务实的大方向下。咱们计划,根据腾讯的能力模型逐一梳理,相信走完这轮复习,你会有所收获。

    【★本章节是序章(不涉及高P相关能力说明),目的是提供“模型”和“释义”,帮助大家设定合适自己的对标模型,作为小目标】

    二、能力模型

    2.1 能力模型表格

    能力项中标红的部分,属于最先拉满的技能,正好对应组里同事提到的“胆大、心细和创新”。所以本系列的最后一篇,有计划分享如何在简历中,凸现这三个重点。

    2.2 雷达图(对标职级T2-1)

    这是对标T2.1级别,梳理的雷达图。之后的系列,会陆续以此为目标,阐述相关能力项所需要具备的能力。

    2.3 对标职级背景

    腾讯去年宣布调整职级,取消了原有的 6 级 18 等(1.1-6.3 级)的职级体系设计,将专业职级体系优化为 14 级 (4-17 级)。与之相对应的是,统一置换为“专业职级+职位称谓”。

    • 「岗位职级」一般来讲,5年内的产品经理,大概对应“能力模型”中,1-3级。也就是T1-1 ~ T3-3这个区间内。

    • 「晋升条件」腾讯的晋升指标主要就有两部分。一方面是硬性指标:根据年限、绩效、贡献等等决定;另一方面是答辩(专业通道面试):原则上2.2之前对硬性指标的要求不高,从T2-3开始对硬性指标要求较高并有严格面试。

    三、简要说明(初级产品岗能力释义及标准)

    3.1通用能力

    1、学习能力(基本素质)

    通用释义:

    • 有学习愿望,能够在指导或者要求下进行学习
    • 能够通过示范式、教练式学习或者指定的学习资源掌握做好自身岗位工作所需要的知识、技能、工具和信息等。

    行为标准:

    • 提交参加基础业务培训或 「自学内容的」资料 「证明」、学习体会或用之于工作的证明
    • 完成要求的培训并通过对应的考核

    2、执行力(基本素质)

    通用释义:

    • 能制定简单的工作计划,保证按时完成工作任务,基本保证工作的质量

    行为标准:

    • 提交过往1年中本人负责的至少2个小型项目的 「工作计划」「执行跟踪表」「执行结果」

    3、沟通能力(基本素质)

    通用释义:

    • 有主动沟通意愿,但沟通技巧和理解能力不足
    • 能够主动跟对方沟通,完成一般的目标单一、内容简单的沟通任务

    行为标准:

    • 举证过往1年中组织的部门内的 「沟通会议的纪要」「解决的主要问题」

    5、心态和情商(关键素质)

    通用释义:

    • 乐观、积极,勤于思考,能够快速融入陌生的环境

    行为标准:

    • 举证在过往1年工作中团队融入、 「工作创新的例证」或直接上级、项目负责人的 「评价」

    3.2 专业知识

    6、技术知识(关联知识)

    通用释义:

    • 知道互联网开发过程中涉及到的主要技术名词等理论概念

    行为标准:

    • 列举自己所了解或掌握的 「技术名词」、实现 「原理」及其 「表现形式」

    7、项目管理(关联知识)

    通用释义:

    • 熟悉项目管理基础知识和和核心管理控制点。能够进行简单项目的计划跟踪和监控

    行为标准:

    • 列举并提交已完成的 「项目计划」「过程跟踪」纪要

    8、其他知识:财务、心理学、美学、办公技能等(关联知识)

    通用释义:

    • 听说过一些和本职位相关的零星的财务、法律知识
    • 能够在指导下完成一些跨BU合作项目的比较具体的工作

    行为标准:

    • 提交过往1年内参加 「跨BU合作项目」的具体工作证明和负责人的工作评价
    • 列举过往工作过程中学习或使用相关财务、法律知识的内容和对应的工作内容

    3.3 专业技能

    9、产品规划:版本计划/节奏(产品能力)

    通用释义:

    • 知道产品规划的工作流程和成果输出,能清晰描述出客户的原始需求,但需要在指导下完成功能特性的设计抽象工作

    行为标准:

    • 列举并提交过往1年中完成的 「功能特性设计」任务的过程和结果证明

    10、专业设计能力(产品能力)

    通用释义:

    • 具备一定的专业知识和技能,擅长某些方面的产品设计和策划技巧,能在别人指导下完成产品局部功能或者小型产品的设计,能使用文档清晰的向他人表述相关设计思想和内容

    行为标准:

    • 列举并提交过往1年中完成的具体 「策划设计案」的文档和研发 「结果证明」

    11、市场分析能力/前瞻性(市场能力)

    通用释义:

    • 具备基本的调研常识,能够在指导下完成调研的任务

    行为标准:

    • 列举并提交过往1年中完成的调研任务过程中的资料和 「最终的分析报告」

    12、对外商务沟通(BD/P3以上)(市场能力)

    通用释义:

    • 事先进行 「谈判策划」,能作为商务主要参与人进行谈判,掌握多种谈判技巧

    行为标准:

    • 作为主要成员 「参与过商务谈判」,并提交谈判负责人的对过程中的 「表现」得评价

    13、运营数据分析(运营能力)

    通用释义:

    • 了解运营涉及的核心数据及指标的含义,能在指导下对运营数据进行最基础的分析并给出报告

    行为标准:

    • 列举并提交过往1年中完成的运营 「数据分析报告」

    14、市场营销:品牌/公关/推广(运营能力)

    15、渠道管理(运营能力)

    通用释义:

    • 熟悉相关产品渠道管理的一般知识
    • 能够理解并掌握各项渠道政策和流程,对客户/代理商进行正确的政策引导,提供合格的渠道服务

    行为标准:

    • 列举自己过往工作过程中主要使用或掌握的 「渠道管理流程」或规范等
    • 列举并提交开展渠道服务和伙伴引导的工作成果证明

    16、市场/用户调研与分析(客户导向)

    通用释义:

    • 熟悉并掌握收集用户需求的理论、方法和基本技巧
    • 能够独立完成有明确目标的客户需求收集的任务

    行为标准:

    • 列举并提交过往1年独立完成的用户 「需求收集及分析」的过程和成果证明

    3.4 组织影响力

    17、方法论建设(领导力)

    18、知识传承(领导力)

    通用释义:

    • 在工作过程中注意积累和总结,并主动分享给其他同事,使优秀实践和成功经验得以传承和快速复制

    行为标准:

    • 提交过往1年中培训课件开发和 「经验总结」
    • 举证知识分享取得的成果,重点展示成果的 「传承和复用」

    19、人才培养(领导力)

    通用释义:

    • 有培养后备人才的意识,时刻保持对后备人选的识别、指引和关注
    • 主动引导团队其他成员一起进行知识分享,能够营造学习、分享和共同进步的团队氛围

    行为标准:

    • 举证在 「后备培养」方面所做的努力和成果,如参加通道建设工作等
    • 举证在 「营造团队学习分享氛围」方面的努力和成果

    四、结束语

    《腾讯产品能力模型 - 序章篇》就到这里啦,希望序章部分能帮助大家找到方向,积跬步以致千里。加油鸭,下期正式开始拆解具体能力模块,期待你的加入~

    本系列交流群,近期会面向读者开放一阵子,特此感谢勤劳的小助手Ella❤️。记得备注 “进群”。

    如果你有任何问题,请在留言区告诉我们。也请记得订阅「公众号木小深」和我们的专栏,欢迎分享给其它有需要的人。我们这期分享就到这里了,再见❤️。

    展开全文
  • 我们提出了一种计算方法,自主软件代理可以采用该方法来制定战术决策(例如产品定价)和战略决策(例如产品组合和生产计划),以在供需不确定的市场中最大化利润。 使用机器学习和优化技术的组合,代理能够表征经济...
  • 产品特点 HTTP / HTTPS / SOCKS5代理协议支持(包括身份验证)。 无需特殊的客户端软件。 只需将系统配置为使用代理即可。 每个配置的AWS Lambda区域都提供大量不断旋转的IP地址。 可配置多个区域之间的IP旋转...
  • 共识算法3--委托权益证明机制简介及算法实现   在区块链中使用PoS会导致贫富差距增加的问题,为解决该问题,提出了DPoS机制,DPoS已经在EOS中得到了应用。实际区块链产品中,由x个投票主节点和y个候选节点实现...
  • 代理商为何要卖增值业务?

    千次阅读 2012-01-09 00:22:51
    增值业务或者是我们自己在卖,或者是我们之外的他们在卖,不管是谁,都要在相应的渠道上销售这些增值业务,只不过渠道不尽相同而已。...要回答这个问题,我们可以从增值业务的特点,卡号产品与增值
  • 产品读书《人人都是产品经理 1.0》

    千次阅读 2018-08-07 17:09:50
    1 写给-1到3岁的产品经理 1.1 为什么要做产品经理 坏产品无处不在:垃圾桶、路标、盲道、洗手间的门、 好产品能改变世界:马桶 1.2 我们到底是不是产品经理 产品:用来解决某个问题的东西。...
  • 十万火急的数据采集项目,爬虫代理测试对比 开春上班第一天,正在喝咖啡发神,老大开会宣布公司要重点投入数据爬取和分析业务,为客户做业务做数据支撑要求达到日均1000W级别的数据采集量,让我做一下技术规划。赶紧...
  • 标志和merkle树的证明,例如Ecrecover,DeriveSha,VerifyProof等 在DynamoDB / Local上使用加密的私钥进行签名,SignTx IPFS接口 从Wei,到用Golang编写的Wei 先决条件 走 在安装 深度 安装 brew install dep ...
  • 电子商务演示微服务平台,微服务架构的概念证明。 微服务 顾客 基于Rest的api处理由MySQL支持的客户数据和交付地址 产品 基于Rest的api获取通过弹性搜索支持的产品目录。 命令 基于Rest的api发出由MySQL支持的订单 ...
  • 保险代理机构管理规定

    千次阅读 2006-05-06 08:28:00
     (三)被代理保险公司出具的收回各种单证等材料的证明;  (四)许可证原件。  保险代理机构解散的,还应当提交股东会、股东大会或者全体合伙人关于解散、清算事项的决议;保险代理机构被依法宣告破产的...
  • 人们发现,在敦促生产者和广告代理商仅使用形容词来命名产品的范围内,形容词被证明是强有力的说服力工具。 还发现有些形容词反映了社会文化方面,例如有机食品对西方和欧洲消费者具有吸引力,而贝蒂或自制食品对...
  • 作为论文的一部分,最重要的部分是证明实际上甚至可以创建这样的功能,但是我目前根本没有时间完成它。 这里还有一些我想重构的代码,对于将来我希望重构,我并不感到骄傲。 建筑 运行mvn clean package -...
  • 著名财经作家吴晓波预言道:2015是一个创业的大浪潮。当O2O,电商,社交已经在...作为产品经理的杨柳做出了不一样的抉择,他成熟选择的背后又有不为人知的艰辛,这些都能给产品小白们,甚至是创业者们很好的思路!
  • 核心功能有了,于是就开始做乞丐版,由于只是内部工具,连UI和产品设计都不需要,只需要让不会写代码的同事们可以无障碍地使用这个脚本工具即可。 视频转码压缩效果貌似还和电脑的芯片组有关(因为视频同事们曾经...
  • 从2015年开始,锁企数量猛增,产品功能也更加丰富,截止目前上千家锁企同台竞技。 随着锁企厮杀的展开,一代新人换旧人就层出不穷,入局者涵盖传统家电厂商、专业锁具厂商、互联网新进品牌、安防巨头以及电子通信...
  • 8人以上社保缴纳证明 2、营业范围 营业范围包含金融服务(含融资性担保、小额信贷)或咨询服务等,且符合法律法规要求;原则上企业成立一年(含)以上,具有一定的客户资源。 3、管理团队 管理团队至少...
  • 2008年开始,我们在卖e网打进,Web based Software。...到头来大家发现,做企业级产品不能像个人网络应用这么玩,太时尚了,我们还是要回归传统,搞点实在的东西。于是有了下图,无中生有的搞出一些实体化的东西,这
  • 近日,360公司董事长周鸿祎做客腾讯科技《新产品经理》系列访谈,期间他将自己多年的产品心得和盘托出,甚至访谈中都不需要腾讯科技发问。不得不说,这场访谈也是在《新产品经理》系列访谈中最精彩的对话之一。前言...
  • 原文出处:GitHub:... 1、Nginx简介 Nginx ("engine x") 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器。Nginx是由Igor Sysoev为俄罗斯访问量第二的Rambler.r...
  • 产品经理,业务或产品意识

    千次阅读 2017-11-27 18:59:54
    互联网产品的运营指标- http://blog.csdn.net/ZLJ925/article/details/78606814 产品经理之产品运营-全栈工程师 - http://blog.csdn.net/nupotian/article/details/71198909 产品经理做APP从头到尾的所有工作流程...
  • 腾讯科技:我听周总讲这些东西的时候,有一个感觉,比如一个很棒的产品经理,他的产品会和他过去的经历和从事的事业都关系,然后导致他这种思想的形成? 周鸿祎:有句通俗的话,如果你解决问题的能力,是一个榔头...
  • 谷歌前CEO埃里克·施密特和前高级副总裁兼产品团队的的管理人乔纳森·罗森伯格。本书分享了作者们十余年来帮助谷歌成长所领悟到的管理启示:科技正在改变商业的方方面面,这种改变速度空前,而且仍在加速,公司若想...
  • matlab之产品大全

    千次阅读 多人点赞 2020-12-16 19:30:59
    多边形验证码 6.Polyspace代码验证访问 7.Polyspace代码验证服务器 8.Ada的Polyspace产品 9.Simulink Check 10.Simulink覆盖范围 11.Simulink设计验证器 12.Simulink测试 十七、数据库访问和报告 1.数据库工具箱 2....
  • 受交通运输部门向电动和共享出行的深度... 我们贡献了一个通用框架,该框架为类似的多产品资源分配设置提供了蓝图,并通过沿该框架的维度开发定制的分析和基于机器学习的解决方案方法来证明其在 SEV 车队领域的功效。
  • Oracle 应用产品11iSAP R/3 4.0SSASYMIX应用软件的功能· 以资源的全面管理为思想,目标是适应市场的变化,增强企业的竞争和生存能力。· 企业级功能: 从企业后台到前台,覆盖范围广,包括:财务, 分销/销售, 制造...
  • 产品经理这份工作将涉及大量选择,本质上,是需要“输入→内视→输出”的环节更多,所以为了更好的去进行“输出”,学习“输入”(AI基础认知、产品认知、技术通识)以及“内视”(认知框架)的重要性就不言而喻了...
  • 电商产品架构是整个电商数字系统的基本框架,它代表了这个虚拟数字世界的游戏规则,也反映出了电商企业的商业核心战略,一个好的电商产品架构是构建一个电商生态体系的关键。 电子商务中的角色定位 要规划出一个...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 22,239
精华内容 8,895
关键字:

产品代理证明