精华内容
下载资源
问答
  • 响应式编程简介之:Reactor

    万次阅读 2020-11-06 09:12:47
    Reactor是reactivex家族的个非常重要的成员,Reactor是第四代的reactive library,它是基于Reactive Streams标准基础上开发的,主要用来构建JVM环境下的非阻塞应用程序。 今天给大家介绍一下Reactor。

    简介

    Reactor是reactivex家族的一个非常重要的成员,Reactor是第四代的reactive library,它是基于Reactive Streams标准基础上开发的,主要用来构建JVM环境下的非阻塞应用程序。

    今天给大家介绍一下Reactor。

    Reactor简介

    Reactor是基于JVM的非阻塞API,他直接跟JDK8中的API相结合,比如:CompletableFuture,Stream和Duration等。

    它提供了两个非常有用的异步序列API:Flux和Mono,并且实现了Reactive Streams的标准。

    并且还可以和reactor-netty相结合,作为一些异步框架的底层服务,比如我们非常熟悉的Spring MVC 5中引入的WebFlux。

    我们知道WebFlux的底层使用的是reactor-netty,而reactor-netty又引用了Reactor。所以,如果你在POM中引入了webFlux依赖:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
    

    那么项目将会自动引入Reactor。

    如果你用的不是Spring webflux,没关系,你可以直接添加下面的依赖来使用Reactor:

    <dependency>
        <groupId>io.projectreactor</groupId>
        <artifactId>reactor-core</artifactId>
    </dependency>
    

    reactive programming的发展史

    最最开始的时候微软为.NET平台创建了Reactive Extensions (Rx) library。接着RxJava实现了JVM平台的Reactive。

    然后Reactive Streams标准出现了,它定义了Java平台必须满足的的一些规范。并且已经集成到JDK9中的java.util.concurrent类中。

    在Flow中定义了实现Reactive Streams的四个非常重要的组件,分别是Publisher,Subscriber,Subscription和Processor。

    Iterable-Iterator 和Publisher-Subscriber的区别

    一般来说reactive在面向对象的编程语言中是以观察者模式的扩展来使用的。

    我们来具体看一下这个观察者模式的实现,以Publisher和Subscriber为例:

       public static interface Publisher<T> {
            public void subscribe(Subscriber<? super T> subscriber);
        }
    
        public static interface Subscriber<T> {
    
            public void onSubscribe(Subscription subscription);
    
            public void onNext(T item);
    
            public void onError(Throwable throwable);
    
            public void onComplete();
        }
    

    上面定义了两个接口,Publisher和Subscriber,Publisher的作用就是subscribe到subscriber。

    而subscriber定义了4个on方法,用来触发特定的事件。

    那么Publisher中的subscribe是怎么触发Subscriber的onSubscribe事件呢?

    很简单,我们看一个具体的实现:

        public void subscribe(Flow.Subscriber<? super T> subscriber) {
            Subscription sub;
            if (throwable != null) {
                assert iterable == null : "non-null iterable: " + iterable;
                sub = new Subscription(subscriber, null, throwable);
            } else {
                assert throwable == null : "non-null exception: " + throwable;
                sub = new Subscription(subscriber, iterable.iterator(), null);
            }
            subscriber.onSubscribe(sub);
    
            if (throwable != null) {
                sub.pullScheduler.runOrSchedule();
            }
        }
    

    上面的例子是PullPublisher的subscribe实现。我们可以看到,在这个subscribe中触发了subscriber.onSubscribe方法。而这就是观察者模式的秘密。

    或者说,当Publisher调用subscribe的时候,是主动push subscriber的onSubscribe方法。

    熟悉Iterable-Iterator模式的朋友应该都知道,Iterator模式,其实是一个主动的pull模式,因为需要不断的去调用next()方法。所以它的控制权是在调用方。

    为什么要使用异步reactive

    在现代应用程序中,随着用户量的增多,程序员需要考虑怎么才能提升系统的处理能力。

    传统的block IO的方式,因为需要占用大量的资源,所以是不适合这样的场景的。我们需要的是NO-block IO。

    JDK中提供了两种异步编程的模型:

    第一种是Callbacks,异步方法可以通过传入一个Callback参数的形式来在Callback中执行异步任务。比较典型的像是java Swing中的EventListener。

    第二中就是使用Future了。我们使用Callable来提交一个任务,然后通过Future来拿到它的运行结果。

    这两种异步编程会有什么问题呢?

    callback的问题就在于回调地狱。熟悉JS的朋友应该很理解这个回调地狱的概念。

    简单点讲,回调地狱就是在callback中又使用了callback,从而造成了这种callback的层级调用关系。

    而Future主要是对一个异步执行的结果进行获取,它的 get()实际上是一个block操作。并且不支持异常处理,也不支持延迟计算。

    当有多个Future的组合应该怎么处理呢?JDK8 实际上引入了一个CompletableFuture类,这个类是Future也是一个CompletionStage,CompletableFuture支持then的级联操作。不过CompletableFuture提供的方法不是那么的丰富,可能满足不了我的需求。

    于是我们的Reactor来了。

    Flux

    Reactor提供了两个非常有用的操作,他们是 Flux 和 Mono。 其中Flux 代表的是 0 to N 个响应式序列,而Mono代表的是0或者1个响应式序列。

    我们看一个Flux是怎么transfer items的:

    先看下Flux的定义:

    public abstract class Flux<T> implements Publisher<T> 
    

    可以看到Flux其实就是一个Publisher,用来产生异步序列。

    Flux提供了非常多的有用的方法,来处理这些序列,并且提供了completion和error的信号通知。

    相应的会去调用Subscriber的onNext, onComplete, 和 onError 方法。

    Mono

    我们看下Mono是怎么transfer items的:

    看下Mono的定义:

    public abstract class Mono<T> implements Publisher<T> 
    

    Mono和Flux一样,也是一个Publisher,用来产生异步序列。

    Mono因为只有0或者1个序列,所以只会触发Subscriber的onComplete和onError方法,没有onNext。

    另一方面,Mono其实可以看做Flux的子集,只包含Flux的部分功能。

    Mono和Flux是可以互相转换的,比如Mono#concatWith(Publisher)返回一个Flux,而 Mono#then(Mono)返回一个Mono.

    Flux和Mono的基本操作

    我们看下Flux创建的例子:

    Flux<String> seq1 = Flux.just("foo", "bar", "foobar");
    List<String> iterable = Arrays.asList("foo", "bar", "foobar");
    Flux<String> seq2 = Flux.fromIterable(iterable);
    Flux<Integer> numbersFromFiveToSeven = Flux.range(5, 3);
    

    可以看到Flux提供了很多种创建的方式,我们可以自由选择。

    再看看Flux的subscribe方法:

    Disposable subscribe(); 
    
    Disposable subscribe(Consumer<? super T> consumer); 
    
    Disposable subscribe(Consumer<? super T> consumer,
              Consumer<? super Throwable> errorConsumer); 
    
    Disposable subscribe(Consumer<? super T> consumer,
              Consumer<? super Throwable> errorConsumer,
              Runnable completeConsumer); 
    
    Disposable subscribe(Consumer<? super T> consumer,
              Consumer<? super Throwable> errorConsumer,
              Runnable completeConsumer,
              Consumer<? super Subscription> subscriptionConsumer);
    

    subscribe可以一个参数都没有,也可以多达4个参数。

    看下没有参数的情况:

    Flux<Integer> numbersFromFiveToSeven = Flux.range(5, 3);
    
    numbersFromFiveToSeven.subscribe();
    

    注意,没有参数并不表示Flux的对象不被消费,只是不可见而已。

    看下带参数的情况:consumer用来处理on each事件,errorConsumer用来处理on error事件,completeConsumer用来处理on complete事件,subscriptionConsumer用来处理on subscribe事件。

    前面的3个参数很好理解,我们来举个例子:

    Flux<Integer> ints3 = Flux.range(1, 4);
            ints3.subscribe(System.out::println,
                    error -> System.err.println("Error " + error),
                    () -> System.out.println("Done"),
                    sub -> sub.request(2));
    

    我们构建了从1到4的四个整数的Flux,on each就是打印出来,如果中间有错误的话,就输出Error,全部完成就输出Done。

    那么最后一个subscriptionConsumer是做什么用的呢?

    subscriptionConsumer accept的是一个Subscription对象,我们看下Subscription的定义:

    public interface Subscription {
    
        public void request(long n);
        public void cancel();
    }
    

    Subscription 定义了两个方法,用来做初始化用的,我们可以调用request(n)来决定这次subscribe获取元素的最大数目。

    比如上面我们的例子中,虽然构建了4个整数,但是最终输出的只有2个。

    上面所有的subscribe方法,都会返回一个Disposable对象,我们可以通过Disposable对象的dispose()方法,来取消这个subscribe。

    Disposable只定义了两个方法:

    public interface Disposable {
    
    	void dispose();
    
    	default boolean isDisposed() {
    		return false;
    	}
    

    dispose的原理是向Flux 或者 Mono发出一个停止产生新对象的信号,但是并不能保证对象产生马上停止。

    有了Disposable,当然要介绍它的工具类Disposables。

    Disposables.swap() 可以创建一个Disposable,用来替换或者取消一个现有的Disposable。

    Disposables.composite(…​)可以将多个Disposable合并起来,在后面统一做处理。

    总结

    本文介绍了Reactor的基本原理和两非常重要的组件Flux和Mono,下一篇文章我们会继续介绍Reactor core的一些更加高级的用法。敬请期待。

    本文的例子learn-reactive

    本文作者:flydean程序那些事

    本文链接:http://www.flydean.com/introduction-to-reactor/

    本文来源:flydean的博客

    欢迎关注我的公众号:「程序那些事」最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

    展开全文
  • 响应式开发原理

    千次阅读 2018-06-19 22:59:50
    什么是响应式网站?就是在不同终端设备上和任何尺寸的屏幕上也可以展示完美的设计响应式网站的概念:flexible grid layout 弹性网格布局flexible ...只需要份多出来的工作量只是JS脚本、CSS样式做一些改变 节...

    什么是响应式网站?

    就是在不同终端设备上和任何尺寸的屏幕上也可以展示完美的设计

    响应式网站的概念:

    • flexible   grid   layout    弹性网格布局
    • flexible   image    弹性图片
    • media queries   媒体查询

    响应式网站的优点:

    • 减少工作量

    1.  网站、设计、代码、内容都 只需要一份
    2. 多出来的工作量只是JS脚本、CSS样式做一些改变              

    •    节省时间
    • 每个设备都能得到正确的设计
    • 搜索优化

    响应式网站的缺点:

    • 会加载更多的样式和脚本资源
    • 设计比较难精确定位和控制
    • 老版本浏览器兼容不好

    媒体查询:

    @media all and (min-width:800px) and (orientation:landscape){
    ...
    }

        and-----与-------全部匹配

        or-------或-------任意条件匹配

        not------非    

    CSS3媒体查询属性简介:

    • width:视口宽度
    • height:视口高度
    • device-width:渲染表面的宽度,就是设备屏幕的宽度
    • device-height:渲染表面的高度,就是设备屏幕的高度
    • orientation:检查设备处于横向还是纵向
    • aspect-ratio:基于视口宽度和高度的宽高比        width/height  如:16/9,4/3

    • device-aspect-ratio:渲染表面的宽度,就是设备屏幕的宽度
    • color:每种颜色的位数bits    如:min-color:16位,8位
    • resolution:检测屏幕或打印机的分辨率    如:min-resolution

    以上属性都可以添加min-max-前缀

    viewport视口:

    • 布局视口(layout viewport)    宽度不变的
    • 可视视口(visual viewport)    显示布局视口的不同内容
    • 理想视口(ideal viewport)    理想视口就是布局视口在一个设备上的最佳尺寸

    理想视口就是为构建手机浏览器优化的页面而添加

    <meta name="viewport" content="width=device-width/>"	

    百度的设置

    <meta name="viewport" content="width=device-width,
    minimum-scale=1.0,		//最小的缩放比例
    maximum-scale=1.0,		//最大的缩放比例
    user-scalable=no/>"	
    怎样分析设计图:

    分析结构:实现部分区域的复用

    如何组织项目目录结构

    • 约定优于配置(convention    over    configuration)
    • 约定代码结构或命名规范来减少配置数量
    • css/*.css
    • jquery.js ->jquery.min.js

    没有最好的组织方式,只有合适的组织方式

    这是我的项目目录:


    使用markdown:

    • 标题:# 空一格+标题内容(一般有六级标题,二级标题加两个##,以此类推)
    • 无序列表:* 空一格+名称;    有序列表:1. 空一格+名称
    • 引用一段名言> 空一格 +引用的名言
    • 链接:[百度](http://www.baidu.com)
    • 加入图片:![百度](http://www.baidu.com)
    • 粗体:用两个**前后包裹住    斜体:用一个*前后包裹住    粗体加斜体:用三个***包裹
    • 表格:   
    |Col1|Col2|Col3|      //第一行
    |---|---|---|         //对齐方式     
    |aaa|111|222|         //内容
    |bbb|222|333|         //内容
            对齐方式:|:---|:---|:---|    左对齐        |---|:---:|---|    居中       |---:|---:|---:| 

            必须写对齐方式

    • 代码:`在代码前后包裹,显示一行的代码;    多行的代码:用三个```包裹

    开始编写HTML代码

    检测IE版本,版本过低则提醒更新

    <!doctype html>
    <html lang="zh-CN">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <meta name="viewport"
              content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <title>理财网站</title>
    </head>
    <body>
    <!--[if ht/lt/gte >=/lte <= IE8]-->
    <p class="browserupgrade">
        你的浏览器版过低,请到<a href="http://browsehappy.com/">这里
        </a>更新,以获得最佳的体验
    </p>
    <!--[endif]-->
    
    </body>
    </html>
    header部分以及H5新增标签简介

    • header    头部    footer    底部
    • nav    导航栏
    • article    是一个特殊section,独立的有内容的区块
    • section    标签定义文档中的节(section、区段)。比如章节、页眉、页脚或文档中的其他部分
    • b    加粗,吸引人注意
    • em    重点强调
    • i    定义与文本中其余部分不同的部分,并把这部分文本呈现为斜体文本。

    命名规则:

    一般都使用class定义样式,id一般用于js快速的区别和获取元素class,一般都用中横线分隔,id一般都使用驼峰命名法

    项目的HTML结构(也可以在我的github看到:点击进入

    <!doctype html>
    <html lang="zh-CN">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <meta name="viewport"
              content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <title>理财网站</title>
    </head>
    <body>
    <!--[if ht/lt/gte >=/lte <= IE8]-->
    <p class="browserupgrade">你的浏览器版过低,请到<a href="http://browsehappy.com/">这里
        </a>更新,以获得最佳的体验</p>
    <!--[endif]-->
    
    <header>
        <nav class="top">
            <span class="tel">理财热线:400-688-888</span>
            <ul>
                <li><a href="#">登录</a></li>
                <li><a href="#">快速注册</a></li>
                <li><a href="#">关于</a></li>
                <li><a href="#">帮助</a></li>
                <li><a href="#">APP下载</a></li>
            </ul>
        </nav>
        <nav class="main">
            <a href="#" class="brand"><img src="img/logo@1x.png" alt="回到首页"></a>
            <ul>
                <li><a href="#">首页</a></li>
                <li><a href="#">理财频道</a></li>
                <li><a href="#">投资频道</a></li>
                <li><a href="#">新手专区</a></li>
                <li><a href="#">安全保障</a></li>
            </ul>
        </nav>
    </header>
    
    <div class="container">
        <div class="transaction">
            <div class="trans-content">
                <div class="trans-data">
                    <span>平台累计成交金额</span>
                    <span class="trans-money">19888</span>
                    <span>万元</span>
                </div>
                <div class="trans-data">
                    <span>过去7日成交金额</span>
                    <span class="trans-money">1888</span>
                    <span>万元</span>
                </div>
                <div class="trans-report">
                    <a href="#">查看平台运营报告</a>
                </div>
            </div>
        </div>
    
        <div class="ad">
            <div class="item">
                <img src="img/ad001.png" alt="">
            </div>
            <div class="item">
                <img src="img/ad002.png" alt="">
            </div>
            <div class="item">
                <img src="img/ad003.png" alt="">
            </div>
        </div>
    
        <section class="feature">
            <div class="item">
                <h3>安全</h3>
                <p>国家AAA信用平台 <br>银行资金托管 <br>上市公司背景保证</p>
            </div>
            <div class="item">
                <h3>权威</h3>
                <p>中央电视台推荐 <br>互联网百强企业 <br>标准起草单位</p>
            </div>
            <div class="item">
                <h3>省心</h3>
                <p>100元旗头 <br>用户利益保障机制 <br>保险公司承保</p>
            </div>
        </section>
    
        <div class="notice">
            <a href="#">
                <span>201-6-31</span>
                元旦期间业务受理及值班元旦期间业务受理及值班元旦期间业务受理及值班元旦期间业务受理及值班
            </a>
            <a href="#" class="more">更多公告</a>
        </div>
    
        <section class="product">
            <h2>
                固定期限产品
                <em>甄选优质基金</em>
                <em>省时省力</em>
                <em>坐等收益</em>
            </h2>
    
            <div class="product-content">
                <div class="item">
                    <h3><em>3</em>个月</h3>
                    <div class="info">
                        <p>约定年化收益:<span class="year-rate">3.5% <i>起</i></span></p>
                        <p>总成交金额:<span class="money">1888<i>万元</i></span></p>
                    </div>
                    <div class="buy">
                        <a href="#">购买</a>
                    </div>
                </div>
                <div class="item">
                    <h3><em>3</em>个月</h3>
                    <div class="info">
                        <p>约定年化收益:<span class="year-rate">3.5% <i>起</i></span></p>
                        <p>总成交金额:<span class="money">1888<i>万元</i></span></p>
                    </div>
                    <div class="buy">
                        <a href="#">购买</a>
                    </div>
                </div>
                <div class="item">
                    <h3><em>3</em>个月</h3>
                    <div class="info">
                        <p>约定年化收益:<span class="year-rate">3.5% <i>起</i></span></p>
                        <p>总成交金额:<span class="money">1888<i>万元</i></span></p>
                    </div>
                    <div class="buy">
                        <a href="#">购买</a>
                    </div>
                </div>
                <div class="item">
                    <h3><em>3</em>个月</h3>
                    <div class="info">
                        <p>约定年化收益:<span class="year-rate">3.5% <i>起</i></span></p>
                        <p>总成交金额:<span class="money">1888<i>万元</i></span></p>
                    </div>
                    <div class="buy">
                        <a href="#">购买</a>
                    </div>
                </div>
                <div class="item">
                    <h3><em>3</em>个月</h3>
                    <div class="info">
                        <p>约定年化收益:<span class="year-rate">3.5% <i>起</i></span></p>
                        <p>总成交金额:<span class="money">1888<i>万元</i></span></p>
                    </div>
                    <div class="buy">
                        <a href="#">购买</a>
                    </div>
                </div>
            </div>
        </section>
    
        <section class="product">
    
            <h2>
                固定期限产品
                <em>甄选优质基金</em>
                <em>省时省力</em>
                <em>坐等收益</em>
            </h2>
    
            <div class="product-content">
                <div class="item">
                    <h3><em>3</em>个月</h3>
                    <div class="info">
                        <p>约定年化收益:<span class="year-rate">3.5% <i>起</i></span></p>
                        <p>总成交金额:<span class="money">1888<i>万元</i></span></p>
                    </div>
                    <div class="buy">
                        <a href="#">购买</a>
                    </div>
                </div>
                <div class="item">
                    <h3><em>3</em>个月</h3>
                    <div class="info">
                        <p>约定年化收益:<span class="year-rate">3.5% <i>起</i></span></p>
                        <p>总成交金额:<span class="money">1888<i>万元</i></span></p>
                    </div>
                    <div class="buy">
                        <a href="#">购买</a>
                    </div>
                </div>
                <div class="item">
                    <h3><em>3</em>个月</h3>
                    <div class="info">
                        <p>约定年化收益:<span class="year-rate">3.5% <i>起</i></span></p>
                        <p>总成交金额:<span class="money">1888<i>万元</i></span></p>
                    </div>
                    <div class="buy">
                        <a href="#">购买</a>
                    </div>
                </div>
                <div class="item">
                    <h3><em>3</em>个月</h3>
                    <div class="info">
                        <p>约定年化收益:<span class="year-rate">3.5% <i>起</i></span></p>
                        <p>总成交金额:<span class="money">1888<i>万元</i></span></p>
                    </div>
                    <div class="buy">
                        <a href="#">购买</a>
                    </div>
                </div>
                <div class="item">
                    <h3><em>3</em>个月</h3>
                    <div class="info">
                        <p>约定年化收益:<span class="year-rate">3.5% <i>起</i></span></p>
                        <p>总成交金额:<span class="money">1888<i>万元</i></span></p>
                    </div>
                    <div class="buy">
                        <a href="#">购买</a>
                    </div>
                </div>
            </div>
    
        </section>
    
        <section class="footer">
            <div class="footer-content">
                <p class="brand"></p>
                <ul>
                    <li class="title">关于我们</li>
                    <li><a href="#">公司介绍</a></li>
                    <li><a href="#">业务模式</a></li>
                    <li><a href="#">合作结构</a></li>
                    <li><a href="#">服务协议</a></li>
                </ul>
                <ul>
                    <li class="title">风险防范</li>
                    <li><a href="#">账户安全</a></li>
                    <li><a href="#">安全保障</a></li>
                </ul>
                <ul>
                    <li class="title">理财产品</li>
                    <li><a href="#">固定期限</a></li>
                    <li><a href="#">债权/散标</a></li>
                </ul>
                <ul>
                    <li class="title">交易帮助</li>
                    <li><a href="#">购买</a></li>
                    <li><a href="#">赎回</a></li>
                    <li><a href="#">提现</a></li>
                </ul>
                <ul>
                    <li class="title">机构服务</li>
                    <li><a href="#">机构中心</a></li>
                    <li><a href="#">合作联系</a></li>
                </ul>
            </div>
        </section>
    </div>
    
    <footer>
        <ul>
            <li><span class="icon icon-zfywxk">支付业务许可证</span></li>
            <li><span class="icon icon-pcirk">PCI认证</span></li>
            <li><span class="icon icon-visayz">Visa 验证</span></li>
            <li><span class="icon icon-vsjmfw">VerSign加密服务</span></li>
            <li><span class="icon icon-wlgs">网络工商</span></li>
            <li><span class="icon icon-rzcx">电子商务协会认证诚信网</span></li>
            <li><span class="icon icon-gs">北京工商</span></li>
        </ul>
        <p>北京某互联网金融公司 版权所有 @ 2017-2018 </p>
    </footer>
    
    </body>
    </html>

    实现PC端样式

    • 使用Normalize.csss作为项目的初始css样式代码:点击获取(消除浏览器之间的差异)

    px、em、rem的区别

    • px相对于屏幕分辨率的一个单位1px相当于1个像素 ,固定的单位
    • em相对的长度单位;                       

    1. em相对参照物为父元素的font-size,
    2. em具有继承的特点,如果父元素没有设置font-size就向上找
    3. 当没有设置font-size时,浏览器会有一个默认的em设置:1em = 16px
    4. em的缺点:容易错乱
    • rem的相对参照物为根元素html,相对于参照固定不变,所以比较好计算,当没有设置font-size时,浏览器会有一个默认的rem设置:1rem = 16px,这点与em一致的

            font-size:  62.5%    1rem = 10px  (10/16*100%)

            font-size:  100%    1rem = 16px

    清除浮动(目前最好的两种方法):

    .clearfix:after{
        content: ".";
        display: block;
        height: 0;
        clear: both;
        visibility: hidden;
    }
    .clearfix {
        zoom: 1;
    }
    .clearfix:after,
    .clearfix:before {
        content: "";
        display: table;
    }
    .clearfix:after {
        clear: both;
    }

    实现移动端样式

    使用媒体查询实现

    • 设置断点:以常用的断点设置,不要为专门的设备设置断点,主要要以设计图为主
    • 断点区间设置不同的padding...之类的样式

    CSS选择器:

    • E > F    ul > li 就是选ul下的子类li,不是子孙的li
    • E + F    ul li + li 就是选ul下除了第一个的li外的所有li
    • E ~F     

    <ul>
            <li></li>
            <li></li>
            <a href=""></a>
            <a href=""></a>
            <li></li>
        </ul>

        ul li ~li就是选到除第一个li外的所有li(注意和第二种的差别)


    属性选择器:

    • E[attr]    有attr这个属性就可以
    • E[attr = "value"]    有attr这个属性,还要完全等于value这个值
    • E[attr^ = "value"]    有attr这个属性,以value开头,如:a[href^="http://"]
    • E[attr$ = "value"]    有attr这个属性,以value结尾,如:img[src$=".png"]
    • E[attr* = "value"]    有attr这个属性,包含value就可以了
    • E[attr~ = "value"]    有attr这个属性,以空格分开的词汇都可以模糊的选择到
    • E[attr|= "value"]    有attr这个属性,以value开头或者有value-开头的值

    打印样式设置,在main.css最后面添加下面的代码即可:

    @media print {
        *,
        *:before,
        *:after{
            background: transparent !important;
            color: #000 !important;
            box-shadow: none!important;
            text-shadow: none!important;
        }
    
        a,
        a:visited {
            text-decoration: underline;
        }
    
        a[href]:after {
            content: "(" attr(href)")";
        }
    
        abbr[title]:after {
            content: "(" attr(title)")";
        }
    
        /*
        *   使用#和JavaScript的超链接不打印href
        */
        a[href^="#"]:after,
        a[href^="javascript"]:after {
            content: "";
        }
    
        pre,
        blockquote {
            border: 1px solid #999999;
            /* page-break-inside只有opera浏览器起作用,避免在元素内部插入分页符*/
            page-break-inside: avoid;
        }
    
        thead {
            display: table-header-group;
        }
    
        tr,
        img{
            page-break-inside: avoid;
        }
    
        img {
            max-width: 100%!important;
        }
    
        p,
        h2,
        h3 {
            /* 这两个属性的作用,当标题和文字底部发生分页时,保证标题和内容不会分开 */
            orphans: 3;
            widows: 3;
        }
    
        h2,
        h3 {
            page-break-after: avoid;
        }
    }

    如何实现响应式广告和响应式图片

    一个好的广告滚动组件支持:

    • 支持不同的图片数量
    • 支持响应式布局
    • 具有良好的兼容性

    怎么样来挑选第三方组件:

    • 使用人数
    • 是否开源
    • 文档是否齐全
    • 活跃性
    • 小乔够用的组件(轻量级)

    这里选用的是Owl Carousel 2,链接:点击打开链接

    响应式图片:

    • js或者服务端实现(服务端实现:通过把屏幕或者设备信息写入cookie,在获取图片的时候,由服务端决定返回那种图片)
    • srcset    img标签中的一个属性,
    <div class="content">
        <img class="image" src="img/480.png"
            srcset="img/480.png 480w, img/800.png 800w, img/1600.png 1600w">
    </div>
        由浏览器自己来选择图片,当加载了大图片时,缩小浏览器,图片不会变,浏览器认为图片已经加载在html中了
    • srcset配合sizes
    <div class="content">
        <img class="image" src="img/480.png"
            srcset="img/480.png 480w, img/800.png 800w, img/1600.png 1600w"
            sizes="(min-width:800px) calc(100vw - 30em), 100vw">
    </div>
    • picture
    <div class="content">
        <picture>
            <source media="(min-width:36em)"
                    srcset="img/tiananmen-s.jpg 768w"/>
            <source media="(min-width:36em)"
                    srcset="img/tiananmen.jpg 1600w"/>
            <source type="image/svg+xml" srcset="logo.svg 480w, logo.svg 800w,logo.svg 1600w"/>
            <source type="image/webp" srcset="logo.webp 480w, logo-m.webp 800w,log-lo.webp 1600w"/>
    
            <img class="image" src="img/tiananmen.jpg" alt="">
        </picture>
    </div>

    可以设置多个source来进行响应式图片的设计,还可以设置宽屏、横屏下的图片显示不同;也可以支持webp图片

    webp是谷歌开发出来的图片,更小

    • svg

        矢量图形,无论浏览器怎么缩放,图片都不会失真

    这里有两个在线绘制的网站:IcoMoon    http://editor.method.ac/

    这里项目的响应式图片处理:

    这里使用picture,需要使用一个库:picturefill 来处理picture的兼容性

    对svg的图片进行压缩:iconizr

    对png的图片进行压缩:tinypng

    可以在我的github上查看这个项目:responsive-project,如果想自己看视频学习,可以加我百度云(任性的_我),免费赠送学习视频

    Node.js简介

    Node.js是一个基于Chrome V8引擎的JavaScript运行环境。Node.js使用了一个事件驱动,非阻塞式 I/O的模型,使其轻量又高效。Node.sj的包管理器npm,是全球最大的开源库生态系统。

    npm的使用:

    • npm install +包名,如:npm install jquery(在国内最好使用cnpm,在我的这篇博客上写了具体的安装方法 npm与调试工具的安装
    • cnpm init     创建package.json(这里使用的cnpm是npm的镜像,使下载更快)

     其中package.json下有两个依赖:

    "dependencies": {},
    "devDependencies": {},
    • "dependencies"是用于配置生产环境
    • "devDependencies"是用于配置开发环境
    "dependencies": {
        "jquery": "^3.3.1"
      },

    •  "jquery": "^3.3.1"    前面写包名,后面写包的版本
    • ^是使版本号在大于等于3.3.1的版本号都可以,注意大版本号需要相同;如:3.4.* , 3.5.*

    使用node.js下的http-server服务,就可以在网站上通过相应的端口号进行访问,不在是只在本地才可以访问(http-server 网站:点击打开

    • 安装:cnpm install http-server -g

    处理兼容性以及在多个设备上进行调试

    PC端如何处理兼容性:

    • 在主要的浏览器上都要进行测试,如:谷歌、火狐、欧朋、IE等浏览器上进行测试
    • 下载IETester进行IE的测试

    移动端处理兼容性:

    • Genymotion来进行安卓虚拟机的测试   genymotion
    • hack的兼容性问题 ,使用这个网站:browserhacks
    • 解决IE低版本不支持h5新标签的问题,使用这个方法:html5shiv
    • 解决IE低版本不支持css3条件查询的问题,使用这个:Respond
    • 主动的测试:modernizr (防御性编程),可以检测新特性在不同浏览器的兼容性。
    • 也可以在这个网站查属性的兼容性:can i use

    在多个设备上进行调试:

    打包发布

    • 在发布之前还可以做代码优化:

    1.  压缩
    2. 合并
    3. 增加版本号           

        压缩可以使用手动的方法,直接把代码拷到这个网站:javascript-minifier

    • 主流的3个工具

    1. Grunt    (自动化构建工具)
    2. Gulp    (自动化构建工具)
    3. Webpack    (静态资源打包工具)

        Gulp中文文档:gulp中文文档

        安装gulp:

    cnpm install gulp -g
    cnpm install gulp --save-dev

        安装gulp所需的插件:

    cnpm install gulp-dev gulp-rev-replace gulp-useref gulp-filter gulp-uglify gulp-csso --save-dev

        这些插件的作用:

    • gulp-dev     添加版本号,给每个文件计算一个哈希码,当文件发生改变时,哈希码也会发生改变
    • gulp-rev-replace    当文件名改变了,把文件的引用也修改为新的文件名
    • gulp-useref     通过注释来告诉gulp把哪些文件进行一些合并,怎么的方式合并,合并之后文件的命名(网站:gulp-useref
    • gulp-filter    把文件做一些压缩,然后又把文件放回去
    • gulp-uglify      压缩js的插件
    • gulp-csso     压缩css的插件

        代码如下:

    var gulp = require("gulp");
    var rev = require("gulp-dev");
    var revReplace = require("gulp-rev-replace");
    var useref = require("gulp-useref");
    var filter = require("gulp-filter");
    var uglify = require("gulp-uglify");
    var csso = require("gulp-csso");
    
    
    gulp.task('default', function () {
        var jsFilter = filter('**.*.js', {restore: true});
        var cssFilter = filter('**.*.css', {restore: true});
        var indexHtmlFilter = filter(['**.*', '!**/index.html'], {restore: true});
    
        //每一个pipe就相当于过滤器一样
        return gulp.src('src/index.html')
            .pipe(useref())
            .pipe(jsFilter)
            .pipe(uglify())
            .pipe(jsFilter.restore)
            .pipe(cssFilter)
            .pipe(csso())
            .pipe(cssFilter.restore)
            .pipe(indexHtmlFilter)
            .pipe(rev())
            .pipe(indexHtmlFilter.restore)
            .pipe(revReplace())
            .pipe(gulp.dest('dist'));
    });

        执行后的结果:


        就把所有需要打包的文件处理好了

        使用/*! */注释来注释就不会被打包掉(版本号之类的)

        还有一些有趣的插件:

    • gulp-watch:监听文件的变化自动给我们打包 ;网址:gulp-watch
    • gulp-postcss:通过多个插件来管理CSS,但只解析CSS一次。网址:gulp-postcss
    • gulp-concat :把所有的js文件合并成all.js文件。 网址:gulp-concat
    • gulp-responsive:可以把一个大图片直接生成一定规则的响应式图片。    网址:gulp-responsive

    补充--1选择一个趁手的IDE

        Webstorm:

    • 快速查找
    • 代码补全
    • 版本控制
    • 本地历史
    • 即时模板
    • 光标
    • 代码格式化

    对于文件的模板可以进行自定义设置(File ->setting ->file and Code Templates)

    查看本地历史,可以看我们修改的记录(在文件中右键-> Local History ->Show History)

    代码格式化(Code ->Reformat Code )

    快捷键设置(File -> Keymap-右栏)

    Webstorm进阶操作:


    Emmet:(文档地址:Emmet

    • 嵌套 (> , + , ^ , * , ()) 
    • 属性 (# .  , [] , $ , {}
    • 创作没有意义的文字    ( lorem )

        注意事项:一定要把光标定义到快速创建的代码最后面(如 ul>li>a,就要把光标放在a的后面);快速创建的代码中不要有空格

    展开全文
  • 响应式流(Reactive Streams)...JEP266中为Java语言的并发性又引入许多新的方式:响应式流,个为它而生互操作性更强的发布-订阅框架;并且为了Java9其他API而增强的 java.util.concurrent.CompletableFuture 类,

    为响应式流(Reactive Streams)增加的发布-订阅(publisher-subscriber)框架、并发包CompletableFuture类的增强,等等。。

    JEP266中为Java语言的并发性又引入许多新的方式:响应式流,一个为它而生互操作性更强的发布-订阅框架;并且为了Java9其他API而增强的 java.util.concurrent.CompletableFuture 类, 以及其他的更多的更新。

    在本文中,展开对响应式流的介绍,然后介绍这个发布订阅框架。

    响应式流(Reactive Streams)

    批处理系统在收集了足够多的数据,达到某一个阈值亟待进行下一步操作的时候,就衍生出了一个新的名词—数据处理(Data processing)。这时候,面向流(stream-oriented)的架构思想可以帮助我们尽快达成这个目标。它可以捕获和处理实时数据,并且可以快速地(秒级甚至更短)基于处理的结果来对系统进行相应的操作。和它相比,一个批处理系统可能会花费数秒、数天、甚至更久来做出响应。

    处理数据流(特别是大小不定的实时数据)需要在异步系统中特别小心。主要问题是要控制资源消耗,避免数据源和处理系统出现供大于求(积压)的情况。这时候,需要异步地来对数据进行并行处理,利用分布式系统或者发挥多核CPU的效能,能有效地使数据处理过程变得快速高效。

    响应式流(Reactive Streams)为这种非阻塞背压的异步流处理提供了一个标准。在处理系统出现过载的时候,采用异步发送信号的方式通知数据源做相应的处理。这个通知的信号就像是水管的阀门一样,关闭这个阀门会增加背压(数据源对处理系统的压力),同时也会增加处理系统的压力。

    这个标准的目的是治理跨异步边界的流数据交换(比如向其他线程传输数据) ,同时确保处理系统不被缓冲数据而压垮。换一种说法,背压是这个标准模型的一个组成部分,以便允许在线程之间调停的队列被界定。特别注意,背压通信是异步的。

    响应式流(Reactive Streams)的提出就致力于提供一组最小规模的接口、方法、或者协议来描述这个操作或实体:具有非阻塞背压的异步数据流。

    发布-订阅(publisher-subscriber)框架

    Java 9 通过java.util.concurrent.Flowjava.util.concurrent.SubmissionPublisher 类来实现响应式流。

    Flow 类中定义了四个嵌套的静态接口,用于建立流量控制的组件,发布者在其中生成一个或多个供订阅者使用的数据项:

    • Publisher:数据项发布者、生产者
    • Subscriber:数据项订阅者、消费者
    • Subscription:发布者与订阅者之间的关系纽带,订阅令牌
    • Processor:数据处理器

    发布者(Publisher)以流的方式发布数据项,并注册订阅者,并且实现 Flow.Publisher 接口,该接口声明了一个方法,我们通过调用它来为发布者注册订阅者:

    void subscribe(Flow.Subscriber<? super T> subscriber)

    调用此方法来向发布者注册订阅者,但是,如果此订阅者已被其他发布者注册或注册失败(策略冲突),这个方法就会调用订阅者的onError() 方法来抛出IllegalStateException 异常,除此之外,订阅者的onSubscribe() 方法会调用一个新的Flow.Subscription ,当空对象传给订阅者时,subscribe() 方法会抛出NullPointerException异常。

    订阅者(Subscriber)从订阅的发布者中返回数据项,并且实现Flow.Subscriber<T> ,这个接口声明的方法如下:

    void onSubscribe(Flow.Subscription subscription)
    void onComplete()
    void onError(Throwable throwable)
    void onNext(T item)

    onSubscribe() 方法用来确认订阅者注册到发布者是否注册成功,它以参数列表的方式接收一个Flow.Subscription类型的参数,而这个参数类型里面声明的方法允许向发布者请求发布新的数据项,或请求发布者不再发布更多的数据项。

    onComplete() 方法用在当订阅者没有调用其他方法,而Subscription 发生错误没有终止的情况下。调用这个方法之后,此订阅者就不能调用其他方法。

    onError(Throwable throwable) 方法用在当发布者或订阅者遭遇不可恢复的错误的时候, 调用这个方法之后,此订阅者也不能调用其他方法。

    onNext() 方法用于声明下一个数据项的订阅,如果在此过程中抛出异常,结果将得不到确认,甚至会导致订阅被取消。

    一个订阅令牌(Subscription)为发布者和订阅者定义一种关系, 使得订阅者接收特定的数据项或者在特定时间取消接收请求,订阅令牌实现自Flow.Subscription 接口,该接口声明方法如下:

    void request(long n)
    void cancel()

    request() 方法添加n个数据项到当前未满的订阅请求中。如果n小于或等于0,订阅者的onError() 方法会被调用,并且抛出IllegalArgumentException 异常,此外,如果n大于0,订阅者就会在onNext() 方法的调用下接收到n个数据项,除非中间异常终止。 从Long.MAX_VALUE次到n次中间是无界的调用。

    cancel() 用来终止订阅者接收数据项,它有一种尝试机制,也就是说,在调用它之后也有可能收到数据项。

    最后,数据处理器(Processor)在不改变发布者与订阅者的情况下基于流做数据处理,可以在发布者与订阅者之间放多个数据处理器,成为一个处理器链,发布者与订阅者不依赖于数据处理,它们是单独的过程。JDK9中不提供具体的数据处理器,必须由开发者来通过实现无方法声明的Processor接口来自行构建。

    SubmissionPublisher 实现自Flow.Publisher 接口,向当前订阅者异步提交非空的数据项,直到它被关闭。每个当前订阅者以一个相同的顺序接收新提交的数据项,除非数据项丢失或者遇到异常。SubmissionPublisher 允许数据项在丢失或阻塞的时候扮演发布者角色。

    SubmissionPublisher 提供了三个构造方法来获取实例。无参的构造器依赖于 ForkJoinPool.commonPool() 方法来提交发布者,以此实现生产者向订阅者提供数据项的异步特性。

    下面的程序演示了SubmissionPublisher 用法和这套发布-订阅框架的其他特性:

    import java.util.Arrays;
    
    import java.util.concurrent.Flow.*;
    import java.util.concurrent.SubmissionPublisher;  
    
    public class FlowDemo
    {
       public static void main(String[] args)
       {
          // Create a publisher.
    
          SubmissionPublisher<String> publisher = new SubmissionPublisher<>();
    
          // Create a subscriber and register it with the publisher.
    
          MySubscriber<String> subscriber = new MySubscriber<>();
          publisher.subscribe(subscriber);
    
          // Publish several data items and then close the publisher.
    
          System.out.println("Publishing data items...");
          String[] items = { "jan", "feb", "mar", "apr", "may", "jun",
                             "jul", "aug", "sep", "oct", "nov", "dec" };
          Arrays.asList(items).stream().forEach(i -> publisher.submit(i));
          publisher.close();
    
          try
          {
             synchronized("A")
             {
                "A".wait();
             }
          }
          catch (InterruptedException ie)
          {
          }
       }
    }
    
    class MySubscriber<T> implements Subscriber<T>
    {
       private Subscription subscription;
    
       @Override
       public void onSubscribe(Subscription subscription)
       {
          this.subscription = subscription;
          subscription.request(1);
       }
    
       @Override
       public void onNext(T item)
       {
          System.out.println("Received: " + item);
          subscription.request(1);
       }
    
       @Override
       public void onError(Throwable t)
       {
          t.printStackTrace();
          synchronized("A")
          {
             "A".notifyAll();
          }
       }
    
       @Override
       public void onComplete()
       {
          System.out.println("Done");
          synchronized("A")
          {
             "A".notifyAll();
          }
       }
    }

    其中使用了wait()notifyAll() 方法来使主线程等到onComplete() 的完成,否则是不会看到任何输出的。

    下面是输出结果:

    Publishing data items...
    Received: jan
    Received: feb
    Received: mar
    Received: apr
    Received: may
    Received: jun
    Received: jul
    Received: aug
    Received: sep
    Received: oct
    Received: nov
    Received: dec
    Done

    最后说一句,熟悉RxJava的同学可以会心一笑了。

    原文

    展开全文
  • 从 0 到 1,魅族网络架构经历了四个时代,也部署到...将全国响应速度控制到 30ms,网络架构改造演进过程中积累的经验和教训?基础网络的监控是每个团队关心问题,看魅族做了哪四大监控优化来解决基础网络可用性问题?

    2015 年 12 月 21 日魅族副总裁李楠在年度媒体沟通会公布 2015 年总销量突破 2000 万台,同比去年增长 350%,增长率全球手机品牌第一;

    2015 年 12 月 29 日魅族副总裁杨颜公布,2015 年魅族 Flyme 注册用户数突破 3000 万,应用商店现有超过 100 万款应用,总下载量超过 100 亿,营收能力同比增长 12 倍。

    在业绩出现爆发式增长的同时,数据中心基础资源也出现大规模扩张,目前的一些数据如下。



    网络设备数量:200+

    • 服务器数量:2000+

    • 虚拟子机数量:2500+

    • 互联网带宽:4G+

    • 专线带宽:400M+

    • CDN 带宽:100G+


    运维问题


    在传统手机制造业向互联网方向转型,以及业务爆发式增长,基础网络运维遇到过什么问题、困难呢?




    • 架构:网络架构脆弱,故障不定时爆发。比如单点架构:IDC 与办公共用办公网珠海总部节点为中心,当中心节点需维护或故障时,将影响 IDC 节点可用性;

    • 硬件:硬件性能瓶颈,高峰期 CPU 高达 99%。比如广域网采用低端路由器跑公网 DMVPN,采用 CPU 进行封装、转发,耗设备设能,在晚上高峰期 CPU 经常会高达 99%左右,产生丢包影响;

    • 监控:监控覆盖率低,故障无法跟踪定位。比如机房内、机房间、公网的质量情况;

    • 运营商:运营商复杂,公网质量无法保障。比如公网链路丢包;


        数据中心演进的 4 个时代


    一、练级阶段(2010-2013)


    1、 2010 - 2011:架构:外网 1.5 个机柜;业务:魅族官网、社区;人力:开发兼运维;


    2、2011 - 2012:架构:5 个机柜,二层级联、机架式单系统服务器;业务:魅族官网、社区、商城、Flyme 官网;人力:成立业务运维、DBA 运维;


    3、2012 - 2013

    架构:二层 STP 网络架构、IBM 刀箱 + EMC 存储 + VMWARE 虚拟化

    业务:魅族官网、社区、商城、Flyme 官网、云服务

    人力:业务运维、DBA 运维


    二、英勇黄铜(2013 年):网络架构 V1.0


    “英勇黄铜,金字塔的塔基,就是那种挖坑的存在。如果你掉进去了,想爬上来没有一定的实力真心不容易啊!”



    伴随着魅族官网、社区、商城、Flyme 官网、云服务的发展,业务驱动诞生了魅族网络架构 V1.0 版本,主要特点:


    网络架构:传统二层 STP 网络架构,链路资源利用率低、可靠性性低、维护成本大;

    硬件设备:性能和稳定性不足,核心设备经常会出现 CPU 负载过高导致重启。


    典型机房代表:广州亚太 IDC ,已于 2015 年 12 月完成了裁撤。


    三、不屈白银(2014 年):网络架构 V2.0


    “不屈白银,大多数玩家都处在这个位置当中。”

            

    伴随着应用中心、游戏中心、O2O、大数据、flyme 云服务、魅族云等发展,传统的网络架构已经无法支撑满足,业务驱动诞生了魅族网络架构 V2.0 版本。


    主要特点:


    1、网络架构:1)引入 10G 万兆大流量区;2)大二层虚拟化网络架构;3)内、外、管理流量混合;


    2、硬件设备:引入数据中心级高密交换机,稳定支撑承载互联网业务。典型机房代表:华南 IDC、华东 IDC。


    四、荣耀黄金(2015 年):网络架构 V3.0


    “联盟里的中端玩家。”

        

    伴随着互联网业务的爆发性发展,传统的“人肉运维模式”已经无法支撑千万级用户,于是标准化驱动诞生了魅族网络架构 V3.0 版本.


    什么叫标准化?举个简单例子:商鞅变法前,秦国各地度量衡不统一。为了保证国家的赋税收入,商鞅制造了标准的度量衡器,意义:全国上下有了标准的度量准则,为人们从事经济文化交流活动提供了便利的条件。


    我们是怎么做的呢?我们通过架构设计、网络设备选型、IP规划、网络连接规划、网络配置脚本等制订一套标准规范。


    3.0 版本网络架构除标准化外,其它主要特点:


    1)三网分离:

    a) 结构逻辑清晰;

    b) 安全分级:内外网物理隔离,提高内网的安全级别,降低安全风险;

    c) 提高网络可用性、吞吐能力;

    d) 管理网带外管理,提高运维排错能力。


    2)流量可视化:

    a) 外网流量特性固定,基本是直上直下的南北流量;

    b) 内网流量复杂,属于东西南北穿透。

    内外网流量分开便于网络流量管控可视化。


    3)单组 TOR 升级:一组 TOR 容量提升 50% 以上。原来 V2.0 一组接入层交换机仅能覆盖 2 个机架(24 台服务器),而 V3.0 版本一组接入层交换机可以覆盖 3 个机架(36 台服务器起)


    4)逻辑分区:普通区、LVS 区、大流量区、安全管控区。


    5)安全方面:

    a) DDOS 流量清洗购买了 BAT 的云盾(腾讯叫宙斯盾)服务;

    b) 自研 WAF 平台;

    c) 出口 ACL 白名单


    V3.0 网络架构版本另外一个突出特点是 LVS 引入了 FULLNAT 模式,逐步淘汰 DR 模式,从而提高了数据中心的扩展性、健壮性。


    五、华贵铂金(2016 年后):网络架构 V4.0


    测试及进行中,请留意进展。


    六、IDC 网络架构介绍


    前面所提到的都是单个 IDC 的网络架构,大家都还记得 2013 年 7 月及 2015 年 5 月一些同行的光纤被挖断故障?单机房会存在扩展难、无法容灾、无就近接入等问题。针对单机房问题,我们的应对措施:


    1. 制定运营商、代理商服务 SLA 协议标准,比如 99.9%;

    2. 多线 IDC + 分布式数据中心部署,提高业务部署冗余性,提高业务部署冗余性。


    接下来将分享我们的 IDC 网络架构:


    先简单概述我们多机房业务的部署,目前我们通过 GSLB 已经实现了用户就近接入,提高了用户体验,即华东片区用户访问华东 IDC,华南片区用户访问华南 IDC。 关于异地多活的方案,我们正在演练阶段,计划今年将会实现。


        

    下面看 IDC 基础网络架构,IDC 由专线平面 A 、VPN 平面 B 双平面组成 ,其中专线平面为主,VPN 平面为备,当专线平面瘫痪后,流量会自动切换到 VPN 平面上。



    我们先来看看 VPN 平面,节点之间是建立电信、联通链路两条 VPN,路由协议跑的是 IPSEC + EBGP,BGP 具有灵活、稳定的特点,设备选型是 FT 的 1000D,VPN 吞吐量高达 30Gbps 以上,可用性相比 2015 年之前,有了一定的提升。

                    

    备注:

    99.9%(月中断时长:43.2 分钟)

    99.92%(月中断时长:34.56 分钟)

    99.95%(月中断时长:21.6 分钟)

    我们做过相关的测试:当电信线路发生中断故障,中断 10 - 12S 路由切换到联通链路。


    由于运营商网络错综复杂万变,运营商经常凌晨会进行割接或者链路经常出现堵塞,造成广东片区访问北京、华东片区网络丢包等现象,随着互联网业务日益壮大,对网络质量要求越来越高,于是我们在今年 1 月份搭建了专线平面,把可用性提高到至 99.92% - 99.95%,华南、华东、华北互联,构成一个“三角形”环状,当其中一条链路出现故障,流量可以自动切换到第二条链路上。举两个例子:


    a)专线平面(A):环保护


    比如:华南 ⇒ 华东,当主链路 a 发生异常故障中断,秒级切换至 b,即华南 ⇒ 华北 ⇒ 华东


    b)VPN 平面(B):公网冗余保护


    比如:华南 ⇒ 华东,当专线同时发生异常故障中断,秒级切换至 B 平面,即华南 ⇒ 华东走 A 链路


        

    七、办公网与 IDC 解耦


    数据中心的大概分享到这里,接下来将简单介绍一下办公网以及跟数据中心的互联互访。


    曾经踩过的坑:2015 年 7 月珠海总部办公大楼掉电,影响中断华南 IDC—华东 IDC 机房间网络的通讯。


    办公网与 IDC 解耦,IDC ⇒ FW ⇒ OA:通过 OA 边界墙实现办公网与 IDC 的隔离,默认只放通运维相关的端口,策略申请需要安全部门评估审批。


    网络监控的 4 大优化


    面对千万级用户的异地多点网络架构,魅族的网络监控是怎么支撑的呢?


    监控痛点


    我们监控曾经遇到痛点:


    1. 监控系统可读性差;

    2. 监控项告警重叠;

    3. 告警无法定位问题;

    4. 业务产品带宽使用。


    监控架构总体视图


    先来看看监控总体视图:

        

    监控对象分三块:


    1、设备监控:设备可用性、状态监控、性能监控

    2、链路监控:公网质量、专线质量、VPN质量、流量情况

    3、架构监控:路由邻居变化、路由下一跳变化


    监控工具主要是:Zabbix、Cacti、NetFlow、SmokePing、基调、博睿


    一、监控模板标准化的优化


    优化前:


    监控配置人手一个标准,名称、参数,等一切变量都存在随心而定的情况,导致监控系统的可读性以及准确性存在严重的问题。

        

          监控模块标准化(前)


    优化后:


    对设备的监控配置进行了标准化,比如:什么类型的设备用什么样的监控模板,模板需要包含什么内容,甚至是模板的命名也进行了标准化


                 监控模块标准化(后)



    二、告警收敛的优化


    优化前:



    每日会收到超过 100 条的短信和邮件的告警,很多是一些没有实际意义的告警,严重的干扰了正常的工作,经过对告警信息的分析,主要存在几个问题:

    1、告警的准确性;

    2、重复告警;

    3、通知类告警太多。


    优化后:



    对告警阀值进行研究,细化,提高告警的准确性,并形成一套告警体系,对重复事件进行关联,通知类事件每天只进行一次邮件通知,极大的优化了监控告警,实现了当收到短信告警时,肯定是发生异常了。


    三、公网/专线线路质量监控优化


            公网线路质量监控


        

    优化前:


    我们 IDC 经过二级运营商接入至一级运营商的网络,专线网络也是同样的情况,当发生故障时,我们只知道整条访问路径有问题,但不知道故障具体发生在哪个节点


    优化后:


    为了解决这个问题,我们把接入运营商网络时经过的所有关键节点(二级运营商机房的边界、一级运营商网络边界)均纳入到我们的监控系统中,在我们的监控系统中可以非常直观的看到某个运营商整条访问路径的链路质量。


    对于专线网络也是同样的做法,我们联合线路供应商,在线路的关键节点上配置了监控地址,整体链路的质量情况也尽在掌握当中。


                专线线路质量监控

        


    四、带宽可视化的优化

        
    网络架构演进及实践17.jpg



    为什么要做这事?主要是基于成本方面考虑,另外对业务的带宽使用情况进行可视化,推动业务优化架构等。


    宽容量分配体系可视化,产出带宽产品维度的营收报表,实现按需分配带宽和专线资源,并量化监控。


    数据中心的未来


    上面提到了网络架构的四个时代,魅族数据中心未来应该如何设计?目前来看有以下几个挑战。


    一、多机房 IDC 布署规划


    1、国内:分布式


    现阶段国内我们在华南、华东、华北均已部署了我们自已的数据中心,从第三方网络质量监测报告显示:覆盖西南、西北片区的用户网络质量较差,延时高达 50-60ms 之间。基于用户访问体验的考虑,将全国用户的响应时间控制在 30ms 以下,是我们优化的目标之一,所以下一阶段我们将会结合业务覆盖用户情况考虑在西南、西北片区部署数据中心节点。


    另外一个驱动力是基于业务高可用,下一阶段我们会考虑核心机房同城双活。


    2、海外:全球化


    国内手机市场利润率逐年降低,国产手机强大后走出国门是必然趋势。业务发展驱动数据中心延伸至海外布局,目前我们海外已完成香港机房布署,下一阶段将会匹配海外业务市场发展情况,进行全球发展部署。


    二、SDN + 魅族云


    什么叫 SDN?软件定义网络,给我们会带来什么收益?


    1、IDC 流量智能调度


    现阶段我们 IDC 网络遇到如下挑战:


    1)数据中心间网络链路带宽资源有限,难以满足业务临时性的大容量传输需求,对重点业务流量的 QOS 保障需要较长的时间扩容满足,业务部分经常抱怨基础运维侧行动缓慢、缺乏灵活性、响应速度慢。


    2)IDC 冗余链路利用率低。


    为了更好地满足业务的带宽需求,提升专线利用率及降低运营复杂度,我们下一阶段将会逐步实践 IDC SDN 解决方案


    2、云计算网络:


    1)租户隔离;

    2)网络配置自动下发;

    3)云业务的快速更变;


    最后,简单介绍一下我们团队:5 人,主要负责魅族移动互联网数据中心基础网络架构规划、建设、优化、运营等。

    展开全文
  • 为什么响应式编程并非时之势?

    千次阅读 2016-06-08 11:33:17
    本文作者为 David Buschman,文章从程序架构与系统的发展历程出发,逐步论证了为什么响应式编程并非时之势,而是能带来更快处理速度,更高硬件利用率的未来选择。文章系国内 ITOM 管理平台 OneAPM 编译呈现。
  • 高级加密标准AES的实际应用

    万次阅读 2009-03-18 20:56:00
    高级加密标准AES的实际应用 作者:不赖猴 1. 什么是对称密钥加密?对称密钥加密又称单密钥加密,它是在非对称密钥加密(又称公钥加密)前使用的唯一的加密类型。它的加密和解密过程都使用同个密钥。 2. 对称...
  • 最大功率就是耳机允许输入的最大的信号功率,超过了就会烧坏耳机。 失真、或者总谐波失真(THD): 这个参数表示耳机输出的信号波形与输入的电信号的波形不...频响或者频率响应: 这个指标表示所指的耳机能够播放
  • http 响应头之location

    千次阅读 2018-11-15 05:23:47
    http 响应头之location
  • Linux 应急响应流程及实战演练

    千次阅读 2019-02-03 08:54:28
    当企业发生黑客入侵、系统崩溃或其它影响业务正常...针对常见的攻击事件,结合工作中应急响应事件分析和解决的方法,总结了一些 Linux 服务器入侵排查的思路。 0x01 入侵排查思路 、账号安全 基本使用: 1、用...
  • django框架——请求对象和响应对象

    千次阅读 2019-04-26 22:01:44
    Django会将这个对象自动传递给响应的视图函数,一般视图函数约定俗成地使用 request 参数承接这个对象。 request 参数承接这个对象。 、请求相关的常用值 path_info 返回用户访问url,不包括域名 method ...
  • RabbitMQ 的请求/响应模式

    千次阅读 2013-12-31 15:52:43
    如果客户端想发送一些信息给服务器,或者客户端按照某些标准请求一些信息,那么这种模式非常适合。如果服务器想自己发送信息给客户端,那么这种模式就非常不适合。这时我们就必须依赖像长轮询或者web挂钩这样的对...
  • 响应式编程之数据访问:ADBA与R2DBC

    千次阅读 2019-04-30 22:19:47
    JDBC具有阻塞性 - 没有什么可以减轻JDBC的阻塞性质,什么时候可以使用API​​进行响应性关系数据库集成?先用有Oracle宣布推出ADBA,再有在SpringOne平台华盛顿大会上宣布的 R2DBC,用于针对关系型数据库进行反应式...
  • 这是款非常实用的基于bootstrap 3的响应式jQuery滚动新闻插件。该bootstrap滚动新闻插件可以制作为自动向上或向下滚动的模式,可以带图片显示,界面设计时尚自然,非常适合于网站制作实时滚动新闻列表。 它的...
  • 十万到百万的服务,响应能达到tps50 /200ms就可以了 后台服务,能达到tps 20 / 200ms即可(通常后台同时使用也没多少人) 秒杀类的短时间高并发……TPS100或200 在 100ms内响应 应该也能撑段时间(具体情况还是...
  • EasyReact 是款基于响应式编程范式的客户端开发框架,开发者可以使用此框架轻松地解决客户端的异步问题。 目前 EasyReact 已在美团和大众点评客户端的部分业务中实践,并且持续迭代了一年多的时间。近日,我们...
  • 为什么要学习响应式设计

    千次阅读 2012-11-26 09:34:26
    随着iPad mini的发布,又个新的屏幕尺寸诞生了。用不着全面统计,你就会发现移动互联网时代众多的屏幕规格,从智能手机的3、4、5英寸,到平板电脑的7、8、9、10英寸,再到笔记本和台式机的13至30英寸,绝非目前...
  • 转载 ... Fiddler可以帮您记录,调试IE与Web应用程序的交互,找到Web程序运行性能的瓶颈, 还有如查看向Web服务器发送cookies的内容...说多一点是,Fiddler站在用户与Web服务器的中间,由它转发请求与响应,因此Fidd
  • 网络安全应急响应及其发展方向

    千次阅读 2007-03-11 17:07:00
    计算机信息系统和网络...自从CERT/CC成立以来,世界各地成立了各种类型的应急响应组,在我国应急响应也得到了各界的广泛关注。然而究竟什么是应急响应?它涉及到那些关键技术? 本文首先从三个方面讨论了应急响应
  • Scrapy-Request和Response(请求和响应

    万次阅读 2017-07-11 15:06:50
    请求和响应 Scrapy的Request和Response对象用于爬网网站。 通常,Request对象在爬虫程序中生成并传递到系统,直到它们到达下载程序,后者执行请求并返回个Response对象,该对象返回到发出请求的爬虫程序。 ...
  • 理解HTTP响应的ETag

    千次阅读 2010-08-25 16:27:00
    在使用 Google Page Analysis 和 YSlow 进行网页性能分析的时候,都会遇到 ...5. 服务器检查该Last-Modified或ETag,并判断出该页面自上次客户端请求之后还未被修改,直接返回响应304和个空的响应体。    
  • 首席安全官Plus是个围绕“大数据、云计算和人工智能”高技术领域,发布...随着网络安全攻防对抗的日趋激烈,网络安全单纯指望防范和阻止的策略已经失效,必须更加注重检测与响应。企业和组织要在网络已经遭受攻击...
  • SVG鼠标事件响应的四种写法

    万次阅读 2013-01-17 16:27:35
    SVG有四种常用的鼠标响应的脚本写法(SMIL方式、Attributes方式、JavaScript+SMIL方式、EventListener方式),根据不同的需要让大家有更多的选择。本文介绍了四种实现SVG鼠标事件的例子。 SVG鼠标事件实现方式的例子...
  • 只是简单的提示响应式设计拥有不错的UX和优越的性能,是移动设计方面的个不错的选择。 考虑到这一点,让我们起来测试一下“响应式设计”与“自适应设计”在性能和用户体验上各自的利弊。 自移动终端...
  • 标准Web系统的架构分层

    万次阅读 多人点赞 2015-06-22 10:30:36
    标准Web系统的架构分层 标准Web系统架构适用于传统的基于WEB浏览器/手机端的CRM系统、ERP系统、SaaS系统、O2O系统、商城系统、物流系统。架构的灵活性和业务适应性决定了不同的系统根据业务形态、访问量、安全性所...
  • css3 media响应式媒体查询器用法总结

    万次阅读 2016-04-02 00:49:30
    随着响应式设计模型的诞生,Web网站又要发生翻天腹地的改革浪潮,可能有些人会觉得在国内IE6用户居高不下的情况下,这些新的技术还不会广泛的蔓延下去,那你就错了,如今淘宝,凡客,携程等等公司都已经在大胆的尝试...
  • 透过宏定义了解MFC的消息响应机制

    千次阅读 2008-01-15 17:57:00
    消息系统是MFC的重要组成部分。MFC的消息响应机制并不复杂,而且MFC的开发环境 Visual Studio来供了非常好的自动化...当不小心的代码操作使自动化工具不好用的时候,看着那组更像是堆的宏,很多人只好一头雾水。
  • JSP学习笔记——HTTP请求和响应

    千次阅读 2014-12-31 10:37:50
    个应用程序的基于TCP / IP协议,分布式,协作,超媒体信息系统(互联网)。http有两个特点,无状态和短连接,短连接是指Web浏览器和Web服务器之间不需要建立持久的连接,这意味着当个客户端向服务器端发出
  • P2P通信标准协议()之STUN

    千次阅读 2016-11-16 11:04:59
    段时间在P2P通信原理与实现中介绍了P2P打洞的基本原理和方法,我们可以根据其原理为自己的网络程序设计一套通信规则, 当然如果这套程序只有自己在使用是没什么问题的。可是在现实生活中,我们的程序往往还需要...
  • 使用openresty通过lua修改请求/响应

    千次阅读 2020-04-15 15:58:08
    } header_filter_by_lua_block语法 header_filter_by_lua_block {lus-script} header_filter_by_lua_file语法 header_filter_by_lua_file body_filter_by_lua 用法 执行Lua脚本修改每个请求的响应body信息 语法 ...
  • 软件测试上线标准

    千次阅读 2017-02-13 10:07:59
    、编写目的  明确软件测试工作的开始和结束标准。 二、软件测试合格标准    以上比例为错误占总测试模块的比例。 三、缺陷修复率标准  1) A、B、C错误修复率应达到100%(C类错误允许存在  2) D错误修复...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 230,539
精华内容 92,215
关键字:

一级响应标准