精华内容
下载资源
问答
  • thinkphp控制变量在模板中显示

    千次阅读 2016-06-17 09:07:49
    控制器中变量 public function register() { $type = I("param.type");//1.学生注册 2.教师注册 3.其他注册 $this -> assign("type", $type); //q全部部门 $depart1 = M("Depart") -> where("status=1 and fid

    控制器中变量

    public function register() {
        $type = I("param.type");//1.学生注册 2.教师注册  3.其他注册
        $this -> assign("type", $type);     
           //q全部部门
        $depart1 = M("Depart") -> where("status=1 and fid=0") -> order("id asc") -> select();
        $this -> assign("depart1", $depart1);
        $this -> display();
    }
    模板中引用位置一:php代码中,直接用$i;
    <php> 
    
        echo $i;
    </php
    模板中引用位置二:模板中直接应用{$i}或者 class="{$unlogined}"
    <font color="red">注意:1.非相关人员,严禁注册。{$i}</font><br>
    
    
    <php>
        $logined = is_array($_SESSION['userInfo']) ? "" : "hide-div";
        $unlogined = $logined == "hide-div" ? "" : "hide-div";
    </php>
    <div id="unlogined-div" class="{$unlogined}">

    模板中引用位置三:模板标签中用,如condition中用,不加{}。
    <if condition="$type neq 4">
        <div class="form-group">
            <label for="" class="control-label col-sm-3">一级部门: <span class="text-danger">*</span></label>
            <div class="col-sm-9">
                <select name="depart1_id" id="depart1_id"  οnchange="depart1change()" class="form-control input-sm">
                    <option value="-1">-----请选择一级部门-----</option>
                    <foreach name="depart1" item="vo">
                        <option value="{$vo.id}">{$vo.name}</option>
                    </foreach>
                </select>
            </div>
        </div>
        <div class="form-group">
            <label for="" class="control-label col-sm-3">二级部门: <span class="text-danger">*</span></label>
            <div class="col-sm-9">
                <select name="depart2_id" id="depart2_id" οnchange="depart2change()" class="form-control input-sm">
                    <option selected='selected'>-----请先选择一级部门-----</option>
                </select>
            </div>
        </div>
        <div class="form-group">
            <label for="" class="control-label col-sm-3">三级部门: <span class="text-danger">*</span></label>
            <div class="col-sm-9">
                <select name="depart3_id" id="depart3_id" class="form-control input-sm">
                    <option selected='selected'>-----请先选择二级部门-----</option>
                </select>
            </div>
        </div>
    </if>


    
    

    展开全文
  • # 然后浏览器访问测试 17、nginx 流量控制 求的数量。请求,可以是一个简单网站首页的GET请求,也可以是登录表单的 POST 请求。流量限制可以用作安全目的,比如可以减慢暴力密码破解的速率。通过将传入请求的速率...

    16、nginx 错误页面配置

    nginx错误页面包括404 403 500 502 503 504等页面,只需要在server中增加以下配置即可:

        error_page  404 403 500 502 503 504  /404.html;
                    location = /404.html {
                            root   /usr/local/nginx/html;
                    }
    

    注意:

    /usr/local/nginx/html/ 路径下必须有404.html这个文件!!!

    404.html上如果引用其他文件的png或css就会有问题,显示不出来,因为其他文件的访问也要做配置;
    为了简单,可以将css嵌入文件中,图片用base编码嵌入;如下:

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8" />
            <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
            <title>404</title>
            <style>
                .layout-table{display:table;height:100%;width:100%;vertical-align: middle;margin-top:150px}
                .layout-table-cell{display: table-cell;vertical-align: middle;text-align:center}
                .layout-tip{font-size:28px;color:#373737;margin: 0 auto;margin-top:16px;border-bottom: 1px solid #eee;padding-bottom: 20px;width: 360px;}
                #tips{font-size:18px;color:#666666;margin-top:16px;}
            </style>
        </head>
        <body class="layui-layout-body">
            <div class="layui-layout layui-layout-admin">
                
                <div class="layui-body">
                    <div class="layout-table">
                        <div class="layout-table-cell">
                            <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAV4AAACMCAYAAAA0qsGKAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkIwRDQ0ODRFMzMyODExRThBQ0Q5Q0UyNkNCMkE4MDk0IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkIwRDQ0ODRGMzMyODExRThBQ0Q5Q0UyNkNCMkE4MDk0Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QjBENDQ4NEMzMzI4MTFFOEFDRDlDRTI2Q0IyQTgwOTQiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QjBENDQ4NEQzMzI4MTFFOEFDRDlDRTI2Q0IyQTgwOTQiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4Qz6opAAAU5klEQVR42uxd3XXjthKe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" class="layout-img">
                            <p class="layout-tip">哎呀,找不到该页面啦!</p>
                            <p id="tips">请检查您的网络连接是否正常或者输入的网址是否正确</p>
                        </div>
                    </div>
                </div>
            </div>
            
        </body>
    </html>
    

    ** 展示效果:**
    在这里插入图片描述

    过程演示:

    [root@tnt-1 ~]# vim /etc/nginx/nginx.conf
    
    #        error_page   500 502 503 504  /50x.html;
    #        location = /50x.html {
    #            root   html;
    #        }
    #
    		 error_page 402 403 404 500 502 503 504 /404.html;
            location = /404.html {
            root /usr/local/nginx/html;
            }
    
    
    
    #进主配置文件,找到原先默认的错误页面配置内容,注释掉或者修改掉.
    #加入新的配置内容.写好路径.内容意思是只要出现402 403 500 502 503 504这些代码的,就会返回/404.html页面,并且去root /usr/local/nginx/html这个位置里面找这个页面.
    
    
    [root@tnt-1 ~]# vim /usr/local/nginx/html/404.html
    
    [root@tnt-1 ~]# nginx -t
    nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    nginx: configuration file /etc/nginx/nginx.conf test is successful
    
    [root@tnt-1 ~]# nginx -s reload
    
    # 然后自己定义的路径里创建一个404的页面.
    # 页面代码上面有一个,复制粘贴就可以.
    # 在vim创建的时候要用这个,因为这个页面代码内容特殊,可以预防复制粘贴不一致.
    # :set paste 回车 然后按A 插入 
    # 然后查看配置文件代码是否正常.
    # 重新加载配置文件.
    # 然后浏览器访问测试
    

    在这里插入图片描述

    17、nginx 流量控制

    求的数量。请求,可以是一个简单网站首页的GET请求,也可以是登录表单的 POST 请求。流量限制可以用作安全目的,比如可以减慢暴力密码破解的速率。通过将传入请求的速率限制为真实用户的典型值,并标识目标URL地址(通过日志),还可以用来抵御 DDOS 攻击。更常见的情况,该功能被用来保护上游应用服务器不被同时太多用户请求所压垮。

    以下将会介绍Nginx的 流量限制 的基础知识和高级配置,”流量限制”在Nginx Plus中也适用。

    1、Nginx如何限流

    Nginx的”流量限制”使用漏桶算法(leaky bucket algorithm),该算法在通讯和分组交换计算机网络中广泛使用,用以处理带宽有限时的突发情况。就好比,一个桶口在倒水,桶底在漏水的水桶。如果桶口倒水的速率大于桶底的漏水速率,桶里面的水将会溢出;同样,在请求处理方面,水代表来自客户端的请求,水桶代表根据”先进先出调度算法”(FIFO)等待被处理的请求队列,桶底漏出的水代表离开缓冲区被服务器处理的请求,桶口溢出的水代表被丢弃和不被处理的请求。

    2、配置基本的限流

    “流量限制”配置两个主要的指令,limit_req_zonelimit_req,如下所示:

    limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
    server {
    	location /login/ {
    		limit_req zone=mylimit;
    
    		proxy_pass http://my_upstream;
    	}
    }
    

    limit_req_zone指令定义了流量限制相关的参数,而limit_req指令在出现的上下文中启用流量限制(示例中,对于”/login/”的所有请求)。

    limit_req_zone指令通常在HTTP块中定义,使其可在多个上下文中使用,它需要以下三个参数:

    • Key - 定义应用限制的请求特性。示例中的 Nginx 变量$binary_remote_addr,保存客户端IP地址的二进制形式。这意味着,我们可以将每个不同的IP地址限制到,通过第三个参数设置的请求速率。(使用该变量是因为比字符串形式的客户端IP地址$remote_addr,占用更少的空间)
    • Zone - 定义用于存储每个IP地址状态以及被限制请求URL访问频率的共享内存区域。保存在内存共享区域的信息,意味着可以在Nginx的worker进程之间共享。定义分为两个部分:通过zone=keyword标识区域的名字,以及冒号后面跟区域大小。16000个IP地址的状态信息,大约需要1MB,所以示例中区域可以存储160000个IP地址。
    • Rate - 定义最大请求速率。在示例中,速率不能超过每秒10个请求。Nginx实际上以毫秒的粒度来跟踪请求,所以速率限制相当于每100毫秒1个请求。因为不允许”突发情况”(见下一章节),这意味着在前一个请求100毫秒内到达的请求将被拒绝。

    当Nginx需要添加新条目时存储空间不足,将会删除旧条目。如果释放的空间仍不够容纳新记录,Nginx将会返回 503状态码(Service Temporarily Unavailable)。另外,为了防止内存被耗尽,Nginx每次创建新条目时,最多删除两条60秒内未使用的条目。

    limit_req_zone指令设置流量限制和共享内存区域的参数,但实际上并不限制请求速率。所以需要通过添加

    limit_req指令,将流量限制应用在特定的location或者server块。在上面示例中,我们对/login/请求进行流量限制。

    现在每个IP地址被限制为每秒只能请求10次/login/,更准确地说,在前一个请求的100毫秒内不能请求该URL。

    过程演示

    [root@tnt-1 ~]# vim /etc/nginx/nginx.conf
     limit_req_zone $binary_remote_addr zone=mylimit:10m rate=1r/s;
    
            location / {
                root   html;
                index  index.html index.htm;
                limit_req zone=mylimit;
            }
    
    
    
    #打开配置文件
    #定义加入一个模块用来做限制.
    #模块意思是,$binary_remote_addr zone 用二进制的方式去记录客户端的IP地址,并且定义一个名字叫做mylimit的地址用来存储所有来访问的客户端的IP地址,最后限制每个IP地址rate=1r/s,允许1秒钟不超过1个请求.内存共享区大小是10m.
    #这个模块要写在server级别之外.为了便于测试,我们把rate=1r/s改成1秒1次.
    #然后再在你需要引用这个模块的地方加上limit_req zone=mylimit;
    #相当于先定义变量,然后引用变量.
    
    
    [root@tnt-1 ~]# nginx -t
    nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    nginx: configuration file /etc/nginx/nginx.conf test is successful
    
    [root@tnt-1 ~]# nginx -s reload
    
    #测试配置文件
    #重新加载
    
    
    [root@tnt-2 ~]# curl -I http://120.25.2xx.2xx
    HTTP/1.1 200 OK
    Server: nginx/1.14.2
    Date: Tue, 09 Jun 2020 09:20:41 GMT
    Content-Type: text/html
    Content-Length: 612
    Last-Modified: Mon, 01 Jun 2020 17:17:58 GMT
    Connection: keep-alive
    ETag: "5ed53846-264"
    Accept-Ranges: bytes
    
    [root@tnt-2 ~]# curl -I http://120.25.2xx.2xx
    HTTP/1.1 503 Service Temporarily Unavailable
    Server: nginx/1.14.2
    Date: Tue, 09 Jun 2020 09:20:41 GMT
    Content-Type: text/html
    Content-Length: 9616
    Connection: keep-alive
    ETag: "5edf30fe-2590"
    
    #然后浏览器或者curl测试.会发现第一次访问正常,快速访问的话就会被限制了.
    #换一台服务器进行curl
    

    3、处理突发

    如果我们在100毫秒内接收到2个请求,怎么办?对于第二个请求,Nginx将给客户端返回状态码503。这可能并不是我们想要的结果,因为应用本质上趋向于突发性。相反地,我们希望缓冲任何超额的请求,然后及时地处理它们。我们更新下配置,在limit_req中使用burst参数:

    location /login/ {
    	limit_req zone=mylimit burst=20;
    	proxy_pass http://my_upstream;
    }
    

    burst参数定义了超出zone指定速率的情况下(示例中的mylimit区域,速率限制在每秒10个请求,或每100毫秒一个请求),客户端还能发起多少请求。上一个请求100毫秒内到达的请求将会被放入队列,我们将队列大小设置为20。

    这意味着,如果从一个给定IP地址发送21个请求,Nginx会立即将第一个请求发送到上游服务器群,然后将余下20个请求放在队列中。然后每100毫秒转发一个排队的请求,只有当传入请求使队列中排队的请求数超过20时,Nginx才会向客户端返回503。

    过程演示

    [root@tnt-1 ~]# vim /etc/nginx/nginx.conf
     location / {
                root   html;
                index  index.html index.htm;
                limit_req zone=mylimit burst=20;
            }
    
    #打开配置文件.
    #加上一个参数burst=20.
    #这个参数理解为用来定义如果一定时间内超过了之前定义的速率1r/s以外的请求,会让第一个请求以外的其它请求去排队.超过了20个,才会丢弃掉返回503报错.就是最多让20个请求进行排队,最大延迟请求数量不大于20,在等待处理.
    
    [root@tnt-1 ~]# nginx -t
    nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    nginx: configuration file /etc/nginx/nginx.conf test is successful
    
    [root@tnt-1 ~]# nginx -s reload
    
    #测配置文件.
    #重新加载.
    #然后测试
    

    和上面一个测试例子对比,这里快速访问两次的话不会返回503.会发现会有一个稍微的卡顿,这里就可以理解为第二个请求在排队.最后返回的还是200.
    在这里插入图片描述

    4、无延迟的排队

    配置burst参数将会使通讯更流畅,但是可能会不太实用,因为该配置会使站点看起来很慢。在上面的示例中,队列中的第20个包需要等待2秒才能被转发,此时返回给客户端的响应可能不再有用。要解决这个情况,可以在burst参数后添加nodelay参数:

    location /login/ {
    	limit_req zone=mylimit burst=20 nodelay;
    
    	proxy_pass http://my_upstream;
    }
    

    使用nodelay参数,Nginx仍将根据burst参数分配队列中的位置,并应用已配置的速率限制,而不是清理队列中等待转发的请求。相反地,当一个请求到达“太早”时,只要在队列中能分配位置,Nginx将立即转发这个请求。将队列中的该位置标记为”taken”(占据),并且不会被释放以供另一个请求使用,直到一段时间后才会被释放(在这个示例中是,100毫秒后)。

    假设如前所述,队列中有20个空位,从给定的IP地址发出的21个请求同时到达。Nginx会立即转发这个21个请求,并且标记队列中占据的20个位置,然后每100毫秒释放一个位置。如果是25个请求同时到达,Nginx将会立即转发其中的21个请求,标记队列中占据的20个位置,并且返回503状态码来拒绝剩下的4个请求。

    现在假设,第一组请求被转发后101毫秒,另20个请求同时到达。队列中只会有一个位置被释放,所以Nginx转发一个请求并返回503状态码来拒绝其他19个请求。如果在20个新请求到达之前已经过去了501毫秒,5个位置被释放,所以Nginx立即转发5个请求并拒绝另外15个。

    效果相当于每秒10个请求的“流量限制”。如果希望不限制两个请求间允许间隔的情况下实施“流量限制”,nodelay参数是很实用的。

    注意: 对于大部分部署,我们建议使用burstnodelay参数来配置limit_req指令。

    5、高级配置示例

    通过将基本的“流量限制”与其他Nginx功能配合使用,我们可以实现更细粒度的流量限制。

    1、白名单

    下面这个例子将展示,如何对任何不在白名单内的请求强制执行“流量限制”:

    geo $limit {
    	default 		1;
    	10.0.0.0/8 		0;
    	192.168.0.0/64 	0;
    }
    
    map $limit $limit_key {
    	0 "";
    	1 $binary_remote_addr;
    }
    
    limit_req_zone $limit_key zone=req_zone:10m rate=5r/s;
    
    server {
    	location / {
    		limit_req zone=req_zone burst=10 nodelay;
    
    		# ...
    	}
    }
    

    这个例子同时使用了geomap指令。geo块将给在白名单中的IP地址对应的$limit变量分配一个值0,给其它不在白名单中的分配一个值1。然后我们使用一个映射将这些值转为key,如下:

    • 如果$limit变量的值是0,$limit_key变量将被赋值为空字符串
    • 如果$limit变量的值是1,$limit_key变量将被赋值为客户端二进制形式的IP地址

    两个指令配合使用,白名单内IP地址的$limit_key变量被赋值为空字符串,不在白名单内的被赋值为客户端的IP地址。当limit_req_zone后的第一个参数是空字符串时,不会应用“流量限制”,所以白名单内的IP地址(10.0.0.0/8和192.168.0.0/24 网段内)不会被限制。其它所有IP地址都会被限制到每秒5个请求。

    limit_req指令将限制应用到**/**的location块,允许在配置的限制上最多超过10个数据包的突发,并且不会延迟转发。

    2、location 包含多limit_req指令

    我们可以在一个location块中配置多个limit_req指令。符合给定请求的所有限制都被应用时,意味着将采用最严格的那个限制。例如,多个指令都制定了延迟,将采用最长的那个延迟。同样,请求受部分指令影响被拒绝,即使其他指令允许通过也无济于事。

    扩展前面将“流量限制”应用到白名单内IP地址的例子:

    http {
    	# ...
    
    	limit_req_zone $limit_key zone=req_zone:10m rate=5r/s;
    	limit_req_zone $binary_remote_addr zone=req_zone_wl:10m rate=15r/s;
    
    	server {
    		# ...
    		location / {
    			limit_req zone=req_zone burst=10 nodelay;
    			limit_req zone=req_zone_wl burst=20 nodelay;
    			# ...
    		}
    	}
    }
    

    白名单内的IP地址不会匹配到第一个“流量限制”,而是会匹配到第二个req_zone_wl,并且被限制到每秒15个请求。不在白名单内的IP地址两个限制能匹配到,所以应用限制更强的那个:每秒5个请求。

    6、配置流量控制相关功能

    1、配置日志记录

    默认情况下,Nginx会在日志中记录由于流量限制而延迟或丢弃的请求,如下所示:

    2019/02/13 04:20:00 [error] 120315#0: *32086 limiting requests, excess: 1.000 by zone "mylimit", client: 192.168.1.2, server: nginx.com, request: "GET / HTTP/1.0", host: "nginx.com"
    

    日志条目中包含的字段:

    • limiting requests - 表明日志条目记录的是被“流量限制”请求
    • excess - 每毫秒超过对应“流量限制”配置的请求数量
    • zone - 定义实施“流量限制”的区域
    • client - 发起请求的客户端IP地址
    • server - 服务器IP地址或主机名
    • request - 客户端发起的实际HTTP请求
    • host - HTTP报头中host的值

    默认情况下,Nginx以error级别来记录被拒绝的请求,如上面示例中的[error]所示(Ngin以较低级别记录延时请求,一般是info级别)。如要更改Nginx的日志记录级别,需要使用limit_req_log_level指令。这里,我们将被拒绝请求的日志记录级别设置为warn

    location /login/ {
    	limit_req zone=mylimit burst=20 nodelay;
    	limit_req_log_level warn;
    	
    	proxy_pass http://my_upstream;
    } 
    

    2、发送到客户端的错误代码

    一般情况下,客户端超过配置的流量限制时,Nginx响应状态码为503(Service Temporarily Unavailable)。可以使用limit_req_status指令来设置为其它状态码(例如下面的444状态码):

    location /login/ {
    	limit_req zone=mylimit burst=20 nodelay;
    	limit_req_status 444;
    }
    

    3、指定location拒绝所有请求

    如果你想拒绝某个指定URL地址的所有请求,而不是仅仅对其限速,只需要在location块中配置deny all指令:

    location /foo.php {
    	deny all;
    }
    

    7、nginx 流量控制总结

    以上已经涵盖了Nginx和Nginx Plus提供的“流量限制”的很多功能,包括为HTTP请求的不同loation设置请求速率,给“流量限制”配置burstnodelay参数。还涵盖了针对客户端IP地址的白名单和黑名单应用不同“流量限制”的高级配置,阐述了如何去日志记录被拒绝和延时的请求。

    18、nginx 访问控制

    1、nginx 访问控制模块

    (1)基于IP的访问控制:http_access_module
    (2)基于用户的信任登录:http_auth_basic_module

    2、基于IP的访问控制

    1、配置语法

    Syntax:allow address | CIDR | unix: | all;
    default:默认无
    Context:http,server,location,limit_except
    
    Syntax:deny address | CIDR | unix: | all;
    default:默认无
    Context:http,server,location,limit_except
    

    2、配置测试

    修改/etc/nginx/conf.d/access_mod.conf内容如下:

     location ~ ^/admin.html {
            root   /opt/app/code;
    		deny 192.168.174.1;
    		allow all;
            index  index.html index.htm;
        }
    

    虚拟机宿主机IP为192.168.174.1,虚拟机IP为192.168.174.132,故这里禁止宿主机访问,允许其他所有IP访问。
    宿主机访问http://192.168.174.132/admin.html,显示403 Forbidden
    当然也可以反向配置,同时也可以使用IP网段的配置方式,如allow 192.168.174.0/24;,表示满足此网段的IP都可以访问。

    3、局限性

    remote_addr只能记录上一层与服务器直接建立连接的IP地址,若中间有代理,则记录的是代理的IP地址。
    http_x_forwarded_for可以记录每一层级的IP。
    在这里插入图片描述

    4、解决方法

    (1)采用别的HTTP头信息控制访问,如HTTP_X_FORWARD_FOR(无法避免被改写)
    (2)结合geo模块
    (3)通过HTTP自定义变量传递

    3、基于用户的信任登录

    1、配置语法

    Syntax:auth_basic string | off;
    default:auth_basic off;
    Context:http,server,location,limit_except
    
    Syntax:auth_basic_user_file file;
    default:默认无
    Context:http,server,location,limit_except
    file:存储用户名密码信息的文件。
    

    2、配置示例

    改名access_mod.confauth_mod.conf,内容如下:

     location ~ ^/admin.html {
            root   /opt/app/code;
            auth_basic "Auth access test!";
            auth_basic_user_file /etc/nginx/auth_conf;
            index  index.html index.htm;
        }
    

    auth_basic不为off,开启登录验证功能,auth_basic_user_file加载账号密码文件。

    3、建立口令文件

    [root@web ~]# htpasswd -cm /etc/nginx/auth_conf user10
    [root@web ~]# htpasswd -m /etc/nginx/auth_conf user20
    [root@web ~]# cat /etc/nginx/auth_conf 
    user10:$apr1$Cw6eF/..$MNBh6rvkvsfH9gDZ/kEhg/
    user20:$apr1$tb6B8...$y28sfvudhfb4V8xPlvvi//
    

    4、访问测试

    在这里插入图片描述

    5、局限性

    (1)用户信息依赖文件方式
    (2)操作管理机械,效率低下

    6、解决方法

    (1)Nginx结合LUA实现高效验证
    (2)Nginx和LDAP打通,利用nginx-auth-ldap模块
    (3)Nginx只做中间代理,具体认证交给应用。

    19、nginx 变量(了解)

    Nginx 同 Apache 和 Lighttpd 等其他 Web 服务器的配置记法不太相同,Nginx的配置文件使用语法的就是一门微型的编程语言。可以类似写程序一般编写配置文件,可操作性很大。既然是编程语言,一般也就少不了“变量”这种东西。

    1、nginx变量简介

    • 所有的 Nginx变量在 Nginx 配置文件中引用时都须带上 $ 前缀

    • 在 Nginx 配置中,变量只能存放一种类型的值,有且也只存在一种类型,那就是字符串类型

    • nginx可以使用变量简化配置与提高配置的灵活性,所有的变量值都可以通过这种方式引用:

    $变量名
    

    2、nginx 变量的定义和使用

    nginx中的变量分为两种,自定义变量与内置预定义变量

    1、自定义变量

    1、声明变量

    可以在sever,http,location等标签中使用set命令(非唯一)声明变量,语法如下

    set $变量名 变量值
    

    注意:

    • nginx 中的变量必须都以$开头

    • nginx 的配置文件中所有使用的变量都必须是声明过的,否则 nginx 会无法启动并打印相关异常日志

    2、变量的可见性

    nginx 变量的一个有趣的特性就是nginx中没一个变量都是全局可见的,而他们又不是全局变量。如下例子

    location a/ {
      return 200 $a
    }
    
    location b/ {
     set $a hello nginx
     return 200 $a
    }
    

    由于变量是全局可见的所以nginx启动不会报错,而第一个location中并不知道$a的具体值因此返回的响应结果为一个空字符串。

    在不同层级的标签中声明的变量性的可见性规则如下:

    • location标签中声明的变量中对这个location块可见

    • server标签中声明的变量对server块以及server块中的所有子块可见

    • http标签中声明的变量对http块以及http块中的所有子块可见

    3、配置 $foo=hello

    server {
        listen 8080;
        server_name  localhost;
        
        location /test {
                set $foo hello;
                echo "foo: $foo";
        }
    }
    

    输出

    [root@localhost html]# nginx -s reload
    [root@localhost html]# curl localhost/test
    foo:  hello
    

    4、 输出 $ 符

    如果我们想通过 echo 指令直接输出含有“美元符”($)的字符串,那么有没有办法把特殊的 $ 字符给转义掉呢?答案是否定的。不过幸运的是,我们可以绕过这个限制,比如通过不支持“变量插值”的模块配置指令专门构造出取值为 $ 的 Nginx 变量,然后再在 echo 中使用这个变量。看下面这个例子:

    http {
        ...
        geo $dollar {
            default "$";
        }
        server {
            ...
           
            location /test-dollar {
                echo "This is a dollar sign: $dollar";
            }
        }
    }
    

    输出

    [root@localhost html]# nginx -s reload
    [root@localhost html]# curl localhost/test-dollar
    This is a dollar sign: \$
    

    这里用到了标准模块 ngx_geo 提供的配置指令 geo 来为变量 $dollar 赋予字符串 “$”,这样我们在下面需要使用美元符的地方,就直接引用我们的 $dollar 变量就可以了。

    5、 使用大括号插值

    在“变量插值”的上下文中,还有一种特殊情况,即当引用的变量名之后紧跟着变量名的构成字符时(比如后跟字母、数字以及下划线),我们就需要使用特别的记法来消除歧义,例如:

    server {
        ...
        location /test-brace {
            set $first "hello ";
            echo "${first}world";
        }
    }
    

    输出

    [root@localhost html]# nginx -s reload
    [root@localhost html]# curl localhost/test-brace
    hello world
    

    这里,我们在 echo 配置指令的参数值中引用变量 first 的时候,后面紧跟着 world 这个单词,所以如果直接写作 “firstworld” 则 Nginx “变量插值”计算引擎会将之识别为引用了变量 firstworld. 为了解决这个难题,Nginx 的字符串记法支持使用花括号在 之后把变量名围起来,比如这里的 ${first}。

    6、变量作用域

    set 指令(以及前面提到的 geo 指令)不仅有赋值的功能,它还有创建 Nginx 变量的副作用,即当作为赋值对象的变量尚不存在时,它会自动创建该变量。比如在上面这个例子中,如果 $a 这个变量尚未创建,则 set 指令会自动创建 $a 这个用户变量。如果我们不创建就直接使用它的值,则会报错。

    例如

    server {
        ...
        location /bad {
            echo $foo;
        }
    }
    

    此时 Nginx 服务器会拒绝加载配置:

    [emerg] unknown "foo" variable
    

    Nginx 变量的创建和赋值操作发生在全然不同的时间阶段,Nginx 变量的创建只能发生在 Nginx 配置加载的时候,或者说 Nginx 启动的时候,而赋值操作则只会发生在请求实际处理的时候。
    这意味着不创建而直接使用变量会导致启动失败,同时也意味着我们无法在请求处理时动态地创建新的 Nginx 变量。

    Nginx 变量一旦创建,其变量名的可见范围就是整个 Nginx 配置,甚至可以跨越不同虚拟主机的 server 配置块。我们来看一个例子:

    server {
        listen 8080;
        
        location /foo {
            echo "foo = [$foo]";
        }
        
        location /bar {
            set $foo 32;
            echo "foo = [$foo]";
        }
    }
    

    输出

    [root@localhost html]# curl 'http://localhost/foo'
    foo = []
    
    [root@localhost html]# curl 'http://localhost/bar'
    foo = [32]
    
    [root@localhost html]# curl 'http://localhost/foo'
    foo = []
    

    这里我们在 location /bar 中用 set 指令创建了变量 foo,于是在整个配置文件中这个变量都是可见的,因此我们可以在 location /foo 中直接引用这个变量而不用担心 Nginx 会报错。
    从这个例子我们可以看到,set 指令因为是在 location /bar 中使用的,所以赋值操作只会在访问 /bar 的请求中执行。而请求 /foo 接口时,我们总是得到空的 foo值,因为用户变量未赋值就输出的话,得到的便是空字符串。

    从这个例子我们可以窥见的另一个重要特性是,Nginx 变量名的可见范围虽然是整个配置,但每个请求都有所有变量的独立副本,或者说都有各变量用来存放值的容器的独立副本,彼此互不干扰。比如前面我们请求了 /bar 接口后,foo 变量被赋予了值 32,但它丝毫不会影响后续对 /foo 接口的请求所对应的 foo 值(它仍然是空的!),因为各个请求都有自己独立的 $foo 变量的副本。

    对于 Nginx 新手来说,最常见的错误之一,就是将 Nginx 变量理解成某种在请求之间全局共享的东西,或者说“全局变量”。而事实上,Nginx 变量的生命期是不可能跨越请求边界的。

    关于 Nginx 变量的另一个常见误区是认为变量容器的生命期,是与 location 配置块绑定的。其实不然。我们来看一个涉及“内部跳转”的例子:

    server {
        listen 8080;
    
        location /foo {
            set $a hello;
            echo_exec /bar;
        }
    
        location /bar {
            echo "a = [$a]";
        }
    }
    

    输出

    [root@localhost html]# curl localhost/foo
    a = [hello]
    

    这 里我们在 location /foo 中,使用第三方模块 ngx_echo 提供的 echo_exec 配置指令,发起到 location /bar 的“内部跳转”。所谓“内部跳转”,就是在处理请求的过程中,于服务器内部,从一个 location 跳转到另一个 location 的过程。这不同于利用 HTTP 状态码 301 和 302 所进行的“外部跳转”,因为后者是由 HTTP 客户端配合进行跳转的,而且在客户端,用户可以通过浏览器地址栏这样的界面,看到请求的 URL 地址发生了变化。内部跳转和 Bourne Shell(或 Bash)中的 exec 命令很像,都是“有去无回”。另一个相近的例子是 C 语言中的 goto 语句。

    既然是内部跳转,当前正在处理的请求就还是原来那个,只是当前的 location 发生了变化,所以还是原来的那一套 Nginx 变量的容器副本。对应到上例,如果我们请求的是 /foo 这个接口,那么整个工作流程是这样的:先在 location /foo 中通过 set 指令将 a 变量的值赋为字符串 hello,然后通过 echo_exec 指令发起内部跳转,又进入到 location /bar 中,再输出 a 变量的值。因为 a 还是原来的 a,所以我们可以期望得到 hello 这行输出。测试证实了这一点:

    但如果我们从客户端直接访问 /bar 接口,就会得到空的 a 变量的值,因为它依赖于 location /foo 来对 a 进行初始化。

    从上面这个例子我们看到,一个请求在其处理过程中,即使经历多个不同的 location 配置块,它使用的还是同一套 Nginx 变量的副本。这里,我们也首次涉及到了“内部跳转”这个概念。值得一提的是,标准 ngx_rewrite 模块的 rewrite 配置指令其实也可以发起“内部跳转”,例如上面那个例子用 rewrite 配置指令可以改写成下面这样的形式:

    server {
    
        listen 8080;
    
        location /foo {
            set $a hello;
            rewrite ^ /bar;
        }
    
        location /bar {
            echo "a = [$a]";
        }
    }
    

    从上面这个例子我们看到,Nginx 变量值容器的生命期是与当前正在处理的请求绑定的,而与 location 无关。

    2、内置预定义变量

    内置预定义变量即无需声明就可以使用的变量,通常包括一个http请求或响应中一部分内容的值,以下为一些常用的内置预定义变量

    变量名定义
    $arg_PARAMETERGET请求中变量名PARAMETER参数的值。
    $args这个变量等于GET请求中的参数。例如,foo=123&bar=blahblah;这个变量只可以被修改
    $binary_remote_addr二进制码形式的客户端地址。
    $body_bytes_sent传送页面的字节数
    $content_length请求头中的Content-length字段。
    $content_type请求头中的Content-Type字段。
    $cookie_COOKIEcookie COOKIE的值。
    $document_root当前请求在root指令中指定的值。
    $document_uri与$uri相同。
    $host请求中的主机头(Host)字段,如果请求中的主机头不可用或者空,则为处理请求的server名称(处理请求的server的server_name指令的值)。值为小写,不包含端口。
    $hostname机器名使用 gethostname系统调用的值
    $http_HEADERHTTP请求头中的内容,HEADER为HTTP请求中的内容转为小写,-变为_(破折号变为下划线),例如:$http_user_agent(Uaer-Agent的值);
    $sent_http_HEADERHTTP响应头中的内容,HEADER为HTTP响应中的内容转为小写,-变为_(破折号变为下划线),例如: $sent_http_cache_control, $sent_http_content_type…;
    $is_args如果$args设置,值为"?",否则为""。
    $limit_rate这个变量可以限制连接速率。
    $nginx_version当前运行的nginx版本号。
    $query_string与$args相同。
    $remote_addr客户端的IP地址。
    $remote_port客户端的端口。
    $remote_user已经经过Auth Basic Module验证的用户名。
    $request_filename当前连接请求的文件路径,由root或alias指令与URI请求生成。
    $request_body这个变量(0.7.58+)包含请求的主要信息。在使用proxy_pass或fastcgi_pass指令的location中比较有意义。
    $request_body_file客户端请求主体信息的临时文件名。
    $request_completion如果请求成功,设为"OK";如果请求未完成或者不是一系列请求中最后一部分则设为空。
    $request_method这个变量是客户端请求的动作,通常为GET或POST。包括0.8.20及之前的版本中,这个变量总为main request中的动作,如果当前请求是一个子请求,并不使用这个当前请求的动作。
    $request_uri这个变量等于包含一些客户端请求参数的原始URI,它无法修改,请查看$uri更改或重写URI。
    $scheme所用的协议,比如http或者是https,比如rewrite ^(.+)$ $scheme://example.com$1 redirect;
    $server_addr服务器地址,在完成一次系统调用后可以确定这个值,如果要绕开系统调用,则必须在listen中指定地址并且使用bind参数。
    $server_name服务器名称。
    $server_port请求到达服务器的端口号。
    $server_protocol请求使用的协议,通常是HTTP/1.0或HTTP/1.1。
    $uri请求中的当前URI(不带请求参数,参数位于args),不同于浏览器传递的args),不同于浏览器传递的args),不同于浏览器传递的request_uri的值,它可以通过内部重定向,或者使用index指令进行修改。不包括协议和主机名,例如/foo/bar.html

    Nginx 内建变量最常见的用途就是获取关于请求或响应的各种信息。

    1、uri vs request_uri

    由 ngx_http_core 模块提供的内建变量 uri,可以用来获取当前请求的 URI(经过解码,并且不含请求参数),
    而 request_uri 则用来获取请求最原始的 URI (未经解码,并且包含请求参数)。

    location /test-uri {
        echo "uri = $uri";
        echo "request_uri = $request_uri";
    }
    

    输出

    [root@localhost html]# nginx -s reload
    [root@localhost html]# curl localhost/test-uri
    uri = /test-uri
    request_uri = /test-uri
    
    [root@localhost html]# curl "localhost/test-uri?a=3&b=4"
    uri = /test-uri
    request_uri = /test-uri?a=3&b=4
    
    [root@localhost html]# curl "localhost/test-uri/hello%20world?a=3&b=4"
    uri = /test-uri/hello world
    request_uri = /test-uri/hello%20world?a=3&b=4
    

    2、$arg_XXX

    另一个特别常用的内建变量其实并不是单独一个变量,而是有无限多变种的一群变量,即名字以 arg_ 开头的所有变量,我们估且称之为 arg_XXX 变量群。
    一个例子是 arg_name,这个变量的值是当前请求中名为 name 的参数的值,而且还是未解码的原始形式的值。

    location /test-arg {
        echo "name: $arg_name";
        echo "class: $arg_class";
    }
    

    输出

    [root@localhost html]# nginx -s reload
    [root@localhost html]# curl localhost/test-arg
    name: 
    class:
    
    [root@localhost html]# curl "localhost/test-arg?name=Tom&class=3"
    name: Tom
    class: 3
    
    [root@localhost html]# curl "localhost/test-arg?name=hello%20world&class=9"
    name: hello%20world
    class: 9
    

    3、$arg_XXX 不区分大小写

    其实 $arg_name 不仅可以匹配 name 参数,也可以匹配 NAME 参数,抑或是 Name,Nginx 会在匹配参数名之前,自动把原始请求中的参数名调整为全部小写的形式。

    [root@localhost html]# curl "localhost/test-arg?NAME=Marry"
    name: Marry
    class:
    
    [root@localhost html]# curl "localhost/test-arg?Name=Jimmy"
    name: Jimmy
    class:
    

    4、对 uri 解码

    如果你想对 URI 参数值中的 %XX 这样的编码序列进行解码,可以使用第三方 ngx_set_misc 模块提供的

    location /test-unescape-uri {
        set_unescape_uri $name $arg_name;
        set_unescape_uri $class $arg_class;
        echo "name: $name";
        echo "class: $class";
    }
    

    现在我们再看一下效果:

    [root@localhost html]# curl "localhost/test-arg?name=hello%20world&class=9"
    name: hello world
    class: 9
    

    从这个例子我们同时可以看到,这个 set_unescape_uri 指令也像 set 指令那样,拥有自动创建 Nginx 变量的功能。后面我们还会专门介绍到 ngx_set_misc 模块。

    像 $arg_XXX 这种类型的变量拥有无穷无尽种可能的名字,所以它们并不对应任何存放值的容器。而且这种变量在 Nginx 核心中是经过特别处理的,第三方 Nginx 模块是不能提供这样充满魔法的内建变量的。

    类 似 arg_XXX 的内建变量还有不少,比如用来取 cookie 值的 cookie_XXX 变量群,用来取请求头的 http_XXX 变量群,以及用来取响应头的 sent_http_XXX 变量群。这里就不一一介绍了,感兴趣的读者可以参考 ngx_http_core 模块的官方文档。

    20、nginx 监控

    1、nginx的基础监控

    • 进程监控

    • 端口监控

    注意: 这两个是必须要加在zabbix监控,加触发器有问题及时告警。

    web 服务器 nginx 以其高性能与抗并发能力越来越多的被用户使用

    作为一款服务器产品,其运行状态是运维密切关注的,因此,对 nginx 的实时监控就必须要关注的了

    nginx 提供了 ngx_http_stub_status_module,ngx_http_reqstat_module模块,这个模块提供了基本的监控功能

    作为官方企业版的 nginx plus 通过 ngx_http_status_module 提供了更加完善的监控功能: http://demo.nginx.com/status.html

    2、监控的主要指标

    我们需要对以下主要的指标进行监控:

    1、基本活跃指标

    Accepts(接受)、Handled(已处理)、Requests(请求数)是一直在增加的计数器。Active(活跃)、Waiting(等待)、Reading(读)、Writing(写)随着请求量而增减。

    名称描述指标类型
    Accepts(接受)NGINX 所接受的客户端连接数资源: 功能
    Handled(已处理)成功的客户端连接数资源: 功能
    Dropped(已丢弃,计算得出)丢弃的连接数(接受 - 已处理)工作:错误*
    Requests(请求数)客户端请求数工作:吞吐量

    NGINX worker 进程接受 OS 的连接请求时 Accepts 计数器增加,而Handled 是当实际的请求得到连接时(通过建立一个新的连接或重新使用一个空闲的)。这两个计数器的值通常都是相同的,如果它们有差别则表明连接被Dropped,往往这是由于资源限制,比如已经达到 NGINX 的worker_connections的限制。

    2、每秒请求数 – QPS

    按照固定时间间隔采样请求数据,计算出单位时间的请求量可以看到你的 web 服务器的请求情况

    通过持续的 QPS 监控,可以立刻发现是否被恶意攻击或对服务的可用性进行评估

    虽然当问题发生时,通过 QPS 不能定位到确切问题的位置,但是他却可以在第一时间提醒你环境可能出问题了

    3、服务器错误率

    通过监控固定时间间隔内的错误代码(4XX代码表示客户端错误,5XX代码表示服务器端错误),可以了解到客户端收到的结果是否是正确的错误率突然的飙升很可能是你的网站漏洞发出的信号

    如果你希望通过 access log 分析错误率,那么你需要配置 nginx 的日志模块,让 nginx 将响应码写入访问日志

    4、请求处理时间

    请求处理时间也可以被记录在 access log 中,通过分析 access log,统计请求的平均响应时间,通过持续观察,可以发现上游服务器的问题

    3、指标的收集

    介绍了这么多的监控指标,事实上,上面介绍的仅仅是基本的监控指标,针对实际的情况,还有很多指标十分具有监控的必要

    那么,怎么去收集这些指标进行监控呢?

    通过在编译时加入 nginxngx_http_stub_status_module 模块我们可以实时监控以下基本的指标:

    1、nginx Stub Status 监控模块安装

    先使用命令查看是否已经安装这个模块:

    # -V大写会显示版本号和模块等信息、v小写仅显示版本信息
    [root@nginx]#./nginx -V 
    
    # 或用此使用看:
    [root@nginx]#nginx -V 2>&1 | grep -o with-http_stub_status_module 
    

    如果已经安装,会在显示的信息中包含 --with-http_stub_status_module信息。如果没有此模块,需要重新安装,编译命令如下:

    ./configure –with-http_stub_status_module
    

    具体的使用方法是在执行 ./configure 时,指定 --with-http_stub_status_module,然后通过配置:

    location /nginx-status {
                stub_status            on;
                access_log             on;
               allow 127.0.0.1;
                deny all;
                #auth_basic              "nginxstatus";
                #auth_basic_user_file  conf/nginxstaus;
    }
    

    此处默认只有本地访问,如果远程查看需要加相关的IP或者干脆去掉Deny all即可。加密文件可以使用#htpasswd -c /usr/nginx/conf hxb 命令来创建。配置完成后需要重启Nginx服务。状态配置只能是针对某个Nginx服务。目前Nginx还无法做到针对单个站点进行监控。

    2、nginx 状态查看

    配置完成后在浏览器中输入http://127.0.0.1/nginx-status 查看(或者用 curl localhost/nginx_status),显示信息如下:

    Active connections: 100 
    server accepts handled requests
     1075 1064 6253 
    Reading: 0 Writing: 5 Waiting: 95 
    

    Accepts(接受)、Handled(已处理)、Requests(请求数)是一直在增加的计数器。Active(活跃)、Waiting(等待)、Reading(读)、Writing(写)随着请求量而增减。

    名称描述指标类型
    Accepts(接受)NGINX 所接受的客户端连接数资源: 功能
    Handled(已处理)成功的客户端连接数资源: 功能
    Dropped(已丢弃,计算得出)丢弃的连接数(接受 - 已处理)工作:错误*
    Requests(请求数)客户端请求数工作:吞吐量

    3、Stub Status 参数说明

    active connections – 活跃的连接数量

    server accepts handled requests — 总共处理了1075个连接 , 成功创建1064次握手, 总共处理了6253个请求

    每个连接有三种状态waiting、reading、writing

    reading —读取客户端的Header信息数.这个操作只是读取头部信息,读取完后马上进入writing状态,因此时间很短。

    writing — 响应数据到客户端的Header信息数.这个操作不仅读取头部,还要等待服务响应,因此时间比较长。

    waiting — 开启keep-alive后等候下一次请求指令的驻留连接.

    正常情况下waiting数量是比较多的,并不能说明性能差。反而如果reading+writing数量比较多说明服务并发有问题。
      在这里插入图片描述

    名称描述是否累加历史数据
    Accepts(接受)NGINX 接受的客户端连接数(包括 Handled + Dropped + Waiting)
    Handled(已处理)成功处理的客户端连接数(包含 Waiting 状态连接)
    Active(活跃)当前活跃的客户端连接数
    Dropped(已丢弃)已丢弃连接数(出错)
    Requests(请求数)客户端请求数
    Waiting(等待)正在等待的连接数
    Reading(读)正在执行读操作的连接数
    Writing(写)正在执行写操作的连接数

    当用户请求连接Nginx服务器时,accepts计数器会加一。且当服务器处理该连接请求时,handled计数器同样会加一。一般而言,两者的值是相等的,除非达到了某些资源极限(如worker_connection的限制)。

    用户连接请求被处理,就会进入 active 状态。如果该连接没有其他 request,则进入 waiting 的子状态;如果有 request,nginx 会读取 request 的 header,计数器 request 加一,进入 reading 的子状态。 reading 状态持续时间非常短,header 被读取后就会进入 writing 状态。事实上,直到服务器将响应结果返回给用户之前,该连接会一直保持 writing 状态。所以说,writing 状态一般会被长时间占用。

    一旦 NGINX 成功处理一个连接时,连接会移动到Active状态,在这里对客户端请求进行处理:

    Active状态

    Waiting: 活跃的连接也可以处于 Waiting 子状态,如果有在此刻没有活跃请求的话。新连接可以绕过这个状态并直接变为到 Reading 状态,最常见的是在使用“accept filter(接受过滤器)” 和 “deferred
    accept(延迟接受)”时,在这种情况下,NGINX 不会接收 worker 进程的通知,直到它具有足够的数据才开始响应。如果连接设置为
    keep-alive ,那么它在发送响应后将处于等待状态。
    Reading: 当接收到请求时,连接离开 Waiting 状态,并且该请求本身使 Reading 状态计数增加。在这种状态下 NGINX 会读取客户端请求首部。请求首部是比较小的,因此这通常是一个快速的操作。
    Writing: 请求被读取之后,其使 Writing 状态计数增加,并保持在该状态,直到响应返回给客户端。这意味着,该请求在 Writing 状态时, 一方面 NGINX 等待来自上游系统的结果(系统放在 NGINX “后面”),另外一方面,NGINX
    也在同时响应。请求往往会在 Writing 状态花费大量的时间

    通常,一个连接在同一时间只接受一个请求。在这种情况下,Active 连接的数目 == Waiting 的连接 + Reading 请求 + Writing 。

    怎么利用这些参数?
    开源的 Nginx 提供的原始参数中,实时性的会比较有用,如 Active connections、Reading、Writing 以及 Waiting。这些数据能够反映当前 Nginx 的负载情况,方便在服务器出现问题时及时发现问题。而另一些数据由于不是状态量,Nginx 无法计算当前的量值而改做其统计数,如 accepts、handled 和 requests。

    对于维护网站人员,accepts、handled 和 requests 的统计值用处是不大的,值得参考的是短时间内这三者数值的增量。这个短时间可以是一秒,如 accepts_per_second、handled_per_second 和 requests_per_second。一个简单的做法就是每秒都去读取这些参数,返回一个和上一秒的差值就行。当然,handled_per_second 替换成 dropped_per_second=accepts_per_second-handled_per_second 就更完美了。

    通过这七个参数,就可以从连接到请求全方位的监控起 Nginx 的运行状态。为了方便检测,对每次获取的参数保留下来,然后按时间展现出来。下图展示了 Nginx 在运行时的参考数据。
    在这里插入图片描述
    nginx折线图

    4、Reqstat 模块监控

    描述

    • ngx_http_reqstat_module 模块

    • 这个模块计算定义的变量,根据变量值分别统计 nginx 的运行状况。

    • 可以监视的运行状况有:连接数、请求数、各种响应码范围的请求数、输入输出流量、rt、upstream访问等。

    • 可以指定获取所有监控结果或者一部分监控结果。

    • 利用变量添加自定义监控状态。总的监控状态最大个数为50个。

    • 回收过期的监控数据。

    • 设置输出格式

    • 跟踪请求,不受内部跳转的影响

    • 不要使用与响应相关的变量作为条件,比如"$status"

    编译
    默认编入Tengine,可通过 --without-http_reqstat_module 不编译此模块,或通过–with-http_reqstat_module=shared 编译为so模块。

    使用so模块加载的话,请确保其顺序在"ngx_http_lua_module"之后。可以借助"nginx -m"来确认

    例子

    http {
        req_status_zone server "$host,$server_addr:$server_port" 10M;
        req_status_zone_add_indicator server $limit;
        
        server {
            location /us {
                req_status_show;
                req_status_show_field req_total $limit;
            }
    
            set $limit 0;
    
            if ($arg_limit = '1') {
                set $limit 1;
            }
    
            req_status server;
        }
    }
    
    • 以上例,通过访问/us得到统计结果
    • 每行对应一个server
    • 每行的默认格式

    kv,bytes_in,bytes_out,conn_total,req_total,http_2xx,http_3xx,http_4xx,http_5xx,http_other_status,rt,ups_req,ups_rt,ups_tries,http_200,http_206,http_302,http_304,http_403,http_404,http_416,http_499,http_500,http_502,http_503,http_504,http_508,http_other_detail_status,http_ups_4xx,http_ups_5xx

    • kv 计算得到的req_status_zone指令定义变量的值,最大长度可配置,默认104B,超长的部分截断
    • bytes_in 从客户端接收流量总和
    • bytes_out 发送到客户端流量总和
    • conn_total 处理过的连接总数
    • req_total 处理过的总请求数
    • http_2xx 2xx请求的总数
    • http_3xx 3xx请求的总数
    • http_4xx 4xx请求的总数
    • http_5xx 5xx请求的总数
    • http_other_status 其他请求的总数
    • rt rt的总数
    • ups_req 需要访问upstream的请求总数
    • ups_rt 访问upstream的总rt
    • ups_tries upstram总访问次数
    • http_200 200请求的总数
    • http_206 206请求的总数
    • http_302 302请求的总数
    • http_304 304请求的总数
    • http_403 403请求的总数
    • http_404 404请求的总数
    • http_416 416请求的总数
    • http_499 499请求的总数
    • http_500 500请求的总数
    • http_502 502请求的总数
    • http_503 503请求的总数
    • http_504 504请求的总数
    • http_508 508请求的总数
    • http_other_detail_status 非以上13种status code的请求总数
    • http_ups_4xx upstream返回4xx响应的请求总数
    • http_ups_5xx upstream返回5xx响应的请求总数
    • 可以用"req_status_show_field"指令定义输出格式。左侧栏是字段的名字。
    • 注,后续会清理这些状态,因为已经支持了自定义状态。
    • tsar可解析输出结果,具体见https://github.com/alibaba/tsar

    指令

    Syntax: req_status_zone zone_name value size
    Default: none
    Context: main

    创建统计使用的共享内存。zone_name是共享内存的名称,value用于定义key,支持变量。size是共享内存的大小。

    例子:

    req_status_zone server "$host,$server_addr:$server_port" 10M;
    

    创建名为“server”的共享内存,大小10M,使用“$host,$server_addr:$server_port”计算key。

    • 注意,如果希望用tsar来监控的话,key的定义中请不要使用逗号。

    Syntax: req_status zone_name1 [zone_name2 [zone_name3 […]]]
    Default: none
    Context: http、srv、loc

    开启统计,可以指定同时统计多个目标,每一个zone_name对应一个目标。

    Syntax: req_status_show [zone_name1 [zone_name2 […]]]
    Default: 所有建立的共享内存目标
    Context: loc

    按格式返回统计结果。可指定返回部分目标的统计结果。

    Syntax: req_status_show_field field_name1 [field_name2 [field_name3 […]]]
    Default: all the fields, including user defined fields
    Context: loc

    定义输出格式。可以使用的字段:内置字段,以上面的名字来表示;自定义字段,用变量表示。
    'kv’总是每行的第一个字段。

    Syntax: req_status_zone_add_indecator zone_name v a r 1 [ var1 [ var1[var2 […]]
    Default: none
    Context: http

    通过变量增加自定义字段,新增加的字段目前会展现在每行的末尾。

    Syntax: req_status_zone_key_length zone_name length
    Default: none
    Context: http

    定义某个共享内存块中key的最大长度,默认值104。key中超出的部分会被截断。

    Syntax: req_status_zone_recycle zone_name times seconds
    Default: none
    Context: http

    定义某个共享内存块过期数据的回收。回收在共享内存耗尽时自动开启。只会回收访问频率低于设置值的监控数据。
    频率定义为 times / seconds,默认值为10r/min,即

    req_status_zone_recycle demo_zone 10 60;
    
    tengine官方说req-statu模块默认安装。但是并没有。而且tengine的req-status模块不能分upstream监控,从github引入第三方模块解决该问题
    
    1. 安装
    # cd /usr/local/src/
     # wget "http://nginx.org/download/nginx-1.4.2.tar.gz"
     # tar -xzvf nginx-1.4.2.tar.gz
     # wget https://github.com/zls0424/ngx_req_status/archive/master.zip -O ngx_req_status.zip
     # unzip ngx_req_status.zip
     # cd nginx-1.4.2/
     # patch -p1 < ../ngx_req_status-master/write_filter.patch
     # yum -y install pcre pcre-devel openssl openssl-devel gcc gcc-c++   zlib zlib-devel
     # ./configure --prefix=/usr/local/nginx-1.4.2 --add-module=../ngx_req_status-master
     # make -j2
     # make install
     # useradd nginx    passwd nginx
    2. 配置
    http {
     req_status_zone server_name $server_name 256k;
     req_status_zone server_addr $server_addr 256k;
     req_status_zone server_url  $server_name$uri 256k;
    req_status server_name server_addr server_url;
    server {
     server_name www.1000status.com;
     location /req-status {
     req_status_show on;
     }
     }
     }
     
     指令介绍
     req_status_zone
    语法: req_status_zone name string size
    默认值: None
    配置块: http
    定义请求状态ZONE,请求按照string分组来排列,例如:
    req_status_zone server_url  $server_name$uri 256k;
    域名+uri将会形成一条数据,可以看到所有url的带宽,流量,访问数
    
    req_status
    语法: req_status zone1[ zone2]
    默认值: None
    配置块: http, server, location
    在location中启用请求状态,你可以指定更多zones。
    
    req_status_show
    语法: req_status_show on
    默认值: None
    配置块: location
    
    
    
    ./configure --prefix=/usr/local/nginx-1.4.2 --add-module=../ngx_req_status-master --sbin-path=/usr/sbin/nginx  --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/tmp/nginx/client_body  --http-proxy-temp-path=/tmp/nginx/proxy  --http-fastcgi-temp-path=/tmp/nginx/fastcgi --pid-path=/var/run/nginx.pid --lock-path=/var/lock/nginx  --with-http_stub_status_module --with-http_ssl_module   --with-http_gzip_static_module --with-pcre  --group=nginx --user=nginx
    

    5、补充

    查看Nginx并发进程数:ps -ef | grep nginx | wc -l

    查看Web服务器TCP连接状态:netstat -n | awk ‘/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}’

    商业版的 nginx plus 通过他的 ngx_http_status_module 提供了比 nginx 更多的监控指标,可以参看 http://demo.nginx.com/status.html

    4、nginx access log 分析

    nginx 的 access log 中可以记录很多有价值的信息,通过分析 access log,可以收集到很多指标

    python 编写的 linux 工具 ngxtop 就实现了对 access log 的分析功能

    三、HTTPS 基本原理

    https 介绍

    HTTPS(全称:HyperText Transfer Protocol over Secure Socket Layer),其实 HTTPS 并不是一个新鲜协议,Google 很早就开始启用了,初衷是为了保证数据安全。 近些年,Google、Baidu、Facebook 等这样的互联网巨头,不谋而合地开始大力推行 HTTPS, 国内外的大型互联网公司很多也都已经启用了全站 HTTPS,这也是未来互联网发展的趋势。

    为鼓励全球网站的 HTTPS 实现,一些互联网公司都提出了自己的要求:

    1. Google 已调整搜索引擎算法,让采用 HTTPS 的网站在搜索中排名更靠前;
    2. 从 2017 年开始,Chrome 浏览器已把采用 HTTP 协议的网站标记为不安全网站;
    3. 苹果要求 2017 年App Store 中的所有应用都必须使用 HTTPS 加密连接;
    4. 当前国内炒的很火热的微信小程序也要求必须使用 HTTPS 协议;
    5. 新一代的 HTTP/2 协议的支持需以 HTTPS 为基础。

    等等,因此想必在不久的将来,全网 HTTPS 势在必行。

    1、HTTPS 协议介绍

    • HTTP 协议(HyperText Transfer Protocol,超文本传输协议):是客户端浏览器或其他程序与Web服务器之间的应用层通信协议 。

    • HTTPS 协议(HyperText Transfer Protocol over Secure Socket Layer):可以理解为HTTP+SSL/TLS, 即 HTTP 下加入 SSL 层,HTTPS 的安全基础是 SSL,因此加密的详细内容就需要 SSL,用于安全的 HTTP 数据传输。
      在这里插入图片描述

    • 如上图所示 HTTPS 相比 HTTP 多了一层 SSL/TLS

      • SSL(Secure Socket Layer,安全套接字层):1994年为 Netscape 所研发,SSL 协议位于 TCP/IP 协议与各种应用层协议之间,为数据通讯提供安全支持。
      • TLS(Transport Layer Security,传输层安全):其前身是 SSL,它最初的几个版本(SSL 1.0、SSL 2.0、SSL 3.0)由网景公司开发,1999年从 3.1 开始被 IETF 标准化并改名,发展至今已经有 TLS 1.0、TLS 1.1、TLS 1.2 三个版本。SSL3.0和TLS1.0由于存在安全漏洞,已经很少被使用到。TLS 1.3 改动会比较大,目前还在草案阶段,目前使用最广泛的是TLS 1.1、TLS 1.2。

    2、加密算法

    据记载,公元前400年,古希腊人就发明了置换密码;在第二次世界大战期间,德国军方启用了“恩尼格玛”密码机,所以密码学在社会发展中有着广泛的用途。

    1. 对称加密
      有流式、分组两种,加密和解密都是使用的同一个密钥。
      例如:DES、AES-GCM、ChaCha20-Poly1305等

    2. 非对称加密
      加密使用的密钥和解密使用的密钥是不相同的,分别称为:公钥、私钥,公钥和算法都是公开的,私钥是保密的。非对称加密算法性能较低,但是安全性超强,由于其加密特性,非对称加密算法能加密的数据长度也是有限的。

      例如:RSA、DSA、ECDSA、 DH、ECDHE

    3. 哈希算法
      将任意长度的信息转换为较短的固定长度的值,通常其长度要比信息小得多,且算法不可逆。

      例如:MD5、SHA-1、SHA-2、SHA-256 等

    4. 数字签名
      签名就是在信息的后面再加上一段内容(信息经过hash后的值),可以证明信息没有被修改过。hash值一般都会加密后(也就是签名)再和信息一起发送,以保证这个hash值不被修改。

    3、HTTPS 原理

    1、HTTP 访问过程

    在这里插入图片描述

    抓包如下:
    在这里插入图片描述
    如上图所示,HTTP请求过程中,客户端与服务器之间没有任何身份确认的过程,数据全部明文传输,“裸奔”在互联网上,所以很容易遭到黑客的攻击,如下:
    在这里插入图片描述
    可以看到,客户端发出的请求很容易被黑客截获,如果此时黑客冒充服务器,则其可返回任意信息给客户端,而不被客户端察觉,所以我们经常会听到一词“劫持”,现象如下:

    下面两图中,浏览器中填入的是相同的URL,左边是正确响应,而右边则是被劫持后的响应(从貌美如花变成如花。。。)
    在这里插入图片描述
    所以 HTTP 传输面临的风险有:

    • 窃听风险:黑客可以获知通信内容。
    • 篡改风险:黑客可以修改通信内容。
    • 冒充风险:黑客可以冒充他人身份参与通信。

    2、HTTP 向 HTTPS 演化的过程

    第一步:为了防止上述现象的发生,人们想到一个办法:对传输的信息加密(即使黑客截获,也无法破解)
    在这里插入图片描述
    如上图所示,此种方式属于对称加密,双方拥有相同的密钥,信息得到安全传输,但此种方式的缺点是:

    (1)不同的客户端、服务器数量庞大,所以双方都需要维护大量的密钥,维护成本很高

    (2)因每个客户端、服务器的安全级别不同,密钥极易泄露

    第二步:既然使用对称加密时,密钥维护这么繁琐,那我们就用非对称加密试试
    在这里插入图片描述
    如上图所示,客户端用公钥对请求内容加密,服务器使用私钥对内容解密,反之亦然,但上述过程也存在缺点:

    (1)公钥是公开的(也就是黑客也会有公钥),所以第 ④ 步私钥加密的信息,如果被黑客截获,其可以使用公钥进行解密,获取其中的内容

    第三步:非对称加密既然也有缺陷,那我们就将对称加密,非对称加密两者结合起来,取其精华、去其糟粕,发挥两者的各自的优势
    在这里插入图片描述
    如上图所示

    (1)第 ③ 步时,客户端说:(咱们后续回话采用对称加密吧,这是对称加密的算法和对称密钥)这段话用公钥进行加密,然后传给服务器

    (2)服务器收到信息后,用私钥解密,提取出对称加密算法和对称密钥后,服务器说:(好的)对称密钥加密

    (3)后续两者之间信息的传输就可以使用对称加密的方式了

    遇到的问题:

    (1)客户端如何获得公钥

    (2)如何确认服务器是真实的而不是黑客

    第四步:获取公钥与确认服务器身份
    在这里插入图片描述
    1、获取公钥

    (1)提供一个下载公钥的地址,回话前让客户端去下载。(缺点:下载地址有可能是假的;客户端每次在回话前都先去下载公钥也很麻烦)

    (2)回话开始时,服务器把公钥发给客户端(缺点:黑客冒充服务器,发送给客户端假的公钥)

    2、那有木有一种方式既可以安全的获取公钥,又能防止黑客冒充呢? 那就需要用到终极武器了:SSL 证书(申购)
    在这里插入图片描述
    如上图所示,在第 ② 步时服务器发送了一个SSL证书给客户端,SSL 证书中包含的具体内容有:

    (1)证书的发布机构CA

    (2)证书的有效期

    (3)公钥

    (4)证书所有者

    (5)签名

    ………
    3、客户端在接受到服务端发来的SSL证书时,会对证书的真伪进行校验,以浏览器为例说明如下:

    (1)首先浏览器读取证书中的证书所有者、有效期等信息进行一一校验

    (2)浏览器开始查找操作系统中已内置的受信任的证书发布机构CA,与服务器发来的证书中的颁发者CA比对,用于校验证书是否为合法机构颁发

    (3)如果找不到,浏览器就会报错,说明服务器发来的证书是不可信任的。

    (4)如果找到,那么浏览器就会从操作系统中取出 颁发者CA 的公钥,然后对服务器发来的证书里面的签名进行解密

    (5)浏览器使用相同的hash算法计算出服务器发来的证书的hash值,将这个计算的hash值与证书中签名做对比

    (6)对比结果一致,则证明服务器发来的证书合法,没有被冒充

    (7)此时浏览器就可以读取证书中的公钥,用于后续加密了

    4、所以通过发送SSL证书的形式,既解决了公钥获取问题,又解决了黑客冒充问题,一箭双雕,HTTPS加密过程也就此形成

    所以相比HTTP,HTTPS 传输更加安全

    (1) 所有信息都是加密传播,黑客无法窃听。

    (2) 具有校验机制,一旦被篡改,通信双方会立刻发现。

    (3) 配备身份证书,防止身份被冒充。

    3、HTTPS 总结

    综上所述,相比 HTTP 协议,HTTPS 协议增加了很多握手、加密解密等流程,虽然过程很复杂,但其可以保证数据传输的安全。所以在这个互联网膨胀的时代,其中隐藏着各种看不见的危机,为了保证数据的安全,维护网络稳定,建议大家多多推广HTTPS。

    HTTPS 缺点:

    1. SSL 证书费用很高,以及其在服务器上的部署、更新维护非常繁琐
    2. HTTPS 降低用户访问速度(多次握手)
    3. 网站改用HTTPS 以后,由HTTP 跳转到 HTTPS 的方式增加了用户访问耗时(多数网站采用302跳转)
    4. HTTPS 涉及到的安全算法会消耗 CPU 资源,需要增加大量机器(https访问过程需要加解密)

    4、构建私有的 CA 机构

    1、CA 介绍

    CA(Certificate Authority)证书颁发机构主要负责证书的颁发、管理以及归档和吊销。证书内包含了拥有证书者的姓名、地址、电子邮件帐号、公钥、证书有效期、发放证书的CA、CA的数字签名等信息。证书主要有三大功能:加密、签名、身份验证。

    2、构建私有 CA

    1、检查安装 openssl
    rpm -qa openssl
    

    如果未安装,安装 openssl

    yum install openssl openssl-devel
    
    2、查看配置文件

    openssl 配置/etc/pki/tls/openssl.cnf有关CA的配置。如果服务器为证书签署者的身份那么就会用到此配置文件,此配置文件对于证书申请者是无作用的。

    ####################################################################
    [ ca ]
    default_ca      = CA_default            # 默认的CA配置;CA_default指向下面配置块
    
    ####################################################################
    [ CA_default ]
    
    dir             = /etc/pki/CA           # CA的默认工作目录
    certs           = $dir/certs            # 认证证书的目录
    crl_dir         = $dir/crl              # 证书吊销列表的路径
    database        = $dir/index.txt        # 数据库的索引文件
    
    
    new_certs_dir   = $dir/newcerts         # 新颁发证书的默认路径
    
    certificate     = $dir/cacert.pem       # 此服务认证证书,如果此服务器为根CA那么这里为自颁发证书
    serial          = $dir/serial           # 下一个证书的证书编号
    crlnumber       = $dir/crlnumber        # 下一个吊销的证书编号
                                            
    crl             = $dir/crl.pem          # The current CRL
    private_key     = $dir/private/cakey.pem# CA的私钥
    RANDFILE        = $dir/private/.rand    # 随机数文件
    
    x509_extensions = usr_cert              # The extentions to add to the cert
    
    name_opt        = ca_default            # 命名方式,以ca_default定义为准
    cert_opt        = ca_default            # 证书参数,以ca_default定义为准
    
    
    default_days    = 365                   # 证书默认有效期
    default_crl_days= 30                    # CRl的有效期
    default_md      = sha256                # 加密算法
    preserve        = no                    # keep passed DN ordering
    
    
    policy          = policy_match          #policy_match策略生效
    
    # For the CA policy
    [ policy_match ]
    countryName             = match         #国家;match表示申请者的申请信息必须与此一致
    stateOrProvinceName     = match         #州、省
    organizationName        = match         #组织名、公司名
    organizationalUnitName  = optional      #部门名称;optional表示申请者可以的信息与此可以不一致
    commonName              = supplied
    emailAddress            = optional
    
    # For the 'anything' policy
    # At this point in time, you must list all acceptable 'object'
    # types.
    [ policy_anything ]                     #由于定义了policy_match策略生效,所以此策略暂未生效
    countryName             = optional
    stateOrProvinceName     = optional
    localityName            = optional
    organizationName        = optional
    organizationalUnitName  = optional
    commonName              = supplied
    emailAddress            = optional
    
    3、根证书服务器目录

    根CA服务器:因为只有 CA 服务器的角色,所以用到的目录只有/etc/pki/CA

    网站服务器:只是证书申请者的角色,所以用到的目录只有/etc/pki/tls

    4、创建所需要的文件
    [root@server ~]# cd /etc/pki/CA/
    [root@server CA]# ls
    certs  crl  newcerts  private
    [root@server CA]# touch index.txt        #生成证书索引数据库文件
    [root@server CA]# ls
    certs  crl  index.txt  newcerts  private
    [root@server CA]# echo 01 > serial       #指定第一个颁发证书的序列号
    [root@server CA]# ls
    certs  crl  index.txt  newcerts  private  serial
    
    5、创建密钥

    在根CA服务器上创建密钥,密钥的位置必须为/etc/pki/CA/private/cakey.pem,这个是openssl.cnf中中指定的路径,只要与配置文件中指定的匹配即可。

    [root@server CA]# (umask 066; openssl genrsa -out private/cakey.pem 2048)
    Generating RSA private key, 2048 bit long modulus
    ........................................................+++
    .........................+++
    e is 65537 (0x10001)
    
    6、生成自签名证书

    根CA自签名证书,根CA是最顶级的认证机构,没有人能够认证他,所以只能自己认证自己生成自签名证书。

    [root@server CA]# openssl req -new -x509 -key /etc/pki/CA/private/cakey.pem -days 7300 -out /etc/pki/CA/cacert.pem -days 7300
    You are about to be asked to enter information that will be incorporated
    into your certificate request.
    What you are about to enter is what is called a Distinguished Name or a DN.
    There are quite a few fields but you can leave some blank
    For some fields there will be a default value,
    If you enter '.', the field will be left blank.
    -----
    Country Name (2 letter code) [XX]:CN   
    State or Province Name (full name) []:BEIJING      
    Locality Name (eg, city) [Default City]:BEIJING
    Organization Name (eg, company) [Default Company Ltd]:CA
    Organizational Unit Name (eg, section) []:OPT
    Common Name (eg, your name or your server's hostname) []:ca.qf.com
    Email Address []:
    [root@server CA]# ls
    cacert.pem  certs  crl  index.txt  newcerts  private  serial
    
    -new: 	生成新证书签署请求
    -x509: 	专用于CA生成自签证书
    -key: 	生成请求时用到的私钥文件
    -days n:	证书的有效期限
    -out /PATH/TO/SOMECERTFILE: 	证书的保存路径
    
    7、下载安装证书

    /etc/pki/CA/cacert.pem就是生成的自签名证书文件,使用 SZ/xftp工具将他导出到窗口机器中。然后双击安装此证书到受信任的根证书颁发机构
    在这里插入图片描述

    3、CA 证书申请及签名

    1、检查安装 openssl
    rpm -qa openssl
    

    如果未安装,安装 openssl

    yum install openssl openssl-devel
    
    2、客户端生成私钥文件
    [root@node1 ~]# (umask 066; openssl genrsa -out /etc/pki/tls/private/www.qf.com.key 2048)
    Generating RSA private key, 2048 bit long modulus
    ......................+++
    ....................................................................................+++
    e is 65537 (0x10001)
    [root@node1 ~]# cd /etc/pki/tls/private
    [root@node1 private]# ls
    www.qf.com.key
    
    3、客户端用私钥加密生成证书请求
    [root@node1 private]# ls ../
    cert.pem  certs  misc  openssl.cnf  private  
    [root@node1 private]# openssl req -new -key /etc/pki/tls/private/www.qf.com.key -days 365 -out /etc/pki/tls/www.qf.com.csr
    You are about to be asked to enter information that will be incorporated
    into your certificate request.
    What you are about to enter is what is called a Distinguished Name or a DN.
    There are quite a few fields but you can leave some blank
    For some fields there will be a default value,
    If you enter '.', the field will be left blank.
    -----
    Country Name (2 letter code) [XX]:CN
    State or Province Name (full name) []:BEIJING
    Locality Name (eg, city) [Default City]:BEIJING
    Organization Name (eg, company) [Default Company Ltd]:QF
    Organizational Unit Name (eg, section) []:OPT
    Common Name (eg, your name or your server's hostname) []:www.qf.com
    Email Address []:
    
    Please enter the following 'extra' attributes
    to be sent with your certificate request
    A challenge password []:
    An optional company name []:
    [root@node1 private]# cd ../
    [root@node1 tls]# ls
    cert.pem  certs  misc  openssl.cnf  private  www.qf.com.csr
    

    CSR(Certificate Signing Request)包含了公钥和名字信息。通常以.csr为后缀,是网站向CA发起认证请求的文件,是中间文件。

    在这一命令执行的过程中,系统会要求填写如下信息:

    要求添写的内容
    Country Name (2 letter code)使用国际标准组织(ISO)国码格式,填写2个字母的国家代号。中国请填写CN
    State or Province Name (full name)省份,比如填写BeiJing
    Locality Name (eg, city)城市,比如填写BeiJing
    Organization Name (eg, company)组织单位,比如填写公司名称的拼音
    Organizational Unit Name (eg, section)比如填写IT Dept
    Common Name (eg, your websites domain name)城市,比如填写BeiJing
    Email Address邮件地址,可以不填
    A challenge password可以不填
    An optional company name可以不填

    最后把生成的请求文件(/etc/pki/tls/www.qf.com.csr)传输给CA ,这里我使用scp命令,通过ssh协议,将该文件传输到CA下的/etc/pki/CA/private/目录

    root@node1 tls]# scp www.qf.com.csr 192.168.95.134:/etc/pki/CA/private/
    root@192.168.95.134's password: 
    www.qf.com.csr                          100%  997   777.2KB/s   00:00  
    
    4、CA 签署证书
    [root@server ~]# openssl ca -in /etc/pki/CA/private/www.qf.com.csr -out /etc/pki/CA/certs/www.qf.com.ctr -days 365
    Using configuration from /etc/pki/tls/openssl.cnf
    Check that the request matches the signature
    Signature ok
    Certificate Details:
            Serial Number: 1 (0x1)
            Validity
                Not Before: Mar 14 13:45:02 2019 GMT
                Not After : Mar 13 13:45:02 2020 GMT
            Subject:
                countryName               = CN
                stateOrProvinceName       = BEIJING
                organizationName          = QF
                organizationalUnitName    = OPT
                commonName                = www.qf.com
            X509v3 extensions:
                X509v3 Basic Constraints: 
                    CA:FALSE
                Netscape Comment: 
                    OpenSSL Generated Certificate
                X509v3 Subject Key Identifier: 
                    08:65:70:98:2B:0B:15:D0:74:FE:69:58:05:B8:02:BC:45:D8:23:9B
                X509v3 Authority Key Identifier: 
                    keyid:60:6B:BC:F1:A1:01:BF:72:FD:7D:02:A8:BD:15:BE:9C:3B:3E:03:30
    
    Certificate is to be certified until Mar 13 13:45:02 2020 GMT (365 days)
    Sign the certificate? [y/n]:y
    
    
    1 out of 1 certificate requests certified, commit? [y/n]y
    Write out database with 1 new entries
    Data Base Updated
    

    证书通常以.crt为后缀,表示证书文件

    1、可能遇到的问题
    [root@server ~]# openssl openssl ca -in /etc/pki/CA/private/www.qf.com.csr -out /etc/pki/CA/certs/www.qf.com.ctr -days 365
    Using configuration from /etc/pki/tls/openssl.cnf
    Check that the request matches the signature
    Signature ok
    The organizationName field needed to be the same in the
    CA certificate (CA) and the request (QF)
    

    因为默认使用/etc/pki/tls/openssl.cnf,里面要求其一致,修改organizationName=supplied

    修改 /etc/pki/tls/openssl.cnf

    # For the CA policy
    [ policy_match ]
    countryName             = match
    stateOrProvinceName     = match
    organizationName        = supplied
    organizationalUnitName  = optional
    commonName              = supplied
    emailAddress            = optional
    
    2、查看生成的证书的信息
    [root@server ~]# openssl x509 -in /etc/pki/CA/certs/www.qf.com.ctr -noout -subject
    subject= /C=CN/ST=BEIJING/O=QF/OU=OPT/CN=www.qf.com
    
    3、将生成的证书发放给请求客户端
    [root@server ~]# scp www.qf.com.ctr root@192.168.95.135:/etc/pki/CA/certs/
    root@192.168.95.135's password: 
    www.qf.com.ctr                            100% 4422     1.3MB/s   00:00  
    

    4、CA吊销证书

    1、知道客户端吊销的证书的serial
    [root@server ~]#openssl x509 -in /PATH/FROM/CERT_FILE -noout -serial -subject
    
    2、吊销证书

    先根据客户提交的serial与subject信息,对比检验是否与index.txt文件中的信息一致;然后

    [root@server ~]#openssl ca -revoke /etc/pki/CA/newcerts/SERIAL.pem
    
    3、生成吊销证书的编号

    第一次吊销一个证书时才需要执行

    [root@server ~]#echo 01 > /etc/pki/CA/crlnumber
    
    4、更新证书吊销列表
    [root@server ~]#openssl ca -gencrl -out thisca.crl
    
    5、查看证书吊销列表
    [root@server ~]#openssl crl -in /PATH/FROM/CRL_FILE.crl -noout -text
    

    5、nginx HTTPS 部署实战

    1. 申请证书与认证
    2. 证书下载与配置
    3. 问题分析与总结

    申请证书与认证

    要搭建https服务首先需有SSL证书,证书通常是在第三方申请,在阿里云的安全服务中有SSL证书这一项,可以在里面申请免费的证书;

    也可以在自己电脑中生成,虽然也能完成加密,但是浏览器是不认可的,因此最好还是去第三方申请

    1、证书申请

    阿里云提供免费的证书,不需要人工审核,用来做测试是非常不错的选择,申请地址如下URL。

    https://common-buy.aliyun.com/?spm=5176.2020520163.cas.1.1aa12b7aWWn20O&commodityCode=cas#/buy
    

    免费型的证书隐藏的比较深,想要申请免费证书需要先选择 1个域名->Symantec->免费型 ,所以读者这里需要注意一下,如下图参考。
    在这里插入图片描述
    选择之后,一直点击下一步,便可购买完成,免费购买证书之后笔者需要回到证书控制台,在控制台有一个补全信息的链接地址,需要通过此地址补充申请人的联系信息,参考下图填写
    在这里插入图片描述

    2、域名验证

    补全个人信息之后,还需要给阿里云验证当前域名是属于本人的,验证方式有两种,第一种是通过dns解析认证,第二种是通过上传验证文件认证,这里采用的是验证文件认证,首先需要下载文件,如下图
    在这里插入图片描述
    在下载验证文件完成之后,笔者需要把文件放到服务器中去,这里提供一条复制命令

    [root@web ~]#scp ~/Downloads/fileauth.txt  root@192.168.43.34:~/
    

    将验证文件复制到服务器之后,还需要将验证文件放到站点对应目录,参考命令如下:

    [root@web ~]#mkdir -p /website/.well-known/pki-validation  &&  cp  fileauth.txt  /website/.well-known/pki-validation/
    

    现在要验证文件放置的位置是否正确,通过两种方式进行了验证,分别是手动验证,和阿里云验证。

    1、手动验证

    手动验证的目的是首先确保文件位置放置是否正确,可以通过访问站点的url是否成功进行判断,比如笔者可以访问如下URL,如果返回如果页面能够正常打开,并且可以看到某些值,则代表配置成功。

    http://www.qf.com/.well-known/pki-validation/fileauth.txt
    
    2、通过阿里云来验证

    在确保文件放置正确之后,关键的是能让阿里云能访问到,阿里云这里提供了一个检查配置的功能,在下载验证文件页面,有一个检测配置的链接,单击之后便可进行检查,如下图。
    在这里插入图片描述
    当点击 检查配置 之后,如果阿里云能够正常访问,则会在左侧给出提示,现在可以返回证书列表,在列表中可以看到当前状态为审核中,如下图
    在这里插入图片描述
    审核因为不需要人为干预,所以很快就能下发证书,下发证书的时间大约是2分钟左右。

    证书下载与配置

    1、证书下载

    证书签发之后,可以在列表中可以看到状态栏中为 已签发 ,同时操作栏可以下载以及查看详情等,如下图所示
    在这里插入图片描述
    点击下载后,会跳转到下载详情页面,在下载详情页可以选择自己相对应的web服务,比如使用nginx,当选择nginx之后,下方还会很贴心的提示如何配置,下载nginx配置文件。

    下载配置文件之后,需要将其解压,解压之后可以看见里面包含了两个证书文件

    xxx.key

    xxx.pem

    接着需要把这两个证书文件给复制到服务器当中去,首先需要在服务器创建对应的文件夹,参考命令如下

    [root@web ~]#cd  /usr/local/nginx/conf/  &&  mkdir cert    #此命令在服务器执行
    

    在服务器创建完成对应文件夹之后,执行命令将证书文件复制到服务器中,参考命令如下:

    [root@web ~]#scp ~/Downloads/214905423420461/*  root@192.168.43.34:/usr/local/nginx/conf/cert
    
    2、证书配置

    证书复制完成之后,可以对nginx配置文件进行更改,使用vim命令编辑nginx配置文件,参考命令如下:

    [root@web ~]#vim /usr/local/nginx/conf/nginx.conf
    

    在vim界面把之前http的配置部分复制一份,复制之后修改监听的端口(listen)为443,并在其后面添加ssl的信息,参考配置如下:

     	listen 443;
        ssl on;
        ssl_certificate   cert/214905423420461.pem;
        ssl_certificate_key  cert/214905423420461.key;
        ssl_session_timeout 5m;
        ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;
    
    3、重启Nginx

    修改配置文件之后,需要测试nginx配置文件是否正确

    [root@web ~]#nginx -t 
    

    当nginx如果没有出现error相关信息,基本配置没有问题,下面是我的nginx返回结果:

    nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok
    nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful
    

    nginx 配置没有问题之后,笔者需要重启nginx让其生效,参考命令如下

    [root@web ~]#nginx -s reload
    
    4、检验效果

    现在所有该做的工作都做好了,笔者可以通过浏览器来访问可以正常访问,打开如下URL。

    https://www.xxx.com
    

    浏览器地址栏显示如下图所示
    在这里插入图片描述
    如果看到浏览器,展示安全,并且显示绿色就说明大功告成了

    6、nginx 性能优化

    当我需要进行性能优化时,说明我们服务器无法满足日益增长的业务。性能优化是一个比较大的课题,需要从以下几个方面进行探讨

    • 当前系统结构瓶颈
    • 了解业务模式
    • 性能与安全

    1、当前系统结构瓶颈

    首先需要了解的是当前系统瓶颈,用的是什么,跑的是什么业务。里面的服务是什么样子,每个服务最大支持多少并发。比如针对nginx而言,我们处理静态资源效率最高的瓶颈是多大?能支持多少qps访问请求?怎么得出系统当前的结构瓶颈?

    可以通过查看当前cpu负荷,内存使用率,进程使用率来做简单判断。还可以通过操作系统的一些工具来判断当前系统性能瓶颈,如分析对应的日志,查看请求数量。也可以通过nginx http_stub_status_module模块来查看对应的连接数,总握手次数,总请求数。也可以对线上进行压力测试,来了解当前的系统能性能,并发数,做好性能评估。

    2、了解业务模式

    虽然我们是在做性能优化,但还是要熟悉业务,最终目的都是为业务服务的。我们要了解每一个接口业务类型是什么样的业务,比如电子商务抢购模式,这种情况平时流量会很小,但是到了抢购时间,流量一下子就会猛涨。也要了解系统层级结构,每一层在中间层做的是代理还是动静分离,还是后台进行直接服务。需要我们对业务接入层和系统层次要有一个梳理

    3、性能与安全

    性能与安全也是一个需要考虑的因素,往往大家注重性能忽略安全或注重安全又忽略性能。比如说我们在设计防火墙时,如果规则过于全面肯定会对性能方面有影响。如果对性能过于注重在安全方面肯定会留下很大隐患。所以大家要评估好两者的关系,把握好两者的孰重孰轻,以及整体的相关性。权衡好对应的点。

    4、系统与nginx性能优化

    大家对相关的系统瓶颈及现状有了一定的了解之后,就可以根据影响性能方面做一个全体的评估和优化。

    • 网络(网络流量、是否有丢包,网络的稳定性都会影响用户请求)
    • 系统(系统负载、饱和、内存使用率、系统的稳定性、硬件磁盘是否有损坏)
    • 服务(连接优化、内核性能优化、http服务请求优化都可以在nginx中根据业务来进行设置)
    • 程序(接口性能、处理请求速度、每个程序的执行效率)
    • 数据库、底层服务

    上面列举出来每一级都会有关联,也会影响整体性能,这里主要关注的是nginx服务这一层。

    1、文件句柄

    在linux/unix操作系统中一切皆文件,我们的设备是文件,文件是文件,文件夹也是文件。当我们用户每发起一次请求,就会产生一个文件句柄。文件句柄可以简单的理解为文件句柄就是一个索引。文件句柄就会随着请求量的增多,进程调用频繁增加,那么产生的文件句柄也就会越多。

    系统默认对文件句柄是有限制的,不可能会让一个进程无限制的调用句柄。因为系统资源是有限的,所以我们需要限制每一个服务能够使用多大的文件句柄。操作系统默认使用的文件句柄是1024个句柄。

    2、设置方式
    • 系统全局性修改
    • 用户局部性修改
    • 进程局部性修改
    3、系统全局性修该和用户局部性修改
    [root@server ~]#vim /etc/security/limits.conf
    

    在文件最下面找到

    #*               soft    core            0
    #*               hard    rss             10000
    #@student        hard    nproc           20
    #@faculty        soft    nproc           20
    #@faculty        hard    nproc           50
    #ftp             hard    nproc           0
    #@student        -       maxlogins       4
    
    #root只是针对root这个用户来限制,soft只是发提醒,操作系统不会强制限制,一般的站点设置为一万左右就ok了
    root soft nofile 65535
    root hard nofile 65535
    # *代表通配符 所有的用户
    *    soft nofile 25535
    *    hard nofile 25535
    

    可以看到root*,root代表是root用户,*代表的是所有用户,后面的数字就是文件句柄大小。大家可以根据个人业务来进行设置。

    4、进程局部性修改
    [root@server ~]#vim /etc/nginx/nginx.conf
    user  nginx;
    worker_processes  1;  
    
    error_log  /var/log/nginx/error.log warn;
    pid        /var/run/nginx.pid;
    
    worker_rlimit_nofile 65535; #进程限制
    
    events {
        worker_connections  1024;
    }
    
    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;
    
        log_format  main  '$http_user_agent' '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for" '
                          '"$args" "$request_uri"';
    
        access_log  /var/log/nginx/access.log  main;
    
        sendfile        on; 
        #tcp_nopush     on; 
    
        keepalive_timeout  65; 
    
        #gzip  on; 
    
        include /etc/nginx/conf.d/*.conf;
    }
    

    worker_rlimit_nofile 是在进程上面进行限制。

    5、cpu的亲和配置

    cpu的亲和能够使nginx对于不同的work工作进程绑定到不同的cpu上面去。就能够减少在work间不断切换cpu,把进程通常不会在处理器之间频繁迁移,进程迁移的频率小,来减少性能损耗。[nginx 亲和配置](

    查看物理cpu

    [root@server ~]#cat /proc/cpuinfo|grep "physical id"|sort |uniq|wc -l
    

    查看cpu核心数

    [root@server ~]#cat /proc/cpuinfo|grep "cpu cores"|uniq
    

    查看cpu使用率

    [root@server ~]#top  回车后按 1
    
    6、配置worker_processes
    [root@server ~]#vim /etc/nginx/nginx.conf
    

    将刚才查看到自己cpu * cpu核心就是worker_processes

    worker_processes 2; #根据自己cpu核心数配置
    
    7、cpu亲和配置

    假如小菜的配置是2cpu,每个cpu是8核。配置如下

    worker_processes 16;
      1010101010101010 0101010101010101;
    

    配置完成后可以通过下面命令查看nginx进程配置在哪个核上

    [root@server ~]#ps -eo pid,args,psr |grep [n]ginx
    

    在nginx 1.9版本之后,就帮我们自动绑定了cpu;

    worker_cpu_affinity auto;
    

    5、nginx通用配置优化

    [root@server ~]#vim /etc/nginx/nginx.conf
    #将nginx进程设置为普通用户,为了安全考虑
    user nginx; 
    
    #当前启动的worker进程,官方建议是与系统核心数一直
    worker_processes 2;
    #方式一, 第一个work进程绑定第一个cpu核心,第二个work进程绑定到第二个cpu核心,依次内推 直到弟16个
    #wokrer_cpu_affinity 0000000000000000 0000000000000001 0000000000000010 0000000000000100 ... 1000000000000000
    
    #方式二,当 worker_processes 2 时,表明 第一work进程可以绑定第 2 4 6 8 10 12 14 16 核心,那么第二work进程就绑定 奇数核心
    #worker_cpu_affinity 1010101010101010 0101010101010101;
    
    #方式三,就是自动分配绑定
    worker_cpu_affinity auto;
    
    #日志配置成warn
    error_log /var/log/nginx/error.log warn; 
    pid /var/run/nginx.pid;
    
    #针对 nginx 句柄的文件限制
    worker_rlimit_nofile 35535;
    #事件模型
    events {
        #使用epoll内核模型
        user epoll;
        #每一个进程可以处理多少个连接,如果是多核可以将连接数调高 worker_processes * 1024
        worker_connections 10240;
    }
    
    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;
    
        charset utf-8;  #设置字符集
    
        #设置日志输出格式,根据自己的情况设置
        log_format  main  '$http_user_agent' '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for" '
                          '"$args" "$request_uri"';
    
        access_log  /var/log/nginx/access.log  main;
    
        sendfile        on;   #对静态资源的处理比较有效
        #tcp_nopush     on;   #如果做静态资源服务器可以打开
        #tcp_nodeny     on;   #当nginx做动态的服务时可以选择打开
    
        keepalive_timeout  65; 
    
        ########
        #Gzip module
        gzip  on;    #文件压缩默认可以打开
        gzip_disable "MSIE [1-6]\."; #对于有些浏览器不能识别压缩,需要过滤如ie6
        gzip_http_version 1.1;
    
        include /etc/nginx/conf.d/*.conf;
    }
    
    #查看 核心绑定的nginx work进程
    [root@server ~]#ps -eo pid,args,psr | grep [n]ginx
    

    6、ab接口压力测试工具

    ab是Apache超文本传输协议(HTTP)的性能测试工具。其设计意图是描绘当前所安装的Apache的执行性能,主要是显示你安装的Apache每秒可以处理多少个请求。

    # 安装工具
    [root@server ~]#yum install httpd-tools
    
    # 使用
    [root@server ~]#ab -n 2000 -c 2 http://127.0.0.1/index.html
    -n 总的请求数
    -c 并发数
    -k 是否开启长连接
    
    1、参数选项
    -n:即requests,用于指定压力测试总共的执行次数
    -c:即concurrency,用于指定的并发数
    -t:即timelimit,等待响应的最大时间(单位:秒)
    -b:即windowsize,TCP发送/接收的缓冲大小(单位:字节)
    -p:即postfile,发送POST请求时需要上传的文件,此外还必须设置-T参数
    -u:即putfile,发送PUT请求时需要上传的文件,此外还必须设置-T参数
    -T:即content-type,用于设置Content-Type请求头信息,例如:application/x-www-form-urlencoded,默认值为text/plain
    -v:即verbosity,指定打印帮助信息的冗余级别
    -w:以HTML表格形式打印结果
    -i:使用HEAD请求代替GET请求
    -x:插入字符串作为table标签的属性
    -y:插入字符串作为tr标签的属性
    -z:插入字符串作为td标签的属性
    -C:添加cookie信息,例如:"Apache=1234"(可以重复该参数选项以添加多个)
    -H:添加任意的请求头,例如:"Accept-Encoding: gzip",请求头将会添加在现有的多个请求头之后(可以重复该参数选项以添加多个)
    -A:添加一个基本的网络认证信息,用户名和密码之间用英文冒号隔开
    -P:添加一个基本的代理认证信息,用户名和密码之间用英文冒号隔开
    -X:指定使用的和端口号,例如:"126.10.10.3:88"
    -V:打印版本号并退出
    -k:使用HTTP的KeepAlive特性
    -d:不显示百分比
    -S:不显示预估和警告信息
    -g:输出结果信息到gnuplot格式的文件中
    -e:输出结果信息到CSV格式的文件中
    -r:指定接收到错误信息时不退出程序
    -H:显示用法信息,其实就是ab -help
    
    2、内容解释
    Server Software:        nginx/1.10.2 (服务器软件名称及版本信息)
    Server Hostname:        192.168.1.106(服务器主机名)
    Server Port:            80 (服务器端口)
    
    Document Path:          /index1.html. (供测试的URL路径)
    Document Length:        3721 bytes (供测试的URL返回的文档大小)
    
    Concurrency Level:      1000 (并发数)
    Time taken for tests:   2.327 seconds (压力测试消耗的总时间)
    Complete requests:      5000 (的总次数)
    Failed requests:        688 (失败的请求数)
    Write errors:           0 (网络连接写入错误数)
    Total transferred:      17402975 bytes (传输的总数据量)
    HTML transferred:       16275725 bytes (HTML文档的总数据量)
    Requests per second:    2148.98 [#/sec] (mean) (平均每秒的请求数) 这个是非常重要的参数数值,服务器的吞吐量 
    Time per request:       465.338 [ms] (mean) (所有并发用户(这里是1000)都请求一次的平均时间)
    Time  request:       	0.247 [ms] (mean, across all concurrent requests) (单个用户请求一次的平均时间)
    Transfer rate:          7304.41 [Kbytes/sec] received 每秒获取的数据长度 (传输速率,单位:KB/s)
    ...
    Percentage of the requests served within a certain time (ms)
      50%    347  ## 50%的请求在347ms内返回 
      66%    401  ## 60%的请求在401ms内返回 
      75%    431
      80%    516
      90%    600
      95%    846
      98%   1571
      99%   1593
     100%   1619 (longest request)
    
    3、示例演示
    [root@server ~]#ab -n 50 -c 20 http://walidream.com/sub_module
    

    输出内容

    Server Software:        nginx/1.14.1
    Server Hostname:        walidream.com
    Server Port:            80
    
    Document Path:          /sub_module
    Document Length:        169 bytes
    
    Concurrency Level:      20
    Time taken for tests:   0.005 seconds
    Complete requests:      50
    Failed requests:        0
    Write errors:           0
    Non-2xx responses:      50
    Total transferred:      14900 bytes
    HTML transferred:       8450 bytes
    Requests per second:    9746.59 [#/sec] (mean)
    Time per request:       2.052 [ms] (mean)
    Time per request:       0.103 [ms] (mean, across all concurrent requests)
    Transfer rate:          2836.41 [Kbytes/sec] received
    
    Connection Times (ms)
                  min  mean[+/-sd] median   max
    Connect:        0    0   0.1      0       1
    Processing:     1    1   0.3      1       2
    Waiting:        0    1   0.2      1       1
    Total:          1    2   0.3      2       2
    
    Percentage of the requests served within a certain time (ms)
      50%      2
      66%      2
      75%      2
      80%      2
      90%      2
      95%      2
      98%      2
      99%      2
     100%      2 (longest request)
    
    5、注意事项

    ● 测试机与被测试机要分开

    ● 不要对线上的服务器做压力测试

    ● 观察测试工具ab所在机器,以及被测试的前端机的CPU、内存、网络等都不超过最高限度的75%

    6、ab性能指标
    1、吞吐率(Requests per second)

    服务器并发处理能力的量化描述,单位是reqs/s,指的是在某个并发用户数下单位时间内处理的请求数。某个并发用户数下单位时间内能处理的最大请求数,称之为最大吞吐率。记住:吞吐率是基于并发用户数的。这句话代表了两个含义:

    ● 吞吐率和并发用户数相关
    
    ● 不同的并发用户数下,吞吐率一般是不同的
    

    计算公式:总请求数/处理完成这些请求数所花费的时间,即

    Request per second=Complete requests/Time taken for tests
    

    必须要说明的是,这个数值表示当前机器的整体性能,值越大越好
    必须要说明的是,这个数值表示当前机器的整体性能,值越大越好

    2、并发连接数(The number of concurrent connections)

    并发连接数指的是某个时刻服务器所接受的请求数目,简单的讲,就是一个会话。

    3、并发用户数(Concurrency Level)

    要注意区分这个概念和并发连接数之间的区别,一个用户可能同时会产生多个会话,也即连接数。在HTTP/1.1下,IE7支持两个并发连接,IE8支持6个并发连接,FireFox3支持4个并发连接,所以相应的,我们的并发用户数就得除以这个基数。

    4.用户平均请求等待时间(Time per request)

    计算公式:处理完成所有请求数所花费的时间/(总请求数/并发用户数),即:

    Time per request=Time taken for tests/(Complete requests/Concurrency Level)
    
    5.服务器平均请求等待时间(Time per request:across all concurrent requests)

    计算公式:处理完成所有请求数所花费的时间/总请求数,即:

    Time taken for/testsComplete requests
    

    可以看到,它是吞吐率的倒数。同时,它也等于用户平均请求等待时间/并发用户数,即

    Time per request/Concurrency Level
    

    7、cfssl 部署 (了解)

    1、下载cfssl工具

    [root@server ~]#wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
    [root@server ~]#chmod +x cfssl_linux-amd64
    [root@server ~]#sudo mv cfssl_linux-amd64 /root/local/bin/cfssl
     
    [root@server ~]#wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
    [root@server ~]#chmod +x cfssljson_linux-amd64
    [root@server ~]#sudo mv cfssljson_linux-amd64 /root/local/bin/cfssljson
     
    [root@server ~]#wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
    [root@server ~]#chmod +x cfssl-certinfo_linux-amd64
    [root@server ~]#sudo mv cfssl-certinfo_linux-amd64 /root/local/bin/cfssl-certinfo
     
    [root@server ~]#export PATH=/root/local/bin:$PATH
    
    

    2、生成默认的配置文件和证书签名请求文件

    [root@server ~]#cfssl print-defaults config > ca-config.json
    [root@server ~]#cfssl print-defaults csr > ca-csr.json
    
    1、查看并修改CA 配置文件
    [root@server ~]#cat ca-config.json 
    {
        "signing": {
            "default": {
                "expiry": "9999h"
            },
            "profiles": {
                "www": {
                    "expiry": "9999h",
                    "usages": [
                        "signing",
                        "key encipherment",
                        "server auth"
                    ]
                },
                "client": {
                    "expiry": "9999h",
                    "usages": [
                        "signing",
                        "key encipherment",
                        "client auth"
                    ]
                }
            }
        }
    }
    
    • ca-config.json:可以定义多个 profiles,分别指定不同的过期时间、使用场景等参数;后续在签名证书时使用某个 profile;

    • signing:表示该证书可用于签名其它证书;生成的 ca.pem 证书中 CA=TRUE

    • server auth:表示 client 可以用该 CA 对 server 提供的证书进行验证;

    • client auth:表示 server 可以用该 CA 对 client 提供的证书进行验证;

    2、查看并修改 CA 证书签名请求
    {
      "CN": "registry.test.com",
      "hosts": [
        "127.0.0.1",
        "172.16.160.38",
        "registry.test.com"
      ],
      "key": {
        "algo": "rsa",
        "size": 2048
      },
      "names": [
        {
          "C": "CN",
          "ST": "BeiJing",
          "L": "BeiJing",
          "O": "k8s",
          "OU": "System"
        }
      ]
    }
    
    • “CN”:Common Name,kube-apiserver 从证书中提取该字段作为请求的用户名 (User Name);浏览器使用该字段验证网站是否合法;

    • “O”:Organization,kube-apiserver 从证书中提取该字段作为请求用户所属的组 (Group);

    3、生成 CA 证书和私钥
    [root@server ~]#cfssl gencert -initca ca-csr.json | cfssljson -bare ca    #重新执行
    [root@server ~]#ls ca*
    ca-config.json  ca.csr  ca-csr.json  ca-key.pem  ca.pem
    
    4、分发证书

    3、校验证书

    1、使用 openssl 命令校验证书
    [root@server ~]#openssl x509  -noout -text -in  kubernetes.pem
    ...
        Signature Algorithm: sha256WithRSAEncryption
            Issuer: C=CN, ST=BeiJing, L=BeiJing, O=k8s, OU=System, CN=Kubernetes
            Validity
                Not Before: Apr  5 05:36:00 2017 GMT
                Not After : Apr  5 05:36:00 2018 GMT
            Subject: C=CN, ST=BeiJing, L=BeiJing, O=k8s, OU=System, CN=kubernetes
    ...
            X509v3 extensions:
                X509v3 Key Usage: critical
                    Digital Signature, Key Encipherment
                X509v3 Extended Key Usage:
                    TLS Web Server Authentication, TLS Web Client Authentication
                X509v3 Basic Constraints: critical
                    CA:FALSE
                X509v3 Subject Key Identifier:
                    DD:52:04:43:10:13:A9:29:24:17:3A:0E:D7:14:DB:36:F8:6C:E0:E0
                X509v3 Authority Key Identifier:
                    keyid:44:04:3B:60:BD:69:78:14:68:AF:A0:41:13:F6:17:07:13:63:58:CD
     
                X509v3 Subject Alternative Name:
                    DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.cluster, DNS:kubernetes.default.svc.cluster.local, IP Address:127.0.0.1, IP Address:10.64.3.7, IP Address:10.254.0.1
    ...
     
     
    + 确认 `Issuer` 字段的内容和 `ca-csr.json` 一致;
    + 确认 `Subject` 字段的内容和 `kubernetes-csr.json` 一致;
    + 确认 `X509v3 Subject Alternative Name` 字段的内容和 `kubernetes-csr.json` 一致;
    + 确认 `X509v3 Key Usage、Extended Key Usage` 字段的内容和 `ca-config.json``kubernetes` profile 一致;
    
    2、使用 cfssl-certinfo 命令校验证书
    [root@server ~]#cfssl-certinfo -cert kubernetes.pem
    ...
    {
      "subject": {
        "common_name": "kubernetes",
        "country": "CN",
        "organization": "k8s",
        "organizational_unit": "System",
        "locality": "BeiJing",
        "province": "BeiJing",
        "names": [
          "CN",
          "BeiJing",
          "BeiJing",
          "k8s",
          "System",
          "kubernetes"
        ]
      },
      "issuer": {
        "common_name": "Kubernetes",
        "country": "CN",
        "organization": "k8s",
        "organizational_unit": "System",
        "locality": "BeiJing",
        "province": "BeiJing",
        "names": [
          "CN",
          "BeiJing",
          "BeiJing",
          "k8s",
          "System",
          "Kubernetes"
        ]
      },
      "serial_number": "174360492872423263473151971632292895707129022309",
      "sans": [
        "kubernetes",
        "kubernetes.default",
        "kubernetes.default.svc",
        "kubernetes.default.svc.cluster",
        "kubernetes.default.svc.cluster.local",
        "127.0.0.1",
        "10.64.3.7",
        "10.64.3.8",
        "10.66.3.86",
        "10.254.0.1"
      ],
      "not_before": "2017-04-05T05:36:00Z",
      "not_after": "2018-04-05T05:36:00Z",
      "sigalg": "SHA256WithRSA",
    ...
    
    3、使用浏览器验证

    导入证书

    ​ ca.pem改名为ca.crt。将正式导入浏览器。

    构建https服务

    [root@server ~]#cd /root/ssl_test
    [root@server ~]#cat > http-server.js <<EOF
    var https = require('https');
    var fs = require('fs');
     
    var options = {
        key: fs.readFileSync('./keys/app-key.pem'),
        cert: fs.readFileSync('./keys/app.pem')
    };
     
    https.createServer(options, function (req, res) {
        res.writeHead(200);
        res.end('hello world');
    }).listen(8000);
    EOF
     
    [root@server ~]#yum install nodejs -y
    [root@server ~]#npm install https -g
    [root@server ~]#node http-server.js
    

    修改hosts文件添加

    172.16.160.28 www.test.com
    

    在浏览器访问https://www.test.com:8000 发现网站显示为安全

    4、附加内容

    数字证书中主题(Subject)中字段的含义

    • 一般的数字证书产品的主题通常含有如下字段:
    字段名字段值
    公用名称 (Common Name)简称:CN 字段,对于 SSL 证书,一般为网站域名;而对于代码签名证书则为申请单位名称;而对于客户端证书则为证书申请者的姓名;
    单位名称 (Organization Name)简称:O 字段,对于 SSL 证书,一般为网站域名;而对于代码签名证书则为申请单位名称;而对于客户端单位证书则为证书申请者所在单位名称;
    • 证书申请单位所在地
    字段名字段值
    所在城市 (Locality)简称:L 字段
    所在省份 (State/Provice)简称:S 字段
    所在国家 (Country)简称:C 字段,只能是国家字母缩写,如中国:CN
    • 其他一些字段
    字段名字段值
    电子邮件 (Email)简称:E 字段
    多个姓名字段简称:G 字段
    介绍Description 字段
    电话号码:Phone 字段,格式要求 + 国家区号 城市区号 电话号码,如: +86 732 88888888
    地址:STREET 字段
    邮政编码:PostalCode 字段
    显示其他内容简称:OU 字段

    例子:

    [root@server ca]#cat ca-config.json 
    {
        "signing": {
            "default": {
                "expiry": "9999h"
            },
            "profiles": {
                "www": {
                    "expiry": "9999h",
                    "usages": [
                        "signing",
                        "key encipherment",
                        "server auth"
                    ]
                },
                "client": {
                    "expiry": "9999h",
                    "usages": [
                        "signing",
                        "key encipherment",
                        "client auth"
                    ]
                }
            }
        }
    }
     
    [root@server ca]#cat ca-csr.json 
    {
      "CN": "registry.test.com",
      "hosts": [
        "127.0.0.1",
        "172.16.160.38",
        "registry.test.com"
      ],
      "key": {
        "algo": "rsa",
        "size": 2048
      },
      "names": [
        {
          "C": "CN",
          "ST": "BeiJing",
          "L": "BeiJing",
          "O": "k8s",
          "OU": "System"
        }
      ]
    }
     
    [root@server ca]#ll
    总用量 8
    -rw-r--r-- 1 root root 568 11月 14 15:59 ca-config.json
    -rw-r--r-- 1 root root 289 11月 14 16:02 ca-csr.json
     
    [root@dev ca]# cfssl gencert -initca ca-csr.json | cfssljson -bare ca
    2018/11/14 16:05:01 [INFO] generating a new CA key and certificate from CSR
    2018/11/14 16:05:01 [INFO] generate received request
    2018/11/14 16:05:01 [INFO] received CSR
    2018/11/14 16:05:01 [INFO] generating key: rsa-2048
    2018/11/14 16:05:01 [INFO] encoded CSR
    2018/11/14 16:05:01 [INFO] signed certificate with serial number 303515642193399207794287652931621857332460556169
     
    [root@server ca]#ll
    总用量 20
    -rw-r--r-- 1 root root  568 11月 14 15:59 ca-config.json
    -rw-r--r-- 1 root root 1082 11月 14 16:05 ca.csr
    -rw-r--r-- 1 root root  289 11月 14 16:02 ca-csr.json
    -rw------- 1 root root 1679 11月 14 16:05 ca-key.pem
    -rw-r--r-- 1 root root 1379 11月 14 16:05 ca.pem
     
     
    [root@server ~]#openssl x509  -noout -text -in ca.pem
    Certificate:
        Data:
            Version: 3 (0x2)
            Serial Number:
                35:2a:1c:b2:f6:1a:f3:82:38:50:05:8c:fb:65:ef:9e:89:74:8f:89
        Signature Algorithm: sha256WithRSAEncryption
            Issuer: C=CN, ST=BeiJing, L=BeiJing, O=k8s, OU=System, CN=harbor
            Validity
                Not Before: Nov 14 08:00:00 2018 GMT
                Not After : Nov 13 08:00:00 2023 GMT
            Subject: C=CN, ST=BeiJing, L=BeiJing, O=k8s, OU=System, CN=harbor
            Subject Public Key Info:
                Public Key Algorithm: rsaEncryption
                    Public-Key: (2048 bit)
                    Modulus:
                        00:b7:2e:6a:52:f4:d2:34:8b:5e:3f:95:5d:c8:b0:
                        85:9a:1b:ef:c5:0f:1b:94:b9:94:12:fe:fa:66:0d:
                        8c:67:b8:9e:82:30:fc:e1:42:94:6e:00:fb:c0:fd:
                        84:be:65:2c:e4:8f:f1:f1:93:e5:ae:8e:5b:74:7a:
                        d5:94:25:9c:01:76:f9:96:4e:02:b9:27:a2:44:e0:
                        da:b3:f3:09:82:5c:9f:26:a6:26:54:35:15:e6:a6:
                        7a:4b:14:99:07:9d:e3:c3:b8:bd:3f:b6:76:53:05:
                        82:02:bb:e2:61:21:23:5b:3b:23:4c:08:eb:a7:51:
                        00:fb:01:5f:b7:f8:b9:67:5b:a1:99:19:23:42:7a:
                        d2:22:0a:11:01:1d:75:34:9e:25:9c:c8:9f:31:d7:
                        f5:f3:98:14:b8:c4:07:f3:5a:a1:fa:96:bd:0f:b3:
                        dc:13:5b:8e:03:e8:66:3b:b5:bd:8d:08:ee:61:c2:
                        4f:78:dc:9a:ee:37:f8:87:6b:5f:e3:87:ae:91:b0:
                        8c:c9:40:51:44:cb:57:47:23:f1:2d:34:af:0f:5f:
                        42:89:14:ac:de:73:d4:32:54:c2:de:99:38:96:d4:
                        b8:de:f3:df:5c:a5:55:54:8f:a1:b7:fa:42:8b:d9:
                        fe:2d:14:1f:d5:62:d9:c7:c1:4d:55:41:3b:a9:d3:
                        0d:2d
                    Exponent: 65537 (0x10001)
            X509v3 extensions:
                X509v3 Key Usage: critical
                    Certificate Sign, CRL Sign
                X509v3 Basic Constraints: critical
                    CA:TRUE, pathlen:2
                X509v3 Subject Key Identifier: 
                    15:1F:81:A2:AC:41:18:DA:DD:19:36:03:61:18:7B:EF:3D:94:10:AE
                X509v3 Authority Key Identifier: 
                    keyid:15:1F:81:A2:AC:41:18:DA:DD:19:36:03:61:18:7B:EF:3D:94:10:AE
     
                X509v3 Subject Alternative Name: 
                    IP Address:127.0.0.1, IP Address:172.16.160.38
        Signature Algorithm: sha256WithRSAEncryption
             62:41:3c:40:6d:91:29:d2:0b:6d:ce:08:a1:e4:47:64:0a:66:
             0e:c0:55:eb:c4:6b:30:6d:79:51:b4:97:8c:02:1e:15:ba:0f:
             84:ce:2a:3c:c7:86:29:3c:1f:55:35:a1:da:df:70:5d:58:93:
             45:24:c4:20:4d:c1:c7:bb:83:8d:52:0c:7d:43:e2:7c:5b:00:
             5d:57:5a:b5:bf:d0:56:5a:57:32:ca:fc:29:59:23:ab:5e:1e:
             0e:9b:f9:f6:8d:e8:e4:c6:cb:e6:fe:9f:e3:cd:55:2e:7b:35:
             1e:bc:80:0f:ba:d8:66:ae:43:19:bf:d1:bb:81:17:d6:4a:3b:
             01:ba:d4:28:da:3f:19:63:82:72:6f:df:7a:b4:bc:d4:cf:a9:
             b1:fc:a6:c7:c1:5d:9b:09:2e:72:2a:d4:18:ed:f4:3d:97:1e:
             e6:43:81:5c:eb:40:2c:f9:aa:6f:90:16:70:46:77:52:09:64:
             43:83:00:0c:44:59:de:17:65:7b:7e:3d:51:df:54:6e:bb:80:
             cb:22:13:e2:20:80:91:f8:3f:5e:83:70:32:68:ad:ad:7e:4a:
             15:32:45:a7:a5:c4:ed:1c:d4:e4:cc:38:ac:8a:9d:d1:bb:4e:
             1c:21:17:56:a2:a0:f9:39:f3:73:e4:96:00:ac:98:93:f3:80:
             96:9d:b5:97
    [root@dev ca]#
    

    如果出现

    [root@server ~]#docker login registry.test.com
    Username (admin): admin
    Password: 
    Error response from daemon: Get https://registry.mayocase.com/v1/users/: x509: certificate signed by unknown authority
    

    检查下目录/etc/docker/certs.d/registry.test.com下是否有ca.crt文件,可能需要重启docker

    [root@server ~]#cp ca.pem /etc/docker/certs.d/registry.test.com/ca.crt
    [root@server ~]#systemctl restart docker
    

    修改harbor证书后操作:

    [root@server ~]#cd /data/harbor    #一定要在此目录下运行以下命令。
    [root@server ~]#ll
    总用量 878344
    drwxr-xr-x 4 root root        35 7月  31 2017 common
    -rw-r--r-- 1 root root      1988 7月  31 2017 docker-compose.notary.yml
    -rw-r--r-- 1 root root      3155 7月  31 2017 docker-compose.yml
    -rw-r--r-- 1 root root      4304 7月  31 2017 harbor_1_1_0_template
    -rw-r--r-- 1 root root      4178 7月  31 2017 harbor.cfg
    -rw-r--r-- 1 root root      1082 7月  31 2017 harbor.csr
    -rw-r--r-- 1 root root       288 7月  31 2017 harbor-csr.json
    -rw-r--r-- 1 root root 448963966 7月  31 2017 harbor.v1.1.1.tar.gz
    -rw-r--r-- 1 root root 450041094 7月  31 2017 harbor.v1.1.2.tar.gz
    -rwxr-xr-x 1 root root      5169 7月  31 2017 install.sh
    -rw-r--r-- 1 root root    337600 7月  31 2017 LICENSE
    -rw-r--r-- 1 root root       472 7月  31 2017 NOTICE
    -rwxr-xr-x 1 root root     16522 7月  31 2017 prepare
    -rwxr-xr-x 1 root root      4550 7月  31 2017 upgrade 
    # 停止 harbor
    [root@server harbor]# docker-compose down -v        #多运行几次直到所有docker都删除
    # 修改配置
    [root@server harbor]# vim harbor.cfg
    # 更修改的配置更新到 docker-compose.yml 文件
    [root@server harbor]# ./prepare
    # 启动 harbor
    [root@server harbor]#  docker-compose up -d
    

    8、特例: https 为什么慢,把nginx 跑到 qat 卡上

    Intel QAT 助力 Nginx 压缩处理

    1、什么是Intel® QAT?

    Intel® QuickAssist Technology是Intel®公司提供的一种高性能数据安全和压缩的加速方案。该方案利用QAT芯片分担对称/非对称加密计算,DEFLATE无损压缩等大计算量的任务,来降低CPU使用率并提高整体平台性能。该方案可以主板芯片,独立的PCI-E加速卡或者SOC三种方式部署。

    QAT支持硬件加速Deflate无损压缩算法,在处理海量数据时,QAT在不增加CPU开销的前提下,通过压缩来减少需要传输和存盘的数据量,从而减少了网络带宽和磁盘读写的开销,最终提高了整体的系统性能。 例如,在Web Serer上使用QAT硬件加速压缩处理,可将CPU从繁重的压缩计算中解放出来,以处理更多的连接请求。

    2、什么是Nginx Web Server

    Nginx(发音同engine x)是一款使用异步框架的高性能Web服务器,相较于Apache、lighttpd等其他Web Server,Nginx具有占有内存少,稳定性高等优势。根据Netcraft 2018年一月的Web Server市场调查报告, Nginx的装机率达25.39%,位列Web Server市场第三,并在持续增长中[1]。

    Nginx中的GZIP模块实现了对HTTP压缩的支持,该模块通过调用Zlib库实现对网页内容进行Deflate压缩。由于使用软件实现无损压缩,需要消耗大量CPU运算时间进行压缩运算。

    然而,在大并发流量的网站接入层的Nginx需要处理相当多的业务,包括https连接建立,安防攻击,流量镜像,链路追踪等等。使得CPU进行HTTP压缩处理成为Web Server最主要的CPU开销,进而限制了网站支持最大并发连接数。根据客户提供的接入层流量模型分析来看, GZIP 单个模块 CPU 消耗占比达到 15%-20% 左右,且占比呈上升趋势。所以,若能使用加速Nginx的网页压缩处理,可以极大的提高网站性能。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iBGF86Oi-1592399674118)(assets/1-1.jpg)]

    3、Zlib-SHIM API

    Zlib作为广泛部署的软件压缩库,提供Deflate压缩的软件实现,被包括Nginx在内的广大应用程序所采用。Intel® QuickAssist Technology提供了与Zlib类似接口的Zlib-SHIM 软件库来适配上层应用,减少了应用迁移的开发量。该库提供了与Zlib一致的Deflate API,只需对源代码做少量修改,并将原有应用与Zlib-SHIM编译链接,就能使用QuickAssit提供的硬件加速功能。

    Zlib-SHIM库实现了DeflateInit,DeflateInit2,Deflate,DeflateEnd等常用API并支持Stateful和Stateless压缩,可以替代Zlib的绝大部分功能。

    Zlib-SHIM提供了Deflate API同步模式接口(调用程序阻塞在Deflate API上,直到压缩任务完成),而其内部实现调用了异步模式API,即在CPU上运行的QAT驱动程序向QAT协处理器提交了一个数据压缩请求后即返回,期间使用Polling 接口定期检查压缩请求是否完成,等到QAT硬件完成压缩处理后通过回调函数通知CPU端的应用程序进行下一步操作。这样的设计, 在不影响上层应用程序原有设计的前提下,实现了高并发场景中CPU和QAT的协同工作:CPU专注于网络链接处理而QAT处理复杂的压缩计算, 各司其职,最终提高了系统整体性能。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jaDbTTHK-1592399674126)(assets/2-1552557277602.png)]Zlib-SHIM 层次图

    4、Zlib-SHIM工作原理

    采用这种异步模式API实现对外的同步接口,在实现上有三种方法:Direct Polling,Indirect Polling Spinning和Indirect Polling Semaphore模式。

    使用Direct Polling模式时,Deflate调用者会在当前线程直接调用Polling接口,若压缩结果还没有返回则休眠一段时间后再检查,直到压缩成功后Deflate 调用才返回。Direct Polling模式下CPU开销小,但是单个Request从发出到返回结果延迟较长,只有在多进程多线程高并发模式下才能充分发挥QAT的压缩性能。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Yh8xtUpC-1592399674126)(assets/3.png)]Direct polling 模式流程图

    Indirect Polling模式,是通过创建一个轮询线程定期调用Polling接口来检查压缩请求在QAT 协处理器中的执行状态,轮询线程一旦发现有请求执行完毕就通过回调函数(Callback Function)通知CPU端程序进行后续处理。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XkwCXwdA-1592399674128)(assets/4-1.png)]

    Indirect pooling模式时序图

    根据回调通知方式的不同,Indirect Polling模式又可细分为Spinning模式和Semaphore模式:

    Spinning模式中,Deflate函数调用线程定期轮询与回调函数共享的任务完成标志,若尚未完成则主动休眠,若已完成则进行后续处理。

    Semaphore模式中,Deflate调用线程通过互斥锁来隔离与轮询线程共享的任务完成标志的访问操作,若任务尚未完成则Deflate调用线程休眠,一旦任务完成,轮询线程中的回调函数会通过信号量唤醒调用线程进行后续处理。

    采用Indirect Polling模式无论Deflate调用数目多少都需要启动轮询线程,在压缩请求数不大的情况下增加了CPU的Polling开销,但是当压缩任务作为CPU的主要任务时可以减少不必要的Polling调用,提高CPU的使用率。

    Nginx为了实现高性能的高并发处理能采用了单进程单线程异步工作模式,如果使用Indirect Polling模式,就需要在每个Nginx Worker进程中创建一个轮询线程 (Polling Thread), 从而增加了线程间切换的开销和共享数据的互斥的操作, 所以在Nginx和Zlib-SHIM集成中,我们使用了Direct Polling Mode。

    5、USDM优化

    USDM是QAT为了优化内存使用效率而提供的用户态内存管理工具。由于QAT和CPU之前需要频繁高速的交换数据,使用传统的Memory Copy方式不仅效率低而且消耗CPU资源,所以QAT支持DMA方式进行数据传输,CPU只需分配好拥有物理连续内存的输入地址和输出地址,QAT会自动完成的从该地址的输入读取或输出写回的操作。QAT Driver中的USDM模块,利用了Linux 内核提供的Huge-Page特性来获得物理地址连续内存并使用SLAB算法进行内存管理。

    对于每一个新分配的Huge-Page,USDM会对应地在Devfs中新建一个临时文件,并通过mmap将临时文件描述符与新申请到的Huge-Page关联上,当USDM发现该Huge-Page上所有内存块均已释放,并不需将其留作缓存时,就关闭该临时文件以释放Huge-Page。当Zlib-SHIM运行过程中需要使用连续的内存时,就使用USDM Alloc接口从内存池中申请连续物理地址的内存, 并在发送压缩请求时将申请到的连续内存地址作为参数传递给QAT。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ihKd2D5t-1592399674129)(assets/5-1.jpg)]USDM DMA传输

    6、测试结果

    基于以上设计的Zlib-SHIM可以很方便的替换原有Zlib库,使得调用者可以方便的利用QAT进行压缩加速。 在实际应用中, 客户就是将Zlib-SHIM与基于Nginx定制的Web Server进行集成,在接入层的性能优化上取得了理想的效果。

    客户的Web Server运行在Intel® Xeon® CPU上(CPU型号:Intel® Xeon® CPU E5-2650 v2 @ 2.60GHz 32核 内核:2.6.32 Zlib版本:zlib-1.2.8 QAT驱动版本:intel-qatOOT40052 ),在相同网络流量条件下,未开启QAT加速的CPU平均使用率为48%左右,而开启QAT加速后CPU平均使用率为41%左右。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vDsJsoHO-1592399674130)(assets/6-1.jpg)]CPU使用率对比[2]

    相同条件下,开启QAT加速后系统load平均值为12.09,关闭QAT加速时系统load平均值为14.22,如下图所示:
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XlpD74vD-1592399674130)(assets/7-1.jpg)]系统load对比[2]

    综合以上数据,Web Server在QPS 10K的压力下,使用QAT加速后可以节省CPU 15%左右,且Gzip基本上完全卸载、随着其占比变高,优化效果将越好。

    7、总结

    拥有和Zlib相同API接口的Zlib-SHIM可以很方便的与上层应用集成,利用QAT的硬件加速性能。此外,为了最大限度的发挥QAT的新能,Intel还提供了使用专有API的QATzip软件库,相应的Nginx module也在开发中,相信不久的将来集成QATzip的Web Server能够提供更好的性能。

    性能测试中使用的软件和工作负荷可能仅在英特尔微处理器上进行了性能优化。诸如SYSmark和MobileMark等测试均系基于特定计算机系统、硬件、软件、操作系统及功能。上述任何要素的变动都有可能导致测试结果的变化。请参考其他信息及性能测试(包括结合其他产品使用时的运行性能)以对目标产品进行全面评估。

    展开全文
  • 控制全局变量初始化顺序转自:http://nathan.xuli.googlepages.com/cpp_global 全局变量的初始化分两种。一种是static initialization,用常量来初始化,在程序被load的时侯就完成了。另一种就是dynamic ...

    控制全局变量初始化顺序

    转自:http://nathan.xuli.googlepages.com/cpp_global 

            全局变量的初始化分两种。一种是static initialization,用常量来初始化,在程序被load的时侯就完成了。另一种就是dynamic initialization,简单地说就是需要调一个函数来执行初始化,在CRT的启动代码中会完成这个工作。我要说的就是后一种类型的全局变量。这种类型的全局变量的初始化顺序是由链接器处理translation unit的顺序决定的,对我们而言,它是不定的。所以最好不要写出全局变量初始化顺序有依赖关系的代码。
            
    在学习了一些Linker的知识后(参见我的两篇译文Linker In-DepthUnder The Hood: Reduce EXE and DLL Size with LIBCTINY.LIB),我偶而想到了一种可以控制全局变量初始化顺序的方法。关键是使用"#pragma init_seg"指令(只有VC才有吧?不知道别的编译器里是否有对等的东西)。关于#pragma init_seg的用法我就不多说了,请自行查阅MSDN吧,里面还有一个不错的例子。
            
    举例说明,假设我有如下的代码:

    // a.cpp

    CTest1 g_test1 ;

     

    // b.cpp

    CTest2 g_test2 ;

             在两个cpp文件中分别定义了一个全局变量,你无法明确指出g_test1g_test2谁先谁后,现在假设g_test1g_test2之前初始化,那么修改代码如下:

    // a.cpp

    #pragma init_seg(".CRT$XCD")
    CTest1 g_test1 ;

    // b.cpp

    #pragma init_seg(".CRT$XCC")
    CTest2 g_test2 ;

             我现在可以肯定的说,g_test2g_test1之前初始化!
            
    道理其实也很简单,Linker有以下几条规则:

             (1)
    指向全局变量初始化代码的指针被放到.CRT$XCU节中。
             (2)
    链接器会合并所有相同名字的节。
             (3)
    section名字中含有$符号时,链接器把$之前的名字做为最终的节名,$之后的字符串的字典顺序将作为相同名字的节合并时的依据。
            
    除此以外,VC的运行时库中已经定义了两个节:.CRT$XCA.CRT$XCZ,并且在每个节中分别定义了一个变量:__xc_a__xc_z。这样.CRT$XCU中的数据以及__xc_a__xc_z就构成一个function pointer table__xc_a__xc_z分别标识头和尾。_initterm函数遍历这个数组,调用每个函数指针,全局变量的初始化工作就是这样完成的。(参考cinitexe.c文件)
            
    在上面的代码中,g_test2定义在.CRT$XCC中,g_test1定义在.CRT$XCD中,按照上面的规则,.CRT$XCC将排在.CRT$XCD前面,所以g_test2将在g_test1之前初始化!
            
    Microsoft Knowledge Base Article Q104248中也讨论了使用#pragma init_seg控制初始化顺序的方法,但它利用的是链接器三个不同的option所提供的能力,即:#pragma init_seg(compiler)#pragma init_seg(lib)#pragma init_seg(user)。没有我这种方法控制力强。在.CRT$XCA.CRT$XCZ之间还有BY24个级别可供我利用,嘿!

    #pragma详解

    转自:http://blog.chinaunix.net/u1/41728/showart_454778.html

    #Pragma是预处理指令它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作。#pragma指令对每个编译器给出了一个方法,在保持与CC ++语言完全兼容的情况下,给出主机或操作系统专有的特征。依据定义,编译指示是机器
    或操作系统专有的,且对于每个编译器都是不同的。
    其格式一般为: #Pragma Para
    其中Para 为参数,下面来看一些常用的参数。

    (1)message
    参数。 Message 参数是我最喜欢的一个参数,它能够在编译信息输出窗
    口中输出相应的信息,这对于源代码信息的控制是非常重要的。其使用方法为:
    #Pragma message(“
    消息文本”)
    当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来。

    当我们在程序中定义了许多宏来控制源代码版本的时候,我们自己有可能都会忘记有没有正
    确的设置这些宏,此时我们可以用这条指令在编译的时候就进行检查。假设我们希望判断自
    己有没有在源代码的什么地方定义了_X86这个宏可以用下面的方法
    #ifdef _X86
    #Pragma message(“_X86 macro activated!”)
    #endif
    当我们定义了_X86这个宏以后,应用程序在编译时就会在编译输出窗口里显示“_
    X86 macro activated!”
    。我们就不会因为不记得自己定义的一些特定的宏而抓耳挠腮了。


    (2)
    另一个使用得比较多的pragma参数是code_seg。格式如:
    #pragma code_seg( [/section-name/[,/section-class/] ] )
    它能够设置程序中函数代码存放的代码段,使用没有section-name字符串的#pragmacode_seg可在编译开始时将其复位,当我们开发驱动程序的时候就会使用到它。

    (3)#pragma once (
    比较常用)
    只要在头文件的最开始加入这条指令就能够保证头文件被编译一次,这条指令实际上在VC6
    中就已经有了,但是考虑到兼容性并没有太多的使用它。


    (4)#pragma hdrstop
    表示预编译头文件到此为止,后面的头文件不进行预编译。BCB可以预
    编译头文件以加快链接的速度,但如果所有头文件都进行预编译又可能占太多磁盘空间,所
    以使用这个选项排除一些头文件。
    有时单元之间有依赖关系,比如单元A依赖单元B,所以单元B要先于单元A编译。你可以用#p
    ragma startup
    指定编译优先级,如果使用了#pragma package(smart_init) BCB就会根据优先级的大小先后编译。


    (5)#pragma resource /*.dfm/
    表示把*.dfm文件中的资源加入工程。*.dfm中包括窗体
    外观的定义。

    (6
    #pragma warning( disable : 4507 34; once : 4385; error : 164 )
    等价于:

    #pragma warning(disable:4507 34) //
    不显示450734号警告信息
    #pragma warning(once:4385) // 4385
    号警告信息仅报告一次
    #pragma warning(error:164) //
    164号警告信息作为一个错误。
    同时这个pragma warning 也支持如下格式:
    #pragma warning( push [ ,n ] )
    #pragma warning( pop )
    这里n代表一个警告等级(1---4)
    #pragma warning( push )
    保存所有警告信息的现有的警告状态。
    #pragma warning( push, n)
    保存所有警告信息的现有的警告状态,并且把全局警告
    等级设定为n
    #pragma warning( pop )
    向栈中弹出最后一个警告信息,在入栈和出栈之间所作的
    一切改动取消。例如:
    #pragma warning( push )
    #pragma warning( disable : 4705 )
    #pragma warning( disable : 4706 )
    #pragma warning( disable : 4707 )
    //.......
    #pragma warning( pop )
    在这段代码的最后,重新保存所有的警告信息(包括470547064707)

    7pragma comment(...)
    该指令将一个注释记录放入一个对象文件或可执行文件中。

    常用的lib关键字,可以帮我们连入一个库文件。

    8·通过#pragma pack(n)改变C编译器的字节对齐方式
    C语言中,结构是一种复合数据类型,其构成元素既可以是基本数据类型(如int
    long
    float等)的变量,也可以是一些复合数据类型(如数组、结构、联合等)的
    数据单元。在结构中,编译器为结构的每个成员按其自然对界(alignment)条件分
    配空间。各个成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和
    整个结构的地址相同。
    例如,下面的结构各成员空间分配情况:
    struct test
    {
            char x1;
            short x2;
            float x3;
            char x4;
    };
           
    结构的第一个成员x1,其偏移地址为0,占据了第1个字节。第二个成员x2
    short
    类型,其起始地址必须2字节对界,因此,编译器在x2x1之间填充了一个
    空字节。结构的第三个成员x3和第四个成员x4恰好落在其自然对界地址上,在它
    们前面不需要额外的填充字节。在test结构中,成员x3要求4字节对界,是该结构
    所有成员中要求的最大对界单元,因而test结构的自然对界条件为4字节,编译器
    在成员x4后面填充了3个空字节。整个结构所占据空间为12字节。更改C编译器的
    缺省字节对齐方式
          
    在缺省情况下,C编译器为每一个变量或是数据单元按其自然对界条件分配
    空间。一般地,可以通过下面的方法来改变缺省的对界条件:
      · 使用伪指令#pragma pack (n)C编译器将按照n个字节对齐。
            ·
    使用伪指令#pragma pack (),取消自定义字节对齐方式。
           
    另外,还有如下的一种方式:
            · __attribute((aligned (n)))
    ,让所作用的结构成员对齐在n字节自然边界上。
    如果结构中有成员的长度大于n,则按照最大成员的长度来对齐。
            · __attribute__ ((packed))
    ,取消结构在编译过程中的优化对齐,按照实际
    占用字节数进行对齐。
    以上的n = 1, 2, 4, 8, 16... 第一种方式较为常见。
    应用实例
      在网络协议编程中,经常会处理不同协议的数据报文。一种方法是通过指针偏移的
    方法来得到各种信息,但这样做不仅编程复杂,而且一旦协议有变化,程序修改起来
    也比较麻烦。在了解了编译器对结构空间的分配原则之后,我们完全可以利用这
    一特性定义自己的协议结构,通过访问结构的成员来获取各种信息。这样做,
    不仅简化了编程,而且即使协议发生变化,我们也只需修改协议结构的定义即可,
    其它程序无需修改,省时省力。下面以TCP协议首部为例,说明如何定义协议结构。
    其协议结构定义如下:
    #pragma pack(1) //
    按照1字节方式进行对齐
    struct TCPHEADER
    {
            short SrcPort; // 16
    位源端口号
            short DstPort; // 16
    位目的端口号
            int SerialNo; // 32
    位序列号
            int AckNo; // 32
    位确认号
            unsigned char HaderLen : 4; // 4
    位首部长度
            unsigned char Reserved1 : 4; //
    保留6位中的4
            unsigned char Reserved2 : 2; //
    保留6位中的2
            unsigned char URG : 1;
            unsigned char ACK : 1;
            unsigned char PSH : 1;
            unsigned char RST : 1;
            unsigned char SYN : 1;
            unsigned char FIN : 1;
            short WindowSize; // 16
    位窗口大小
            short TcpChkSum; // 16
    TCP检验和
            short UrgentPointer; // 16
    位紧急指针
    };
    #pragma pack() //
    取消1字节对齐方式 

    指定连接要使用的库
    比如我们连接的时候用到了 WSock32.lib,你当然可以不辞辛苦地把它加入到你的工程中。但是我觉得更方便的方法是使用 #pragma 指示符,指定要连接的库:
    #pragma comment(lib, "WSock32.lib")

     

    附加:

    每种CC++的实现支持对其宿主机或操作系统唯一的功能。例如,一些程序需要精确控制超出数据所在的储存空间,或着控制特定函数接受参数的方式。#pragma指示使每个编译程序在保留CC++语言的整体兼容性时提供不同机器和操作系统特定的功能。编译指示被定义为机器或操作系统特定的,并且通常每种编译程序是不同的。

    语法:

    #pragma token_string

    “token_string”是一系列字符用来给出所需的特定编译程序指令和参数。数字符号“#”必须是包含编译指令的行中第一个非空白字符;而空白字符可以隔开数字符号“#”和关键字“pragma”。在#pragma后面,写任何翻译程序能够作为预处理符号分析的文本。#pragma的参数类似于宏扩展。

    如果编译程序发现它不认得一个编译指示,它将给出一个警告,可是编译会继续下去。

    为了提供新的预处理功能,或者为编译程序提供由实现定义的信息,编译指示可以用在一个条件语句内。CC++编译程序可以识别下列编译程序指令。

    alloc_text

    comment

    init_seg*

    optimize

    auto_inline

    component

    inline_depth

    pack

    bss_seg

    data_seg

    inline_recursion

    pointers_to_members*

    check_stack

    function

    intrinsic

    setlocale

    code_seg

    hdrstop

    message

    vtordisp*

    const_seg

    include_alias

    once

    warning

    *仅用于C++编译程序。

    1  alloc_text

    #pragma alloc_text( "textsection", function1, ... )

    命名特别定义的函数驻留的代码段。该编译指示必须出现在函数说明符和函数定义之间。

    alloc_text编译指示不处理C++成员函数或重载函数。它仅能应用在以C连接方式说明的函数——就是说,函数是用extern "C"连接指示符说明的。如果你试图将这个编译指示应用于一个具有C++连接方式的函数时,将出现一个编译程序错误。

    由于不支持使用__based的函数地址,需要使用alloc_text编译指示来指定段位置。由textsection指定的名字应该由双引号括起来。

    alloc_text编译指示必须出现在任何需要指定的函数说明之后,以及这些函数的定义之前。

    alloc_text编译指示中引用的函数必须和该编译指示处于同一个模块中。如果不这样做,使以后一个未定义的函数被编译到一个不同的代码段时,错误会也可能不会被捕获。即使程序一般会正常运行,但是函数不会分派到应该在的段。

    alloc_text的其它限制如下:

    它不能用在一个函数内部。

    它必须用于函数说明以后,函数定义以前。

    2  auto_inline

    #pragma auto_inline( [{on | off}] )

    当指定off时将任何一个可以被考虑为作为自动嵌入扩展候选的函数排除出该范围。为了使用auto_inline编译指示,将其紧接着写在一个函数定义之前或之后(不是在其内部)。该编译指示将在其出现以后的第一个函数定义开始起作用。auto_inline编译指示对显式的inline函数不起作用。

    3  bss_seg

    #pragma data_seg( ["section-name"[, "section-class"] ] )

    为未初始化数据指定缺省段。data_seg编译指示除了工作于已初始化数据而不是未初始化的以外具有一样的效果。在一些情况下,你能使用bss_seg将所有未初始化数据安排在一个段中来加速你的装载时间。

    #pragma bss_seg( "MY_DATA" )

    将导致把#pragma语句之后的未初始化的数据安排在一个叫做MY_DATA的段中。

    bss_seg编译指示分配的数据不包含任何关于其位置的信息。

    第二个参数section-class是用于兼容2.0版本以前的Visual C++的,现在将忽略它。

    4  check_stack

    #pragma check_stack([ {on | off}] )

    #pragma check_stack{+ | –}

    如果指定off(或者“-”)指示编译程序关闭堆栈探测,或者指定on(或“+”)打开堆栈探测。如果没有给出参数,堆栈探测将根据默认设置决定。该编译指示将在出现该指示之后的第一个函数开始生效。堆栈探测既不是宏和能够生成嵌入代码函数的一部分。

    如果你没有给出check­_stack编译指示的参数,堆栈检查将恢复到在命令行指定的行为。详细情况见编译程序参考。#pragma check_stack/Gs选项的互相作用情况在表2.1中说明。

    2.1 使用check_stack编译指示

    编译指示

    /Gs选项编译?

    行为

    #pragma check_stack()#pragma check_stack

    后续的函数关闭堆栈检查

    #pragma check_stack()#pragma check_stack

    后续的函数打开堆栈检查

    #pragma check_stack(on)#pragma check_stack(+)

    是或者否

    后续的函数打开堆栈检查

    #pragma check_stack(off)#pragma check_stack(-)

    是或者否

    后续的函数关闭堆栈检查

    5  code_seg

    #pragma code_seg( ["section-name"[,"section-class"] ] )

    指定分配函数的代码段。code_seg编译指示为函数指定默认的段。你也能够像段名一样指定一个可选的类名。使用没有段名字符串的#pragma code_seg将恢复分配到编译开始时候的状态。

    6  const_seg

    #pragma const_seg( ["section-name"[, "section-class"] ] )

    指定用于常量数据的默认段。data_seg编译指示除了可以工作于所有数据以外具有一样的效果。你能够使用该编译指示将你的常量数据保存在一个只读的段中。

    #pragma const_seg( "MY_DATA" )

    导致在#pragma语句后面的常量数据分配在一个叫做MY_DATA的段中。

    const_seg编译指示分配的数据不包含任何关于其位置的信息。

    第二个参数section-class是用于兼容2.0版本以前的Visual C++的,现在将忽略它。

    7  comment

    #pragma comment( comment-type [, commentstring] )

    将描述记录安排到目标文件或可执行文件中去。comment-type是下面说明的五个预定义标识符中的一个,用来指定描述记录的类型。可选的commentstring是一个字符串文字值用于为一些描述类型提供附加的信息。因为commentstring是一个字符串文字值,所以它遵从字符串文字值的所有规则,例如换码字符、嵌入的引号(")和联接。

    7-1  compiler

    在目标文件中放置编译程序名和版本号。该描述记录被连接程序忽略。如果你为这个记录类型提供一个commentstring参数,编译程序将生成一个警告。

    7-2  exestr

    commentstring放置到目标文件中去。在连结时,这个字符串再被放到可执行文件去中。当可执行文件被装载时这个字符串不会被装入内存,然而,它可以被一个能够在文件中搜索可打印字符串的程序找到。该描述记录的一个用处是在可执行文件中嵌入版本号或者类似的信息。

    7-3  lib

    将一个库搜索记录放置到目标文件中去。该描述类型必须有包含你要连接程序搜索的库名(和可能的路径)的commentstring参数。因为在目标文件中该库名先于默认的库搜索记录,所以连接程序将如同你在命令行输入这些库一样来搜索它们。你可以在一个源文件中放置多个库搜索记录,每个记录将按照它们出现在源文件中的顺序出现在目标文件中。

    7-4  linker

    在目标文件中放置连接程序选项。你可以用这个描述类型指定连接程序选项来代替在Project Setting对话框中Link页内的选项。例如,你可以指定/include选项以强迫包含一个符号:

    #pragma comment(linker, "/include:__mySymbol")

    7-5  user

    在目标文件中包含一个普通描述记录。commentstring参数包含描述的文本。该描述记录将被连接程序忽略。

     

    下面的编译指示导致连接程序在连接时搜索EMAPI.LIB库。连接程序首先在当前工作目录然后在LIB环境变量指定的路径中搜索。

    #pragma comment( lib, "emapi" )

    下面的编译指示导致编译程序将其名字和版本号放置到目标文件中去。

    The following pragma causes the compiler to place the name and version number of the compiler in the object file:

    #pragma comment( compiler )

    注意,对于具有commentstring参数的描述记录,你可以使用其它用作字符串文字量的宏来提供宏扩展为字符串文字量。你也能够联结任何字符串文字量和宏的组合来扩展成为一个字符串文字量。例如,下面的语句是可以接受的:

    #pragma comment( user, "Compiled on " __DATE__ " at " __TIME__ )

    8  component

    #pragma component( browser, { on | off }[, references [, name ]] )

    #pragma component( minrebuild, on | off )

     

    从源文件内控制浏览信息和依赖信息的收集。

    8-1  浏览信息(Browser

    你可以将收集打开或关闭,你也可以指定收集时忽略特别的名字。

    使用onoff在编译指示以后控制浏览信息的收集。例如:

    #pragma component(browser, off)

    终止编译程序收集浏览信息。

    注意,为了用这个编译指示打开浏览信息的收集,必须先从Project Setting对话框或者命令行允许浏览信息。

    references选项可以有也可以没有name参数。使用没有name参数的references选项将打开或者关闭引用信息的收集(然而继续收集其它浏览信息)。例如:

    #pragma component(browser, off, references)

    终止编译程序收集引用信息。

    使用有nameoff参数的references选项将阻止从浏览信息窗口中出现引用到的名字。用这个语法将忽略你不感兴趣的名字和类型从而减少浏览信息文件的大小。例如:

    #pragma component(browser, off, references, DWORD)

    从这一点以后忽略DWORD的引用。你能够用on恢复DWORD的引用收集:

    #pragma component(browser, on, references, DWORD)

    这是唯一的方法可以恢复收集指定名字的引用,你必须显式地打开任何你关闭的名字。

    为了防止预处理程序扩展名字(就像扩展NULL0),用引号括起来:

    #pragma component(browser, off, references, "NULL")

    8-2  最小化重建(Minimal Rebuild

    Visual C++的最小化重建功能要求编译程序创建并保存需要大量磁盘空间的C++类依赖信息。为了节省磁盘空间,你能够在你不需要收集依赖信息时使用#pragma component(minrebuild,off),例如,没有改变过头文件。在未修改过的类之后插入#pragma component(minrebuild,on)重新打开依赖信息。

    详见Enable Minimal Rebuild(/Gm)编译程序选项。

    9  data_seg

    #pragma data_seg( ["section-name"[, "section-class"] ] )

    指定数据的默认段。例如:

    #pragma data_seg( "MY_DATA" )

    导致在#pragma语句后分配的数据保存在一个叫做MY_DATA的段中。

    data_seg编译指示分配的数据不包含任何关于其位置的信息。

    第二个参数section-class是用于兼容2.0版本以前的Visual C++的,现在将忽略它。

    10  function

    #pragma function( function1 [, function2, ...] )

    指定必须生成对编译指示中参数列表内函数的调用。如果你使用intrinsic编译指示(或者/Oi)来告诉编译程序生成内含函数(内含函数如同嵌入代码一样生成,不作为一个函数调用),你能够用function编译指示显式地强迫函数调用。当遇到一个function编译指示,它将在其后面遇到的第一个包含有内含函数的函数定义处生效。其持续作用到源文件的尾部或者出现对同一个内含函数指定intrinsic编译指示。function编译指示只能用于函数外——在全局层次。

    为了列出具有内含形式的函数表,参见#pragma intrinsic

    11  hdrstop

    #pragma hdrstop [( "filename" )] 

    控制预编译头文件的工作方式。filename是要使用或者创建(依赖于是否指定了/Yu/Yc)预编译头文件的名字。如果 filename不包括一个指定路径,将假定预编译头文件和源文件处于同一个目录中。当指定自动预编译头文件选项/YX时,所有指定的文件名将被忽略。

    如果有/YX或者/Yc选项,而且CC++文件包含了一个hdrstop编译指示时,编译程序保存编译指示之前的编译状态。编译指示之后的编译状态不被保存。

    hdrstop编译选项不能出现在一个头文件内。它只能出现在源文件的文件级,它也不能出现在任何数据或者函数的说明或定义之中。

    注意,除非指定没有文件名的/YX选项或者/Yu/Yc选项,否则hdrstop编译指示将被忽略。

    用一个文件名命名要保存编译状态的预编译头文件。在hdrstopfilename之间的空格是可选的。在hdrstop编译指示中的文件名是一个字符串,这样它服从于CC++的字符串规则。特别的,你必须像下面例子里面显示的用引号括起来。

    #pragma hdrstop( "c:/projects/include/myinc.pch" )

    预编译头文件的文件名按照如下规则决定,按照优先次序:

    /Fp编译程序选项的参数;

    #pragma hdrstopfilename参数;

    原文件名的基本文件名加上.PCH扩展名。

    12  include_alias

    #pragma include_alias( "long_filename", "short_filename" )

    #pragma include_alias( <long_filename>, <short_filename> )

    指定作为long_filename别名的short_filename。一些文件系统允许超出8.3FAT文件系统限制的长头文件名。编译程序不能简单地将长文件名截断为8.3名字,因为长头文件名的前8个字符可能不是唯一的。无论何时编译程序遇到long_filename串,它代替short_filename,并且用short_filename搜索头文件。这个编译指示必须出现在相应的#include指示之前。例如:

    // First eight characters of these two files not unique.

    #pragma include_alias( "AppleSystemHeaderQuickdraw.h", "quickdra.h" )

    #pragma include_alias( "AppleSystemHeaderFruit.h", "fruit.h" )

    #pragma include_alias( "GraphicsMenu.h", "gramenu.h" )

     

    #include "AppleSystemHeaderQuickdraw.h"

    #include "AppleSystemHeaderFruit.h"

    #include "GraphicsMenu.h"

    这个别名在搜索时精确匹配,包括拼写和双引号、尖括号。include_alias编译指示在文件名上执行简单的字符串匹配,不进行其它的文件名验证。例如,给出下列指示:

    #pragma include_alias("mymath.h", "math.h")

    #include "./mymath.h"

    #include "sys/mymath.h"

    并不执行别名替代,因为头文件名字符串没有精确匹配。另外,在/Yu/Yc/YX编译程序选项,或hdrstop编译指示中作为参数的头文件名不被替换。例如,如果你的源文件包含下列指示:

    #include <AppleSystemHeaderStop.h>

    相应的编译程序选项必须是:

    /YcAppleSystemHeaderStop.h

    你能够用include­_alias编译指示将任何头文件映射到其它文件。例如:

    #pragma include_alias( "api.h", "c:/version1.0/api.h" )

    #pragma include_alias( <stdio.h>, <newstdio.h> )

    #include "api.h"

    #include <stdio.h>

    不要混淆用双引号和尖括号括起来的文件名。例如,给出上面的#pragma include_alias指示时,在下面的#include指示中编译程序不执行替换。

    #include <api.h>

    #include "stdio.h"

    还有,下面的指示将产生一个错误:

    #pragma include_alias(<header.h>, "header.h")  // Error

    注意,在错误信息中报告的文件名,或者预定义宏__FILE__的值,是执行替换以后的文件名。例如,在下列指示之后:

    #pragma include_alias( "VeryLongFileName.H", "myfile.h" )

    #include "VeryLongFileName.H"

    文件VeryLongFileName.H产生下列错误信息:

    myfile.h(15) : error C2059 : syntax error

    还要注意的是不支持传递性。给出下面的指示:

    #pragma include_alias( "one.h", "two.h" )

    #pragma include_alias( "two.h", "three.h" )

    #include "one.h"

    编译程序将搜索two.h而不是three.h

    13  init_seg

    C++特有

    #pragma init_seg({ compiler | lib | user | "section-name" [, "func-name"]} )

    指定影响启动代码执行的关键字或代码段。因为全局静态对象的初始化可以包含执行代码,所以你必须指定一个关键字来定义什么时候构造对象。在使用需要初始化的动态连接库(DLL)或程序库时使用init_seg编译指示是尤其重要的。

    init_seg编译指示的选项有:

    13-1  compiler

    Microsoft C运行时间库保留。在这个组中的对象将第一个构造。

    13-2  lib

    用于第三方类库开发者的初始化。在这个组中的对象将在标记为构造compiler的对象之后,其它对象之前构造。

    13-3  user

    用于任何其它用户。在这个组中的对象将最后构造。

    13-4  section-name

    允许显式地指定初始化段。在用户指定的section-name中的对象将不会隐式地构造,而它们的地址将会被放置在由section-name命名的段中。

    13-5  func-name

    指定当程序退出时,作为atexit函数调用的函数。这个函数必须具有和atexit函数相同的形式:

    int funcname(void (__cdecl *)(void));

    如果你需要延迟初始化,你能够选择指定显式的段名。随后你必须调用每个静态对象的构造函数。

    14  inline_depth

    #pragma inline_depth( [0... 255] )

    通过控制能够被扩展的一系列函数调用(从0255次)来控制嵌入函数扩展的发生次数,这个编译指示控制用inline__inline标记的或在/Ob2选项下能自动嵌入的嵌入函数。

    inline_depth编译指示控制能够被扩展的一系列函数调用。例如,如果嵌入深度是4,并且如果A调用B然后调用C,所有的3次调用都将做嵌入扩展。然而,如果设置的最近一次嵌入深度是2,则只有AB被扩展,而C仍然作为函数调用。

    为了使用这个编译指示,你必须设置编译程序选项/Ob1或者2。用这个编译指示指定的深度设定在该指示后面的第一个函数开始生效。如果你在括号内不指定一个值,inline_depth设置嵌入深度到默认值8

    在扩展时,嵌入深度可以被减少而不能被增加。如果嵌入深度是6,同时在扩展过程中预处理程序遇到一个inline_depth编译指示设置为8,则深度保持为6

    嵌入深度0将拒绝嵌入扩展,深度255将设置在嵌入扩展时没有限制。如果用一个没有指定值的编译指示,则使用为默认值。

    15  inline_recursion

    #pragma inline_recursion( [{on | off}] )

    控制直接或者相互间的递归函数调用式的嵌入扩展。用这个编译指示控制用inline__inline标记的或在/Ob2选项下能自动嵌入的嵌入函数。使用这个编译指示需要设置编译程序选项/Ob1或者2。默认的inline_recursion状态是off。这个编译指示在出现该编译指示之后第一个函数调用起作用,并不影响函数的定义。

    inline_recursion编译指示控制如何扩展递归函数。如果inline_recursionoff,并且如果一个嵌入函数调用了它自己(直接的或者间接的),函数将仅仅扩展一次。如果inline_recursionon,函数将扩展多次直到达到inline_depth的值或者容量限制。

    16  intrinsic

    #pragma intrinsic( function1 [, function2, ...] )

    指定对在编译指示参数表中函数调用是内含的。编译程序像嵌入代码一样生成内含函数,而不是函数调用。下面列出了具有内含形式的库函数。一旦遇到intrinsic编译指示,它从第一个包含指定内含函数的函数定义开始起作用。作用持续到源文件尾部或者出现包含相同内含函数的function编译指示。intrinsic编译指示只能用在函数定义外——在全局层次。

    下列函数具有内含形式:

    _disable

    _enable

    _inp

    _inpw

    _lrotl

    _lrotr

    _outp

    _outpw

    _rotl

    _rotr

    _strset

    abs

    fabs

    labs

    memcmp

    memcpy

    memset

    strcat

    strcmp

    strcpy

    strlen

     

     

     

    使用内含函数的程序更快,因为它们没有函数调用的额外代价,然而因为有附加的代码生成,可能比较大。

    注意,_allocasetjmp函数总是内含的,这个行为不受intrinsic编译指示影响。

    下列浮点函数没有内含形式。然而它们具有直接将参数通过浮点芯片传送而不是推入程序堆栈的版本。

    acos

    asin

    cosh

    fmod

    pow

    sinh

    tanh

     

     

     

     

     

    当你同时指定/Oi/Og编译程序选项(或者任何包含/Og/Ox/O1/O2的选项)时下列浮点函数具有真正的内含形式。

    atan

    exp

    log10

    sqrt

    atan2

    log

    sin

    tan

    cos      

     

     

     

    你可以用编译程序选项/Op/Za来覆盖真内含浮点选项的生成。在这种情况下,函数会像一般库函数一样被生成,同时直接将参数通过浮点芯片传送而不是推入程序堆栈。

    17  message

    #pragma message( messagestring )

    不中断编译,发送一个字符串文字量到标准输出。message编译指示的典型运用是在编译时显示信息。

    下面的代码段用message编译指示在编译过程中显示一条信息:

    #if _M_IX86 == 500

    #pragma message( "Pentium processor build" )

    #endif

    messagestring参数可以是一个能够扩展成字符串文字量的宏,并且你能够用字符串文字量和宏的任何组合来构造。例如,下面的语句显示被编译文件的文件名和文件最后一次修改的日期和时间。

    #pragma message( "Compiling " __FILE__ )

    #pragma message( "Last modified on " __TIMESTAMP__ )

    18  once

    #pragma once

    指定在创建过程中该编译指示所在的文件仅仅被编译程序包含(打开)一次。该编译指示的一种常见用法如下:

    //header.h

    #pragma once

    // Your C or C++ code would follow:

    19  optimize

    仅在专业版和企业版中存在

    #pragma optimize( "[optimization-list]", {on | off} )

    代码优化仅有Visual C++专业版和企业版支持。详见Visual C++ Edition

    指定在函数层次执行的优化。optimize编译选项必须在函数外出现,并且在该编译指示出现以后的第一个函数定义开始起作用。onoff参数打开或关闭在optimization-list指定的选项。

    optimization-list能够是0或更多个在表2.2中给出的参数:

    2.2   optimize编译指示的参数

    参数

    优化类型

    a

    假定没有别名。

    g

    允许全局优化。

    p

    增强浮点一致性。

    s t

    指定更短或者更快的机器代码序列。

    w

    假定在函数调用中没有别名。

    y

    在程序堆栈中生成框架指针。

    这些和在/O编译程序选项中使用的是相同的字母。例如:

    #pragma optimize( "atp", on )

    用空字符串("")的optimize编译指示是一种特别形式。它要么关闭所有的优化选项,要么恢复它们到原始(或默认)的设定。

    #pragma optimize( "", off )

    .

    .

    .

    #pragma optimize( "", on )

    20  pack

    #pragma pack( [ n] )

    指定结构和联合成员的紧缩对齐。尽管用/Zp选项设定整个翻译单元的结构和联合成员的紧缩对齐,可以用pack编译指示在数据说明层次设定紧缩对齐。从出现该编译指示后的第一个结构或者联合说明开始生效。这个编译指示不影响定义。

    当你使用#pragma pack(n),其中n1248或者16,第一个以后的每个结构成员保存在较小的成员类型或者n字节边界上。如果你使用没有参数的#pragma pack,结构成员将被紧缩到由/Zp指定的值。默认的/Zp紧缩的大小是/Zp8

    编译程序还支持下面的增强语法:

    #pragma pack( [ [ { push | pop}, ] [  identifier, ] ] [ n ] )

    该语法允许你将使用不同紧缩编译指示的组件合并到同一个翻译单元内。

    每次出现有push参数的pack编译指示将保存当前的紧缩对齐值到一个内部的编译程序堆栈。编译指示的参数列表从左向右读取。如果你使用了push,当前紧缩值被保存。如果你提供了一个n值,这个值将成为新的紧缩值。如果你指定了一个你选定的标示符,这个标示符将和新的紧缩值关联。

    每次出现有pop参数的pack编译指示从内部编译程序堆栈顶部取出一个值并将那个值作为新的紧缩对齐。如果你用了pop,而内部编译程序堆栈是空的,对齐值将从命令行得到,同时给出一个警告。如果你用了pop并指定了n的值,那个值将成为新的紧缩值。如果你用了pop并指定了一个标示符,将移去所有保存在堆栈中的的值直到匹配的找到匹配的标示符,和该标示符关联的紧缩值也被从堆栈中移出来成为新的紧缩值。如果没有找到匹配的标示符,将从命令行获取紧缩值并产生一个1级警告。默认的紧缩对齐是8

    pack编译指示的新的增强功能允许你编写头文件保证在使用头文件之前和其后的紧缩值是一样的:

    /* File name: include1.h

    */

    #pragma pack( push, enter_include1 )

    /* Your include-file code ... */

    #pragma pack( pop, enter_include1 )

    /* End of include1.h */

    在前面的例子中,进入头文件时将当前紧缩值和标示符enter_include1关联并推入,被记住。在头文件尾部的pack编译选项移去所有在头文件中可能遇到的紧缩值并移去和enter_include1关联的紧缩值。这样头文件保证了在使用头文件之前和其后的紧缩值是一样的。

    新功能也允许你在你的代码内用pack编译指示为不同的代码,例如头文件设定不同的紧缩对齐。

    #pragma pack( push, before_include1 )

    #include "include1.h"

    #pragma pack( pop, before_include1 )

    在上一个例子中,你的代码受到保护,防止了在include.h中的任何紧缩值的改变。

    21  pointers_to_members

    C++特有

    #pragma pointers_to_members(pointer-declaration, [most-general-representation] )

    指定是否能够在相关类定义之前说明一个指向类成员的指针,并且用于控制指针的大小和解释指针的代码。你能够在你的源代码中使用pointers_to_members编译知识来代替/vmx编译程序选项。

    pointer-declaration参数指出是否在相关函数定义之前或其后你已经说明了一个指向成员的指针。pointer-declaration参数是下面两个符号之一:

    参数

    说明

    full_generality

    生成安全的,但是有时不能优化的代码。如果有一些指向成员的指针在相关类定义之前说明,你要用full_generality。这个参数总是使用由most-general-representation指定的指针表示方式。

    best_case

    对于所有指向成员的指针用最佳的表示方式生成安全的,优化的代码。需要在说明一个指向类成员指针之前定义类。默认是best_case

    most-general-representaion参数指出在一个翻译单元中编译程序能够安全引用任何指向类成员指针的最小指针表示方式。这个参数可以是下列之一:

    参数

    说明

    single_inheritance

    最普通的表示方式是单继承,指向成员函数。如果用于指向具有多重或者虚拟继承方式类成员的指针,将产生一个错误。

    multi_inheritance

    最普通的表示方式是多重继承,指向成员函数。如果用于指向具有虚拟继承方式类成员的指针,将产生一个错误。

    virtual_inheritance

    最普通的表示方式是虚拟继承,指向成员函数。不会产生错误。当使用#pragma pointers_to_members (full_generality)时这是默认的参数。

    22  setlocale

    #pragma setlocale( "locale-string" )

    定义用于翻译宽字符常数和字符串文字量时用的地区(国家和语言)。由于用于从多字节字符转换到宽字符的算法根据地区或者由于在运行可执行程序不同的地方进行编译而不同,这个编译指示提供一种在编译时指定目标地区的方式。这保证宽字符字符串将以正确的格式保存。默认的locale-string“C”“C”地区将字符串中的每个字符作为wchar_t(即unsigned int)映射其值。

    23  vtordisp

    C++特有

    #pragma vtordisp({on | off} )

    允许隐藏的附加vtordisp构造函数/析构函数替换成员。vtordisp编译指示仅能够用于具有虚拟基类的代码。如果派生类从一个虚拟基类重载了一个虚拟函数,并且如果派生类的构造函数或析构函数用指向虚拟基类的指针调用了这个函数,编译程序将根据虚拟基类在类中引入一个附加的隐藏“vtordisp”域。

    vtodisp编译选项影响它后面的类布局。/vd0/vd1选项为整个模块指定了相同的行为。指定off将禁止隐藏的vtordisp成员,指定on(默认)将在它们需要的时候允许vtordisp。仅在不可能出现类的构造函数和析构函数通过this指针调用其指向对象中的虚拟函数时才关闭vtordisp

    #pragma vtordisp( off )

    class GetReal : virtual public { ... };

    #pragma vtordisp( on )

    24  warning

    #pragma warning( warning-specifier : warning-number-list [,warning-specifier : warning-number-list...] )

    #pragma warning( push[ , n ] )

    #pragma warning( pop )

    允许有选择地修改编译程序警告信息的行为。

    warning-specifier能够是下列值之一:

    warning-specifier

    含义

    once

    只显示指定信息一次。

    default

    对指定信息应用默认的编译程序选项。

    1,2,3,4

    对指定信息引用给定的警告等级。

    disable

    不显示指定信息。

    error

    对指定信息作为错误显示。

    warning-number_list能够包含任何警告编号。如下,在一个编译指示中可以指定多个选项:

    #pragma warning( disable : 4507 34; once : 4385; error : 164 )

    这等价于:

    #pragma warning( disable : 4507 34 )  // Disable warning messages

                                                //  4507 and 34.

    #pragma warning( once : 4385 )         // Issue warning 4385

                                                //  only once.

    #pragma warning( error : 164 )         // Report warning 164

                                                //  as an error.

    对于那些关于代码生成的,大于4699的警告标号,warning编译指示仅在函数定义外时有效。如果指定的警告编号大于4699并且用于函数内时被忽略。下面例子说明了用warning编译指示禁止、然后恢复有关代码生成警告信息的正确位置:

    int a;

    #pragma warning( disable : 4705 )

    void func()

    {

        a;

    }

    #pragma warning( default : 4705 )

    warning编译指示也支持下面语法:

    #pragma warning( push [ ,n ] )

    #pragma warning( pop )

    这里n表示警告等级(14)。

    warning(push)编译指示保存所有警告的当前警告状态。warning(push,n)保存所有警告的当前状态并将全局警告等级设置为n

    warning(pop)弹出最后一次推入堆栈中的警告状态。任何在pushpop之间改变的警告状态将被取消。考虑下面的例子:

    #pragma warning( push )

    #pragma warning( disable : 4705 )

    #pragma warning( disable : 4706 )

    #pragma warning( disable : 4707 )

    // Some code

    #pragma warning( pop )

    在这些代码的结束,pop恢复了所有警告的状态(包括470547064707)到代码开始时候的样子。

    当你编写头文件时,你能用pushpop来保证任何用户修改的警告状态不会影响正常编译你的头文件。在头文件开始的地方使用push,在结束地方使用pop。例如,假定你有一个不能顺利在4级警告下编译的头文件,下面的代码改变警告等级到3,然后在头文件的结束时恢复到原来的警告等级。

    #pragma warning( push, 3 )

    // Declarations/ definitions

    #pragma warning( pop )

     

    原文地址 http://tb.blog.csdn.net/TrackBack.aspx?PostId=1621227

     

     

     

    展开全文
  • CAD系统变量

    千次阅读 2018-05-11 14:34:07
    *CAD系统变量 要获取到系统变量的值,然后解析系统变量的含义,在网上找到这些资料: 3DDWFPREC 控制三维DWF发布的精度。 3DCONVERSIONMODE 用于将材质和光源定义转换为当前产品版本。 3DSELECTIONMODE 控制使用...

    *CAD系统变量
    要获取到系统变量的值,然后解析系统变量的含义,在网上找到这些资料:
    3DDWFPREC 控制三维DWF发布的精度。
    3DCONVERSIONMODE 用于将材质和光源定义转换为当前产品版本。
    3DSELECTIONMODE 控制使用三维视觉样式时视觉上重叠的对象的选择优先级。
    ACADLSPASDOC 控制是将acad.lsp文件加载到每个图形中,还是仅加载到任务中打开的第一个图形中。
    ACADPREFIX 存储由ACAD环境变量指定的目录路径。
    ACADVER 存储AutoCAD的版本号。
    ACISOUTVER 控制使用ACISOUT命令创建的SAT文件的ACIS版本。
    ADCSTATE 指示设计中心窗口处于打开还是关闭状态。
    AFLAGS 设置属性选项。
    ANGBASE 将相对于当前UCS的基准角设置为 0。
    ANGDIR 设置正角度的方向。从相对于当前UCS方向的 0 角度测量角度值。
    ANNOALLVISIBLE 隐藏或显示不支持当前annotation scale的annotative对象。
    ANNOAUTOSCALE 注释比例更改时更新annotative对象可支持annotation scale。
    ANNOTATIVEDWG 指定图形插入到其他图形中时,是否相当于annotative块。
    APBOX 打开或关闭自动捕捉靶框的显示。
    APERTURE 以像素为单位设置对象捕捉靶框的显示尺寸。
    APSTATE 块编辑器中的“块编写选项板”窗口处于打开还是关闭状态。
    AREA 存储由AREA命令计算出的上一个面积。
    ATTDIA 控制INSERT命令是否使用对话框用于属性值的输入。
    ATTIPE 控制用于创建多行属性的在位编辑器的显示。
    ATTMODE 控制属性的显示。
    ATTMULTI 控制是否可创建多行属性。
    ATTREQ 在插入块过程中控制INSERT是否使用默认属性设置。
    AUDITCTL 控制AUDIT命令是否创建核查报告 (ADT) 文件。
    AUNITS 设置角度单位。
    AUPREC 设置所有只读角度单位和所有可编辑角度单位的小数位数。
    AUTODWFPUBLISH 控制自动发布功能的开关状态。
    AUTOSNAP 控制自动捕捉标记、工具栏提示和磁吸的显示。也可以打开极轴追踪和对象捕捉追踪,并控制极轴追踪、对象捕捉追踪和正交模式工具栏提示的显示。
    BACKGROUNDPLOT 控制是否打开后台打印和后台发布。默认情况下,关闭后台打印,打开后台发布。
    BACKZ 以绘图单位存储当前视口后向剪裁平面到目标平面的偏移值。
    BACTIONCOLOR 在块编辑器中设置动作的文字颜色。
    BDEPENDENCYHIGHLIGHT 控制在块编辑器中选定参数、动作或夹点时是否依赖亮显依赖对象。
    BGRIPOBJCOLOR 在块编辑器中设置夹点的颜色。
    BGRIPOBJSIZE 在块编辑器中设置相对于屏幕显示的自定义夹点的显示尺寸。
    BINDTYPE 控制绑定或在位编辑外部参照时外部参照名称的处理方式。
    BLIPMODE 控制点标记是否可见。该系统变量的名称与命令相同。
    BLOCKEDITLOCK 禁止打开块编辑器以及编辑动态块定义。
    BLOCKEDITOR 反映块编辑器是否已打开。
    BPARAMETERCOLOR 设置块编辑器中的参数的颜色。
    BPARAMETERFONT 设置块编辑器中的参数和动作所用的字体。
    BPARAMETERSIZE 在块编辑器中设置相对于屏幕显示的参数文本和功能的显示尺寸。
    BTMARKDISPLAY 控制是否显示动态块参照的数值集标记。
    BVMODE 控制当前可见性状态下可见的对象在块编辑器中的显示方式。
    CALCINPUT 控制是否计算文本中以及窗口和对话框的数字输入框中的数学表达式和全局常量。
    CAMERADISPLAY 打开或关闭相机对象的显示。
    CAMERAHEIGHT 为新相机对象指定默认高度。
    CANNOSCALE 设置当前空间中的当前annotation scale的名称
    CANNOSCALEVALUE 返回当前annotation scale的值
    CDATE 以小数格式存储当前的日期和时间。
    CECOLOR 设置新对象的颜色。
    CELTSCALE 设置当前对象的线型比例因子。
    CELTYPE 设置新对象的线型。
    CELWEIGHT 设置新对象的线宽。
    CENTERMT 控制夹点拉伸多行水平居中的文字的方式。
    CHAMFERA 当CHAMMODE设置为 0 时设置第一个倒角距离。
    CHAMFERB 当CHAMMODE设置为 0 时设置第二个倒角距离。
    CHAMFERC 当CHAMMODE设置为 1 时设置倒角长度。
    CHAMFERD 当CHAMMODE设置为 1 时设置倒角角度。
    CHAMMODE 设置CHAMFER的输入方法。
    CIRCLERAD 设置默认的圆半径。
    CLAYER 设置当前图层。
    CLEANSCREENSTATE 全屏显示状态的开关状态。
    CLISTATE 命令窗口处于打开还是关闭状态。
    CMATERIAL 设置新对象的材质。
    CMDACTIVE 指示激活的是普通命令、透明命令、脚本还是对话框。
    CMDDIA 控制执行QLEADER命令时在位文字编辑器的显示。
    CMDECHO 控制在AutoLISP命令函数运行时是否回显提示和输入。
    CMDINPUTHISTORYMAX 设置存储在命令提示中的以前输入值的最大数量。
    CMDNAMES 显示活动命令和透明命令的名称。
    CMLEADERSTYLE 当前使用的多重引线样式的名称
    CMLJUST 指定多线对正方式。
    CMLSCALE 指定多线比例。
    CMLSTYLE 当前使用的多线样式的名称。
    COMPASS 控制三维指南针在当前视口中的开关状态。
    COORDS 控制状态行上坐标的格式和更新频率。
    COPYMODE 控制是否自动重复COPY命令。
    CPLOTSTYLE 控制新对象的当前打印样式。
    CPROFILE 显示当前配置的名称。
    CROSSINGAREACOLOR 控制交叉选择时选择区域的颜色。
    CSHADOW 设置三维对象的阴影显示特性。
    CTAB 返回图形中的当前(模型或布局)选项卡名称。
    CTABLESTYLE 当前使用的表格样式的名称
    CURSORSIZE 按屏幕大小的百分比确定十字光标的大小。
    CVPORT 显示当前视口的标识码。
    DASHBOARDSTATE 指示“面板”窗口处于打开还是关闭状态。
    DATALINKNOTIFY 控制更新或缺少数据链接的通知
    DATE 以“修改的Julian日期”格式存储当前的日期和时间。
    DBCSTATE 存储数据库连接管理器的状态(打开或关闭)。
    DBLCLKEDIT 控制绘图区域中的双击编辑操作。
    DBMOD 指示图形的修改状态。
    DCTCUST 显示当前的自定义拼写词典的路径和文件名。
    DCTMAIN 显示当前主拼写词典的三字母关键字。
    DEFAULTLIGHTING 控制当前视口中的默认光源。
    DEFAULTLIGHTINGTYPE 指定默认光源类型。
    DEFLPLSTYLE 打开在AutoCAD2000 之前的版本中创建的图形时,指定所有图层的默认打印样式;在不使用图形模板从头创建新图形时,指定图层 0 的默认打印样式。
    DEFPLSTYLE 指定在打开AutoCAD2000 之前的版本中创建的图形或不使用图形模板从头创建新图形时,图形中新对象的默认打印样式。
    DELOBJ 控制保留还是删除用于创建三维对象的几何体。
    DEMANDLOAD 指定是否以及何时按需加载某些应用程序。
    DGNFRAME 确定DGN参考底图边框在当前图形中是否可见或是否打印。
    DGNOSNAP 控制DGN参考底图中几何图形的对象捕捉。
    DIASTAT 存储最近一次使用的对话框的退出方式。
    DIMADEC 控制角度标注中显示精度的小数位数。
    DIMALT 控制标注中的换算单位的显示。
    DIMALTD 控制换算单位中的小数位数。
    DIMALTF 控制换算单位的乘数。
    DIMALTRND 舍入换算标注单位。
    DIMALTTD 设置换算标注单位中的公差值的小数位数。
    DIMALTTZ 控制对公差值的消零处理。
    DIMALTU 设置所有标注子样式(角度标注除外)的换算单位的单位格式。
    DIMALTZ 控制对换算单位标注值的消零处理。DIMALTZ的值为 0 到 3 时只影响英尺-英寸标注。
    DIMANNO 指示当前标注样式是否是annotative。
    DIMAPOST 指定用于所有标注类型(角度标注除外)的换算标注测量值的文字前缀或后缀(或两者都指定)。
    DIMARCSYM 控制弧长标注中圆弧符号的显示。
    DIMASO 旧式的。保留在产品中以保持脚本的完整性。
    DIMASSOC 控制标注对象的关联性以及是否分解标注。
    DIMASZ 控制尺寸线和引线箭头的大小。并控制基线的大小。
    DIMATFIT 尺寸界线内的空间不足以同时放下标注文字和箭头时,此系统变量将确定这两者的排列方式。
    DIMAUNIT 设置角度标注的单位格式。
    DIMAZIN 对角度标注进行消零处理。
    DIMBLK 设置尺寸线末端显示的箭头块。
    DIMBLK1 设置尺寸线第一个端点的箭头。
    DIMBLK2 设置尺寸线第二个端点的箭头。
    DIMCEN 控制由DIMCENTER、DIMDIAMETER和DIMRADIUS命令绘制的圆或圆弧的圆心标记和中心线。
    DIMCLRD 为尺寸线、箭头和标注引线指定颜色。同时控制用LEADER命令创建的引线的颜色。
    DIMCLRE 为尺寸界线指定颜色。
    DIMCLRT 为标注文字指定颜色。
    DIMDEC 设置标注主单位中显示的小数位数。
    DIMDLE 当使用小斜线代替箭头进行标注时,设置尺寸线超出尺寸界线的距离。
    DIMDLI 控制基线标注中尺寸线的间距。
    DIMDSEP 指定创建单位格式为十进制的标注时要使用的单字符小数分隔符。
    DIMEXE 指定尺寸线超出尺寸界线的距离。
    DIMEXO 指定尺寸界线偏离原点的距离。对于固定长度的尺寸界线,此值将决定最小偏移量。
    DIMFIT 已废弃,请改用DIMATFIT和DIMTMOVE。
    DIMFRAC 设置分数格式(当DIMLUNIT设置为 4 [建筑] 或 5 [分数] 时)。
    DIMFXL 设置尺寸界线的总长度,起始于尺寸线,直到标注原点。以图形单位设置长度。
    DIMFXLON 控制是否将尺寸界线设置为固定长度。DIMFXLON打开时,尺寸界线设置为DIMFXL指定的长度。
    DIMGAP 尺寸线分成两段从而将标注文字放置在两段之间时,设置标注文字周围的距离。同时设置用LEADER命令创建的注释和基线之间的间距。如果输入负值,DIMGAP将在标注文字周围放置一个方框。
    DIMJOGANG 确定折弯半径标注中,尺寸线的横向线段的角度。
    DIMJUST 控制标注文字的水平位置。
    DIMLDRBLK 指定引线箭头的类型。
    DIMLFAC 设置线性标注测量值的比例因子。
    DIMLIM 生成标注界限作为默认文字。将DIMLIM设置为“开”将会关闭DIMTOL。
    DIMLTEX1 设置第一条尺寸界线的线型。值为随层、随块或线型名称。
    DIMLTEX2 设置第二条尺寸界线的线型。值为随层、随块或线型名称。
    DIMLTYPE 设置尺寸线的线型。值为随层、随块或线型名称。
    DIMLUNIT 设置所有标注类型(角度标注除外)的单位。
    DIMLWD 为尺寸线指定线宽。其值是标准线宽。
    DIMLWE 为尺寸界线指定线宽。其值是标准线宽。
    DIMPOST 指定标注测量值的文字前缀或后缀(或两者都指定)。
    DIMRND 将所有标注距离舍入到指定值。
    DIMSAH 控制尺寸线箭头块的显示。
    DIMSCALE 设置应用于标注变量(可指定大小、距离或偏移量)的全局比例因子。
    DIMSD1 控制是否显示第一条尺寸线和箭头。
    DIMSD2 控制是否显示第二条尺寸线和箭头。
    DIMSE1 控制是否禁止显示第一条尺寸界线。
    DIMSE2 控制是否禁止显示第二条尺寸界线。
    DIMSHO 旧式的。除用于保持脚本的完整性外没有任何影响。
    DIMSOXD 如果尺寸界线内没有足够的空间,则隐藏箭头。
    DIMSTYLE 当前使用的标注样式的名称。
    DIMTAD 控制文字相对于尺寸线的垂直位置。
    DIMTDEC 设置标注主单位的公差值中要显示的小数位数。
    DIMTFAC 与通过DIMTXT系统变量设置一样,指定分数和公差值的文字高度相对于标注文字高度的比例因子。
    DIMTFILL 控制标注文字的背景。
    DIMTFILLCLR 设置标注中文字背景的颜色。
    DIMTIH 控制所有标注类型(坐标标注除外)的标注文字在尺寸界线内的位置。
    DIMTIX 在尺寸界线之间绘制文字。
    DIMTM 设置标注文字的最小(下)公差极限(当DIMTOL或DIMLIM设置为开时)。
    DIMTMOVE 设置标注文字的移动规则。
    DIMTOFL 控制是否在尺寸界线之间绘制尺寸线(即使标注文字被放置在尺寸界线之外)。
    DIMTOH 控制标注文字在尺寸界线外的位置。
    DIMTOL 将公差附在标注文字之后。将DIMTOL设置为开将会关闭DIMLIM。
    DIMTOLJ 设置公差值相对于标注文字的垂直对正方式。
    DIMTP 设置标注文字的最大(上)公差极限(当DIMTOL或DIMLIM设置为开时)。
    DIMTSZ 指定线性标注、半径标注以及直径标注中用于替代箭头的小斜线的尺寸。
    DIMTVP 控制标注文字在尺寸线上方或下方的垂直位置。
    DIMTXSTY 指定标注的文字样式。
    DIMTXT 指定标注文字的高度(除非当前文字样式具有固定的高度)。
    DIMTZIN 控制对公差值的消零处理。
    DIMUNIT 旧式的。保留在产品中以保持脚本的完整性。DIMUNIT将替换为DIMLUNIT和DIMFRAC。
    DIMUPT 控制用户定位文字选项。
    DIMZIN 控制对主单位值的消零处理。
    DISPSILH 控制三维实体对象轮廓边在二维线框或三维线框视觉样式中的显示。
    DISTANCE 存储DIST命令计算出的距离。
    DONUTID 设置圆环的默认内径。
    DONUTOD 设置圆环的默认外径。此值不能为零。
    DRAGMODE 控制拖动对象的显示。
    DRAGP1 设置重生成拖动模式下的输入采样率。
    DRAGP2 设置快速拖动模式下的输入采样率。
    DRAGVS 创建三维实体图元以及拉伸实体和拉伸曲面时设置视觉样式。
    DRAWORDERCTL 控制重叠对象的显示次序。受继承影响的命令有BREAK、FILLET、HATCH、HATCHEDIT、EXPLODE、TRIM、JOIN、PEDIT和OFFSET。
    DRSTATE 确定“图形修复管理器”窗口处于打开还是关闭状态。
    DTEXTED 指定为编辑单行文字而显示的用户界面。
    DWFFRAME 确定DWF参考底图边框是否可见。
    DWFOSNAP 确定是否为附着在图形中的DWF参考底图中的几何图形启用对象捕捉。
    DWGCHECK 打开图形时检查图形中是否存在潜在问题。
    DWGCODEPAGE 与SYSCODEPAGE系统变量存储相同的值(由于兼容性原因)。
    DWGNAME 存储当前图形的名称。
    DWGPREFIX 存储图形的驱动器和文件夹前缀。
    DWGTITLED 指示当前图形是否已命名。
    DXEVAL 控制数据提取处理表何时与数据源比较,如果数据不是当前数据,则显示更新通知
    DYNDIGRIP 控制在夹点拉伸编辑期间显示哪些动态标注。必须将DYNDIVIS系统变量设置为 2,这将显示所有的动态标注。
    DYNDIVIS 控制在夹点拉伸编辑期间显示的动态标注数量。DYNDIGRIP控制在夹点拉伸编辑期间显示哪些动态标注。
    DYNMODE 打开或关闭动态输入功能。全部功能都打开时,上下文将控制所显示的内容。
    DYNPICOORDS 控制指针输入是使用相对坐标格式,还是使用绝对坐标格式。
    DYNPIFORMAT 控制指针输入是使用极轴坐标格式,还是使用笛卡尔坐标格式。此设置仅适用于第二点或下一点。
    DYNPIVIS 控制何时显示指针输入。
    DYNPROMPT 控制“动态输入”工具栏提示中提示的显示。
    DYNTOOLTIPS 控制受工具栏提示外观设置影响的工具栏提示。
    EDGEMODE 控制TRIM和EXTEND命令确定边界的边和剪切边的方式。
    ELEVATION 存储新对象相对于当前UCS的当前标高。
    ENTERPRISEMENU 显示企业CUI(如果已定义)的文件名,包括文件名的路径。
    ERRNO
    AutoLISP函数调用导致AutoCAD检测到错误时,显示相应的错误代码的编号。
    ERSTATE 确定“外部参照”选项板处于打开还是关闭状态。
    EXPERT 控制是否显示某些特定提示。
    EXPLMODE 控制EXPLODE命令是否支持按非统一比例缩放 (NUS) 的块。
    EXTMAX 存储图形范围右上角点的值。
    EXTMIN 存储图形范围左下角点的值。
    EXTNAMES 为存储在定义表中的命名对象名称(例如线型和图层)设置参数。
    FACETRATIO 控制圆柱和圆锥实体镶嵌面的宽高比。设置为 1 将增加网格密度以改善渲染模型和着色模型的质量。
    FACETRES 调整着色对象和删除了隐藏线的对象的平滑度。有效值为 0.01 到 10.0。
    FIELDDISPLAY 控制显示的字段是否带有灰色背景。不打印背景。
    FIELDEVAL 控制字段的更新方式。
    FILEDIA 禁止显示文件导航对话框。
    FILLETRAD 存储当前的圆角半径。
    FILLMODE 指定是否填充图案填充和填充、二维实体以及宽多段线。
    FONTALT 指定找不到指定的字体文件时要使用的替换字体。
    FONTMAP 指定要使用的字体映射文件。
    FRONTZ 按图形单位存储当前视口中的前向剪裁平面距离目标平面的偏移量。
    FULLOPEN 指示当前图形是否局部打开。
    FULLPLOTPATH 控制是否将图形文件的完整路径发送到后台打印。
    GRIDDISPLAY 控制栅格的显示行为和显示界限。
    GRIDMAJOR 控制主栅格线与次栅格线比较的频率。有效值范围为从 1 到 100。
    GRIDMODE 指定栅格的开关状态。
    GRIDUNIT 指定当前视口的栅格间距(X和Y方向)。
    GRIPBLOCK 选定后,控制块中嵌套对象上的夹点的显示。
    GRIPCOLOR 控制未选中夹点的颜色。有效取值范围为 1 到 255。
    GRIPDYNCOLOR 控制动态块的自定义夹点的颜色。有效取值范围为 1 到 255。
    GRIPHOT 控制选定夹点的颜色。有效取值范围为 1 到 255。
    GRIPHOVER 控制光标暂停在未选定夹点上时该夹点的填充颜色。有效取值范围为 1 到 255。
    GRIPOBJLIMIT 选择集包括的对象多于指定数量时,禁止显示夹点。
    GRIPS 控制选择集夹点在“拉伸”、“移动”、“旋转”、“比例缩放”和“镜像夹点”模式中的使用。
    GRIPSIZE 以像素为单位设置夹点框的大小。有效取值范围为 1 到 255。
    GRIPTIPS 控制当光标悬停在支持夹点提示的动态块和自定义对象的夹点上时夹点提示的显示。
    GTAUTO 控制在设置为三维视觉样式的视口中启动命令之前选择对象时,夹点工具是否自动显示。
    GTDEFAULT 控制在三维视图中分别启动MOVE和ROTATE命令时,3DMOVE和 3DROTATE命令是否自动启动。
    GTLOCATION 运行 3DMOVE或 3DROTATE命令之前选择对象时,控制夹点工具的初始位置。
    HALOGAP 指定一个对象被另一个对象遮挡处要显示的间距。按照一英寸的百分比指定该值,并且它不受缩放级别的影响。
    HANDLES 报告应用程序是否可以访问对象句柄。
    HIDEPRECISION 控制消隐和着色的精度。
    HIDETEXT 指定执行HIDE命令时是否处理由TEXT、DTEXT或MTEXT命令创建的文字对象。
    HIGHLIGHT 控制对象的亮显;不影响使用夹点选定的对象。
    HPANG 指定填充图案的角度。
    HPASSOC 控制填充图案和渐变填充是否关联。
    HPBOUND 控制由BHATCH和BOUNDARY命令创建的对象类型。
    HPDOUBLE 指定用户定义图案的双向填充图案。双向将指定与原始直线成 90 度角绘制的第二组直线。
    HPDRAWORDER 控制图案填充和填充的绘图次序。存储“图案填充和填充”对话框中的“绘图次序”设置。
    HPGAPTOL 设置图案填充边界时可以忽略的最大间隙,默认值为 0。
    HPMAXLINES 控制将生成的填充线的最大数目。可在100到10,000,000之间对值进行设置。
    HPINHERIT 控制在HATCH和HATCHEDIT命令中使用“继承特性”时结果图案填充的图案填充原点。
    HPNAME 设置默认填充图案,输入句点 (.)将HPNAME重置为默认值。
    HPOBJWARNING 设置可以选择的图案填充边界对象数量(超过此数量将显示警告信息)。
    HPORIGIN 相对于当前用户坐标系为新的图案填充对象设置图案填充原点。
    HPORIGINMODE 控制HATCH确定默认图案填充原点的方式。
    HPSCALE 指定填充图案的比例因子,其值必须大于零。
    HPSEPARATE 控制在几个闭合边界上进行操作时,HATCH是创建单个图案填充对象,还是分别创建各个图案填充对象。
    HPSPACE 指定用户定义的简单图案的填充图案线间距,其值必须大于零。
    HYPERLINKBASE 指定图形中用于所有相对超链接的路径。
    IMAGEHLT 控制是亮显整个光栅图像还是仅亮显光栅图像边框。
    IMPLIEDFACE 控制隐含面的检测。
    INDEXCTL 控制是否创建图层和空间索引并将其保存到图形文件中。
    INETLOCATION 存储BROWSER命令和“浏览Web”对话框所使用的Internet网址。
    INPUTHISTORYMODE 控制用户输入历史记录的显示内容和位置。
    INSBASE 存储BASE命令设置的插入基点,用当前空间的UCS坐标表示。
    INSNAME 为INSERT命令设置默认块名。
    INSUNITS 指定插入或附着到图形中的块、图像或外部参照进行自动缩放所用的图形单位值。
    INSUNITSDEFSOURCE 当INSUNITS设置为 0 时,设置源内容单位值。
    INSUNITSDEFTARGET 当INSUNITS设置为 0 时,设置目标图形单位值。
    INTELLIGENTUPDATE 控制图形的刷新率。默认值为 20 帧每秒。
    INTERFERECOLOR 设置干涉对象的颜色。
    INTERFEREOBJVS 设置干涉对象的视觉样式。
    INTERFEREVPVS 指定检查干涉时视口的视觉样式。
    INTERSECTIONCOLOR 控制视觉样式设置为“二维线框”时三维曲面交线处的多段线的颜色。
    INTERSECTIONDISPLAY 控制视觉样式设置为“二维线框”时三维曲面交线处的多段线的显示。
    ISAVEBAK 是否创建备份文件 (BAK)。
    ISAVEPERCENT 确定图形文件中所允许的增量保存耗损空间总量,增量保存只更新保存的图形文件中已更改的部分,从而减少保存图形文件所需的时间。如果ISAVEPERCENT设置为 0,则每一次都进行完全保存。
    ISOLINES 指定对象上每个面的轮廓线数目。有效整数值为 0 到 2047。
    LASTANGLE 存储相对于当前空间的当前UCS的XY平面输入的上一圆弧的端点角度。
    LASTPOINT 存储上一次输入的点。
    LASTPROMPT 存储回显到命令行的上一个字符串。
    LATITUDE 以十进制格式指定图形模型的纬度。
    LAYEREVAL 控制何时计算图层管理器中的“未协调新图层”过滤器列表中的新图层。
    LAYERFILTERALERT 是否删除图层过滤器以提高性能。
    LAYERNOTIFY 指定何时显示尚未协调的新图层的警告。
    LAYLOCKFADECTL 控制锁定图层上的对象的褪色
    LAYOUTREGENCTL 指定“模型”选项卡和布局选项卡中的显示列表的更新方式以提高性能。
    LEGACYCTRLPICK 指定用于循环选择的键和CTRL+单击的操作。
    LENSLENGTH 存储透视视图中使用的焦距(以毫米为单位)。
    LIGHTGLYPHDISPLAY 控制是否显示光线轮廓。此系统变量设置为“关”时,不显示代表图形中的光源的轮廓。
    LIGHTINGUNITS 控制是使用常规光源还是使用光度控制光源,并指示当前的光学单位
    LIGHTLISTSTATE 指示是否已打开“模型中的光源”窗口。
    LIGHTSINBLOCKS 控制渲染时是否使用块中包含的光源
    LIMCHECK 控制是否可以在栅格界限之外创建对象。
    LIMMAX 存储当前空间的右上方栅格界限。
    LIMMIN 存储当前空间的左下方栅格界限。
    LINEARBRIGHTNESS 控制标准光源流程中图形的全局亮度级别。
    LINEARCONTRAST 控制标准光源流程中图形的全局对比度级别。
    LOCALE 显示用于指示当前区域的代码。
    LOCALROOTPREFIX 存储根文件夹的完整路径,该文件夹中安装了本地可自定义文件。
    LOCKUI 指定锁定工具栏和可固定窗口(例如“设计中心”和“特性”选项板)的位置和大小。
    LOFTANG1 设置通过放样操作中第一个横截面的拔模斜度。
    LOFTANG2 设置通过放样操作中最后一个横截面的拔模斜度。
    LOFTMAG1 设置通过放样操作中第一个横截面的拔模斜度的幅值。
    LOFTMAG2 设置通过放样操作中最后一个横截面的拔模斜度的幅值。
    LOFTNORMALS 控制放样对象通过横截面处的法线。指定路径或导向曲线时忽略该设置。
    LOFTPARAM 控制放样实体和曲面的形状。
    LOGEXPBRIGHTNESS 控制使用光度控制光源时图形的全局亮度级别
    LOGEXPCONTRAST 控制使用光度控制光源时图形的全局对比度级别
    LOGEXPDAYLIGHT 控制使用光度控制光源时是否使用室外日光
    LOGEXPMIDTONES 控制使用光度控制光源时图形的全局中色调级别
    LOGFILEMODE 指定是否将文本窗口的内容写入日志文件。
    LOGFILENAME 指定当前图形的文本窗口日志文件的路径和名称。
    LOGFILEPATH 指定任务中所有图形的文本窗口日志文件的路径。
    LOGINNAME 将显示启动程序时配置或输入的用户名。
    LONGITUDE 以十进制格式指定图形模型的经度。
    LTSCALE 设置全局线型比例因子。
    LUNITS 设置线性单位。
    LUPREC 设置长度单位的小数位数。
    LWDEFAULT 设置默认线宽值。
    LWDISPLAY 控制是否显示线宽。
    LWUNITS 控制线宽单位是以英寸显示还是以毫米显示。
    MATSTATE 指示是否已打开“材质”窗口。
    MAXACTVP 设置布局中可同时激活的的视口的最大数目。
    MAXSORT 设置由列表命令进行排序的符号名或块名的最大数目。
    MBUTTONPAN 控制定点设备上的第三个按钮或滑轮的操作。
    MEASUREINIT 控制从头创建的图形是使用英制还是使用公制默认设置。
    MEASUREMENT 控制当前图形是使用英制还是公制填充图案和线型文件。
    MENUCTL 控制屏幕菜单中的页面切换。
    MENUECHO 设置菜单回显和提示控制位。
    MENUNAME 存储自定义文件名,包括文件名的路径。
    MIRRTEXT 控制MIRROR命令反映文字的方式。
    MODEMACRO 在状态行显示字符串,例如当前图形的名称、时间/日期戳记或特殊模式。
    MSMSTATE 存储一个值,用以指示打开或关闭标记集管理器。
    MSOLESCALE 控制具有粘贴到模型空间中的文字的OLE对象的大小。
    MSLTSCALE 缩放由annotation scale显示在“模型”选项卡上的线型
    MTEXTED 设置用于编辑多行文字对象的应用程序。
    MTEXTFIXED 设置多行文字的显示大小和位置。
    MTJIGSTRING 设置启动MTEXT命令时显示在光标位置的样例文字内容。
    MYDOCUMENTSPREFIX 存储用户当前登录的“My Documents”文件夹的完整路径。
    NOMUTT 禁止显示通常情况下不禁止显示的消息。
    NORTHDIRECTION 指定北方阳光的角度。
    OBSCUREDCOLOR 指定暗显直线的颜色。
    OBSCUREDLTYPE 指定遮挡线的线型。
    OFFSETDIST 设置默认的偏移距离。
    OFFSETGAPTYPE 控制偏移闭合多段线时处理线段之间的潜在间隙的方式。
    OLEFRAME 控制是否显示和打印图形中所有OLE对象的边框。
    OLEHIDE 控制OLE对象的显示和打印。
    OLEQUALITY 设置OLE对象的默认打印质量。
    OLESTARTUP 控制打印时是否加载嵌入的OLE对象的源应用程序。
    OPMSTATE 存储一个值,用以指示打开、关闭或隐藏“特性”选项板。
    ORTHOMODE 限定光标在正交方向移动。
    OSMODE 设置执行的对象捕捉模式。
    OSNAPCOORD 控制是否在命令提示下输入坐标以替代执行对象捕捉。
    OSNAPHATCH 旧式的。使用OSOPTIONS系统变量控制对象捕捉是否忽略图案填充对象。
    OSNAPNODELEGACY 控制“节点”对象捕捉是否可用于捕捉到多行文字对象。
    OSNAPZ 控制对象捕捉是否自动投影到与当前UCS中位于当前标高的XY平面平行的平面上。
    OSOPTIONS 使用动态UCS时,将自动隐藏图案填充对象和具有负Z值的几何体上的对象捕捉。
    PALETTEOPAQUE 控制是否可以使窗口透明。
    PAPERUPDATE 试图以不同于为绘图仪配置文件指定的默认值的图纸尺寸打印布局时,控制警告对话框的显示。
    PDMODE 控制显示点对象的方式。有关输入值的详细信息,请参见POINT命令。
    PDSIZE 设置点对象的显示尺寸。
    PEDITACCEPT 禁止在PEDIT中显示“选定的对象不是多段线”提示,将选定对象自动转换为多段线。
    PELLIPSE 控制由ELLIPSE命令创建的椭圆类型。
    PERIMETER 存储由AREA或LIST命令计算的最后一个周长值。
    PERSPECTIVE 指定当前视口是否显示透视视图。
    PERSPECTIVECLIP 确定眼点剪裁的位置。
    PFACEVMAX 设置每个面的最大顶点数。
    PICKADD 控制后续选择是替换当前选择集还是添加到其中。
    PICKAUTO 控制提示“选择对象”时是否自动显示选择窗口。
    PICKBOX 以像素为单位设置对象选择目标的高度。
    PICKDRAG 控制绘制选择窗口的方法。
    PICKFIRST 控制在发出命令之前(先选择后执行)还是之后选择对象。
    PICKSTYLE 控制编组选择和关联图案填充选择的使用。
    PLATFORM 指示正在使用的平台。
    PLINEGEN 设置围绕二维多段线的顶点生成线型图案的方式。
    PLINETYPE 指定是否使用优化的二维多段线。
    PLINEWID 存储默认的多段线宽度。
    PLOTOFFSET 控制打印偏移是相对于可打印区域还是相对于图纸边。
    PLOTROTMODE 控制打印方向。
    PLQUIET 控制是否显示可选的相关打印对话框和非致命脚本错误。
    POLARADDANG 存储极轴追踪和极轴捕捉的其他角度。
    POLARANG 设置极轴角增量。
    POLARDIST
    SNAPTYPE系统变量设置为 1(极轴捕捉)时,设置捕捉增量。
    POLARMODE 控制极轴追踪和对象捕捉追踪的设置。
    POLYSIDES 设置POLYGON命令的默认边数。取值范围为 3 到 1024。
    POPUPS 显示当前配置的显示驱动程序状态。
    PREVIEWEFFECT 指定用于预览对象选择的视觉效果。
    PREVIEWFILTER 从选择预览中排除指定的对象类型。
    PRODUCT 返回产品名称。
    PROGRAM 返回程序名称。
    PROJECTNAME 为当前图形指定工程名称。
    PROJMODE 设置用于修剪或延伸的当前投影模式。
    PROXYGRAPHICS 指定是否将代理对象的图像保存在图形中。
    PROXYNOTICE 在创建代理时显示通知。
    PROXYSHOW 控制代理对象在图形中的显示。
    PROXYWEBSEARCH 指定程序检查对象激活器的方式。
    PSLTSCALE 控制在图纸空间视口中显示的对象的线型比例。
    PSOLHEIGHT 保存POLYSOLID命令创建扫掠实体对象时最后一次输入的高度值。
    PSOLWIDTH 保存POLYSOLID命令创建扫掠实体对象时最后一次输入的的宽度值。
    PSTYLEMODE 指示当前图形处于颜色相关打印样式模式还是命名打印样式模式。
    PSTYLEPOLICY 控制打开在AutoCAD2000 之前的版本中创建的图形或不使用图形模板从头创建新图形时,使用的打印样式模式。
    PSVPSCALE 为所有新创建的视口设置视图比例因子。
    PUBLISHALLSHEETS 控制发出PUBLISH命令时如何填写“发布”对话框列表
    PUBLISHCOLLATE 控制是否将图纸作为单个作业发布
    PUCSBASE 存储定义正交UCS设置(仅用于图纸空间)的原点和方向的UCS名称。
    QCSTATE 确定“快速计算”计算器处于打开还是关闭状态。
    QTEXTMODE 控制文字的显示方式。
    RASTERDPI 控制将毫米或英寸转换为像素(或反之)时的图纸尺寸和打印比例。。
    RASTERPREVIEW 控制是否将BMP预览图像与图形一起保存。
    RECOVERYMODE 控制系统出现故障后是否记录图形修复信息。
    REFEDITNAME 显示正在编辑的参照名称。
    REGENMODE 控制图形的自动重生成。
    RE-INIT 重新初始化数字化仪、数字化仪端口和acad.pgp文件。
    REMEMBERFOLDERS 控制显示在标准文件选择对话框中的默认路径。
    RENDERPREFSSTATE 储存一个值,用以指示打开或关闭“渲染设置”选项板。
    RENDERUSERLIGHTS 控制渲染过程中是否转换用户光源
    REPORTERROR 控制程序异常关闭时是否可以向Autodesk发送错误报告。
    ROAMABLEROOTPREFIX 存储根文件夹的完整路径。
    RTDISPLAY 控制执行实ZOOM或PAN命令时光栅图像和OLE对象的显示。
    SAVEFIDELITY 控制保存图形时是否保存其视觉逼真度
    SAVEFILE 存储当前自动保存的文件名。
    SAVEFILEPATH 指定当前任务中所有自动保存文件目录的路径。
    SAVENAME 显示最近保存的图形的文件名和目录路径。
    SAVETIME 以分钟为单位设置自动保存时间间隔。
    SCREENBOXES 存储绘图区域的屏幕菜单区显示的框数。
    SCREENMODE 指示显示的状态。
    SCREENSIZE 以像素为单位存储当前视口大小(X和Y)。
    SELECTIONANNODISPLAY 控制选定annotative对象时,换算比例表示法是否暂时以较暗状态显示
    SELECTIONAREA 控制选择区域的显示效果。
    SELECTIONAREAOPACITY 控制进行窗口选择和交叉选择时选择区域的透明度。
    SELECTIONPREVIEW 控制光标滚动过对象时的亮显方式。
    SETBYLAYERMODE 控制为SETBYLAYER选择哪些特性
    SHADEDGE 控制渲染时边的着色。
    SHADEDIF 设置漫反射光与环境光的比率。
    SHADOWPLANELOCATION 控制用于显示阴影的不可见地平面的位置。
    SHORTCUTMENU 控制“默认”、“编辑”和“命令”模式的快捷菜单在绘图区域是否可用。
    SHOWHIST 控制图形中实体的“显示历史记录”特性。
    SHOWLAYERUSAGE 控制图层特性管理器中“指示正在使用的图层”选项是否被选。
    SHPNAME 设置默认的形名称。
    SIGWARN 控制打开带有附着的数字签名的文件时是否发出警告。
    SKETCHINC 设置用于SKETCH命令的记录增量。
    SKPOLY 确定SKETCH命令生成直线还是生成多段线。
    SNAPANG 设置当前视口的捕捉和栅格旋转角度。旋转角相对当前UCS指定。
    SNAPBASE 相对于当前UCS设置当前视口的捕捉和栅格原点。
    SNAPISOPAIR 控制当前视口的等轴测平面。
    SNAPMODE 打开或关闭捕捉模式。
    SNAPSTYL 设置当前视口的捕捉样式。
    SNAPTYPE 设置当前视口的捕捉类型。
    SNAPUNIT 设置当前视口的捕捉间距。
    SOLIDCHECK 为当前任务打开或关闭实体校验。
    SOLIDHIST 控制复合实体是否保留包含在复合实体中原始对象的“历史记录”。
    SPLFRAME 控制样条曲线和样条拟合多段线的显示。
    SPLINESEGS 设置PEDIT命令的“样条曲线”选项生成的样条拟合多段线线段数目。
    SPLINETYPE 设置PEDIT命令的“样条曲线”选项生成的曲线类型。
    SSFOUND 如果搜索图纸集成功,则显示图纸集路径和文件名。
    SSLOCATE 控制打开图形时是否定位和打开与该图形相关联的图纸集。
    SSMAUTOOPEN 控制当打开与图纸相关联的图形时图纸集管理器的显示行为。
    SSMPOLLTIME 控制图纸集中状态数据的自动刷新时间间隔。
    SSMSHEETSTATUS 控制图纸集中状态数据的刷新方式。
    SSMSTATE 确定“图纸集管理器”窗口处于打开还是关闭状态。
    STANDARDSVIOLATION 指定创建或修改非标准对象时,是否通知用户当前图形中存在标准冲突。
    STARTUP 控制使用NEW和QNEW命令创建新图形时,是否显示“创建新图形”对话框。还控制当应用程序启动时是否显示“启动”对话框。
    STEPSIZE 指定漫游或飞行模式中每一步的大小。
    STEPSPERSEC 指定漫游或飞行模式中每秒执行的步数。
    SUNPROPERTIESSTATE 指示“阳光特性”窗口处于打开还是关闭状态。
    SUNSTATUS 控制阳光是否在当前视口中投射光线。
    SURFTAB1 为RULESURF和TABSURF命令设置要生成的列表数目。同时为REVSURF和EDGESURF命令设置在M方向的网格密度。
    SURFTAB2 为REVSURF和EDGESURF命令设置在N方向的网格密度。
    SURFTYPE 控制PEDIT命令的“平滑”选项要执行的曲面拟合类型。
    SURFU 为PEDIT命令的“平滑”选项设置在M方向的曲面密度以及曲面对象上的U素线密度。
    SURFV 为PEDIT命令的“平滑”选项设置在N方向的曲面密度以及曲面对象上的V素线密度。
    SYSCODEPAGE 指示由操作系统所决定的系统代码页。要更改代码页,请参见操作系统的“帮助”。
    TABLEINDICATOR 控制当打开在位文字编辑器以编辑表格单元时,行数和列字母的显示。
    TABLETOOLBAR 控制表格工具栏的显示。
    TABMODE 控制数字化仪的使用。
    TARGET 存储当前视口中目标点的位置(用UCS坐标表示)。
    TBCUSTOMIZE 控制是否可以自定义工具选项板组。
    TDCREATE 存储创建图形时的本地时间和日期。
    TDINDWG 存储总的编辑时间,即在两次保存当前图形之间花费的总时间。
    TDUCREATE 存储创建图形时的通用时间和日期。
    TDUPDATE 存储上次更新/保存时的本地时间和日期。
    TDUSRTIMER 存储用户花费时间计时器。
    TDUUPDATE 存储上次更新/保存时的通用时间和日期。
    TEMPOVERRIDES 打开或关闭正交模式、对象捕捉或极轴模式临时替代键。
    TEMPPREFIX 包含为放置临时文件而配置的目录名(如果有的话),附带路径分隔符。
    TEXTEVAL 控制如何判定用TEXT(使用AutoLISP)或 -TEXT输入的文字字符串。
    TEXTFILL 控制打印和渲染时TrueType字体的填充方式。
    TEXTOUTPUTFILEFORMAT 提供打印和文本窗口日志文件的Unicode选项。
    TEXTQLTY 设置文字轮廓的分辨率镶嵌精度
    TEXTSIZE 设置用当前文字样式绘制的新文字对象的默认高度。
    TEXTSTYLE 当前使用的文字样式的名称。
    THICKNESS 设置当前的三维厚度。
    TILEMODE 将“模型”选项卡或上一个布局选项卡置为当前。
    TIMEZONE 设置图形中阳光的时区。
    TOOLTIPMERGE 将绘图图工具栏提示合并为单个工具栏提示。
    TOOLTIPS 控制工具栏上工具栏提示的显示。
    TPSTATE 确定“工具选项板”窗口处于打开还是关闭状态。
    TRACEWID 设置宽线的默认宽度。
    TRACKPATH 控制极轴追踪和对象捕捉追踪对齐路径的显示。
    TRAYICONS 控制是否在状态栏显示状态托盘。
    TRAYNOTIFY 控制是否在状态栏托盘中显示服务通知。
    TRAYTIMEOUT 控制服务通知的显示时间长度(以秒为单位)。
    TREEDEPTH 指定最大深度,即树状结构的空间索引可以分出分支的次数。
    TREEMAX 通过限制空间索引(八分树)中的节点数目,从而限制重生成图形时占用的内存。
    TRIMMODE 控制是否修剪倒角和圆角选定边。
    TSPACEFAC 控制多行文字的行间距。
    TSPACETYPE 控制多行文字中使用的行间距类型。
    TSTACKALIGN 控制堆叠文字的垂直对齐方式。
    TSTACKSIZE 控制堆叠文字分数高度相对于选定文字的当前高度的百分比。
    UCSAXISANG 使用UCS命令的X、Y或Z选项绕其一个轴旋转UCS时,存储默认角度。
    UCSBASE 存储定义正交UCS设置的原点和方向的UCS名称。
    UCSDETECT 控制是否已激活动态UCS获取。
    UCSFOLLOW 从一个UCS转换到另一个UCS时是否生成平面视图。
    UCSICON 显示当前视口或布局的UCS图标。
    UCSNAME 存储当前空间当前视口的当前坐标系名称。
    UCSORG 存储当前空间中当前视口的当前坐标系原点。
    UCSORTHO 确定恢复正交视图时是否自动恢复相关的正交UCS设置。
    UCSVIEW 确定当前UCS是否随命名视图一起保存。
    UCSVP 确定视口中的UCS是保持不变还是进行相应改变以反映当前视口的UCS状态。
    UCSXDIR 存储当前空间中当前视口的当前UCS的X方向。
    UCSYDIR 存储当前空间中当前视口的当前UCS的Y方向。
    UNDOCTL 指示UNDO命令的“自动”、“控制”和“编组”选项的状态。
    UNDOMARKS 存储“标记”选项放置在UNDO控制流中的标记数目。
    UNITMODE 控制单位的显示格式。
    UPDATETHUMBNAIL 控制图纸集管理器中的略图预览的更新。
    USERI1-5 提供整数值存储和检索功能。共有五个系统变量:USERI1、USERI2、USERI3、USERI4 和USERI5。
    USERR1-5 提供实数的存储和检索功能。共有五个系统变量:USERR1、USERR2、USERR3、USERR4 和USERR5。
    USERS1-5 提供文字字符串数据的存储和检索功能。共有五个系统变量:USERS1、USERS2、USERS3、USERS4 和USERS5。
    VIEWCTR 存储当前视口中视图的中心。该值用UCS坐标表示。
    VIEWDIR 存储当前视口中的观察方向(用UCS坐标表示)。
    VIEWMODE 存储当前视口的观察模式。
    VIEWSIZE 存储当前视口中显示的视图的高度(按图形单位测量)。
    VIEWTWIST 存储相对于WCS测量的当前视口的视图旋转角度。
    VISRETAIN 控制依赖外部参照的图层的特性。控制可见性、颜色、线型、线宽和打印样式。
    VPLAYEROVERRIDES 指示对于当前图层视口是否存在任何具有视口 (VP) 特性替代的图层。
    VPLAYEROVERRIDESMODE 控制是否显示和打印与布局视口关联的图层特性替代。
    VPMAXIMIZEDSTATE 存储指示是否将视口最大化的值。
    VSBACKGROUNDS 控制是否在应用于当前视口的视觉样式中显示背景。
    VSEDGECOLOR 设置当前视口视觉样式中边的颜色。
    VSEDGEJITTER 控制使直线显示出铅笔勾画特征的程度。
    VSEDGEOVERHANG 将线延伸至超过其交点,以达到手绘的效果。
    VSEDGES 控制显示在视口中的边的类型。
    VSEDGESMOOTH 指定显示折痕边的角度。
    VSFACECOLORMODE 控制如何计算面的颜色。
    VSFACEHIGHLIGHT 控制当前视口中不具有材质的面上镜面亮显的显示。
    VSFACEOPACITY 控制当前视口中面的透明度。
    VSFACESTYLE 控制如何在当前视口中显示面。
    VSHALOGAP 设置应用于当前视口的视觉样式中的光晕间隔。
    VSHIDEPRECISION 控制应用于当前视口的视觉样式中的隐藏和着色的精度。
    VSINTERSECTIONCOLOR 指定应用于当前视口的视觉样式中相交多段线的颜色。
    VSINTERSECTIONEDGES 控制应用于当前视口的视觉样式中相交边的显示。
    VSINTERSECTIONLTYPE 设置应用于当前视口的视觉样式中的交线线型。
    VSISOONTOP 显示应用于当前视口的视觉样式中着色对象顶部的素线。
    VSLIGHTINGQUALITY 设置当前视口中的光源质量。
    VSMATERIALMODE 控制当前视口中材质的显示。
    VSMAX 存储当前视口虚屏的右上角。
    VSMIN 存储当前视口虚屏的左下角。
    VSMONOCOLOR 为应用于当前视口的视觉样式中面的单色和染色显示设置颜色。
    VSOBSCUREDCOLOR 指定应用于当前视口的视觉样式中遮挡(隐藏)线的颜色。
    VSOBSCUREDEDGES 控制是否显示遮挡(隐藏)边。
    VSOBSCUREDLTYPE 指定应用于当前视口的视觉样式中遮挡(隐藏)线的线型。
    VSSHADOWS 控制视觉样式是否显示阴影。
    VSSILHEDGES 控制应用于当前视口的视觉样式中的实体对象轮廓边的显示。
    VSSILHWIDTH 以像素为单位指定当前视口中轮廓边的宽度。
    VSSTATE 打开或关闭“视觉样式”窗口。
    VTDURATION 以毫秒为单位设置平滑视图过渡的期限。
    VTENABLE 控制何时使用平滑视图过渡。
    VTFPS 以帧/每秒为单位设置平滑视图过渡的最小速度。
    WHIPARC 控制圆和圆弧是否平滑显示。
    WHIPTHREAD 控制是否使用附加处理器来提高操作速度,WHIPTHREAD对单处理器计算机无效。
    WINDOWAREACOLOR 控制窗口选择时透明选择区域的颜色。
    WMFBKGND 控制以Windows图元文件 (WMF) 格式插入对象时背景的显示。
    WMFFOREGND 控制以Windows图元文件 (WMF) 格式插入对象时前景色的指定方式。
    WORLDUCS 指示UCS是否与WCS相同。
    WORLDVIEW 确定响应DVIEW和VPOINT命令的输入是相对于WCS(默认)还是相对于当前UCS。
    WRITESTAT 指示图形文件是只读的还是可写的。
    WSCURRENT 在命令行界面中返回当前工作空间名称并将工作空间置为当前工作空间。
    XCLIPFRAME 控制外部参照剪裁边界的可见性。
    XEDIT 控制当前图形被其他图形参照时是否可以在位编辑。
    XFADECTL 控制正被在位编辑的参照的褪色度百分比。
    XLOADCTL 打开或关闭外部参照的按需加载功能,并控制是打开参照的图形还是打开副本。
    XLOADPATH 创建用于存储按需加载的外部参照文件临时副本的路径。
    XREFCTL 控制是否创建外部参照日志(XLG)文件。
    XREFNOTIFY 控制更新或缺少外部参照通知。
    XREFTYPE 控制附着或覆盖外部参照时的默认参照类型。
    ZOOMFACTOR 控制向前或向后滑动鼠标滚轮时比例的变化程度。
    ZOOMWHEEL 滚动鼠标中间的滑轮时,切换透明缩放操作的方向。*

    展开全文
  • 变量“公司年龄”通常称为控制变量。 很少解释为什么必要或控制什么。 适当记录变量的统计意义或重要性; 几乎没有提供其解释。 本文证明了此变量并未提供用户希望我们相信的任何明智信息。 本文提供了许多示例,...
  • 现代复杂的工业生产过程,通过实施先进控制,可以大大提高工业生产过程操作和控制的稳定性,改善工业生产过程的动态性能,减少关键变量的运行波动幅度,使其更接近于优化目标值,从而将工业生产过程推向更接近装置...
  • Terraform中输入变量

    2018-08-24 14:31:00
    2019独角兽企业重金招聘Python工程师标准>>> ...
  • java面向对象中的变量

    2012-04-07 20:33:10
    变量 变量的分类 变量分为成员变量和局部变量。...从程序可读性角度看,是多个意义的单词组合而成,其中第一个单词首字母小写,后面每个单词首字母大写。  成员变量:在类范围里定义的变量。  类
  • Win8.1下JDK环境变量配置方法

    千次阅读 2015-03-22 10:11:45
    Win8.1下JDK环境变量设置方法首先百度下载JDK,我下载的是JDK8.0.250.18...1.打开控制面板——》系统和安全——》系统——》左边的高级系统设置——》环境变量 2.在系统变量里点新建,新建一个系统变量变量名为
  • 虚拟变量定义在实际建模过程中,被解释变量不但受定量变量影响,同时还受定性变量影响。...由于定性变量通常表示的是某种特征的和无,所以量化方法可采用取值为1或0。这种变量称作虚拟变量,用D表示。
  • 线性回归分析中的哑变量

    万次阅读 2016-01-11 22:44:03
     最近偶尔在重温统计学,发现自己工作后用了各种高级的统计...哑变量(Dummy Variable),也叫虚拟变量,引入哑变量的目的是,将不能够定量处理的变量量化,如职业、性别对收入的影响,战争、自然灾害对GDP的影
  • Stata中因子变量的使用方法

    万次阅读 2018-06-26 18:07:35
    其他控制变量 的 交乘项 ,然后再 联合检验 分组变量的系数以及所有交乘项的系数是否都等于0。此时,即使我们不使用 chowtest 命令,也可以轻松实现 邹氏检验 ,Stata命令如下: . global xx "hours age ...
  • java的下载及环境变量的配置

    千次阅读 2019-04-28 01:52:26
    讲讲java的安装,java的官方下载地址为 ...目前oracle官网提供了java的很多版本,但大多数开发者使用的还是java8,博主也是java8,java8目前最稳定,java分为javase,javaee,javame,javase为标准版,javaee为企业...
  • 多重对应分析在超过两个以上定类变量时候非常有效,当然首先我们要理解并思考,如果只有三个或有限的几个变量完全可以通过数据变换和交互表变量重组可以转换成两个定类变量,这时候就可以用简单对应分析了。...
  • 为什么尽量不要使用全局变量

    千次阅读 2020-04-07 16:42:37
    如何避免使用全局变量? http://qiusuoge.com/12683.html 1)如果只有某.c文件用,就static到该文件中,顺便把结构体定义也收进来; 当一个模块里面的全局变量超过3个(含)时,就用结构体包起来吧。要归0便一起归0,...
  •  最终放弃了找属性这一选项,另辟蹊径,直接从搜索程序中查找配置环境变量的位置,操作步骤如下:1) 在搜索框输入控制面板,并且打开2) 在控制面板页面搜索环境变量3) 选择编辑账户的环境变量就能看到...
  • 企业信息安全的范围技术控制:访问控制:对权限、对账户的控制,例如:控制某个账户可以访问某个系统或者不可以访问某个系统网络安全:局域网、广域网、城域网、交换机的配置、防火墙配置、路由器配置等等系统安全:...
  • 2019独角兽企业重金招聘Python工程师标准>>> ...
  • 本系列几章系统地介绍了开发中Hive常见的用户配置属性(有时称为参数,变量或选项),并说明了哪些版本引入了哪些属性,常见有哪些属性的使用,哪些属性可以进行Hive调优,以及如何使用的问题。以及日常Hive开发中...
  • 前言:移动智能设备的发展,推动了安卓另一个领域,包括智能电视和智能家居,以及可穿戴设备的大量使用,但是这些设备上的开发并不是和传统手机开发一样,特别是焦点控制和用户操作体验风格上很大的区别,本系列...
  • JAVA基础一(认识一下Java和Java变量和常量) 目录 一、Java初识 二、Java变量 一、Java初识 1、Java简介: Java是一门高级面向对象开发语言,发布于Sun公司,现已经被Oracle公司收购 2、Java程序执行过程:...
  • 2019独角兽企业重金招聘Python工程师标准>>> ...
  • 构建企业环境绩效与财务绩效的理论模型,分别以内部经营性指标净资产收益率和外部市场价值指标托宾Q值作为衡量企业财务绩效的因变量,以环境绩效为自变量,边际利润、资产年限、资产负债率和企业规模为控制变量,运用...
  • MySQL - 翻译 - 5.1 Reference Manual参考手册 - 5.1.3 Server System Variables服务器系统变量 - max_heap_table_sizemax_heap_table_sizeOption Sets Variable选项集变量Yes, max_heap_table_size是V
  • 其他控制变量 的 交乘项 ,然后再 联合检验 分组变量的系数以及所有交乘项的系数是否都等于0。此时,即使我们不使用 chowtest 命令,也可以轻松实现 邹氏检验 ,Stata命令如下: . global xx "hours age tenure ...
  • JAVA之旅(一)——基本常识,JAVA概念,开发工具,关键字/标识符,变量/常量,进制/进制转换,运算符,三元运算 Android老鸟重新学一遍JAVA是什么感觉?枯燥啊,乏味啊,而且归纳写博客,都是很痛苦的事情,但是程序...
  • AGV控制系统搭建

    万次阅读 多人点赞 2019-06-25 15:32:33
     本文介绍自动导引车(AGV)车载控制系统的实现过程,分为硬件搭建和软件设计两部分,并在其中穿插 AGV 控制的基础知识讲解。 1. 车载控制器 1.1 控制器的类型  车载控制器是控制系统乃至整个 AGV 的...
  • 2019独角兽企业重金招聘Python工程师标准>>> ...
  • Stata:多个变量组间均值\中位数差异检验

    万次阅读 多人点赞 2019-05-30 10:34:28
    :多个变量在多组之间两两差异检验,以回归分析为基础,可以控制异方差的影响 Note: ttest 和 median 为官方命令; ttable2 、 balancetable 和 ttable3 都是外部命令, 需要用如下命令安装。安装...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 109,493
精华内容 43,797
关键字:

企业控制变量有哪些