Nginx中文配置文档1-新手引导

本文主要翻译一部分常用的Nginx配置文档
环境:
Ubuntu14.04 x64
Nginx1.4.6

参考内容:
官方文档:http://nginx.org/en/docs/
相关概念:http://blog.hylstudio.cn/archives/380

感谢 Mandy Alexander 提供的参考资料:https://www.websiteplanet.com/blog/html-guide-beginners/

nginx的初步使用

安装:配置好apt源后,执行sudo apt-get install nginx即可
启动:sudo service nginx start
重启:sudo service nginx restart
关闭:sudo service nginx stop
查看状态:sudo service nginx status

默认目录

网站根目录:/usr/share/nginx/html
日志目录:/var/log/nginx
配置文件目录:/etc/nginx

配置文件目录中的
├── sites-available
├── sites-enabled
这两个文件夹和apache配置同理,可以配置多个站点。使用软连接生效。

原文:http://nginx.org/en/docs/beginners_guide.html

本引导提供了nginx基本的介绍和描述以,并提供一些可以用来练习的任务。假设nginx已经在读者的机器上装好了,如果还没有安装,请参考安装指导。这个指导描述了如何启动和停止nginx、重新加载配置文件、解释了配置文件的结构、描述了如何设置nginx用来提供静态内容的服务、如何配置nginx作为代理服务器以及如何用nginx连接FastCGI应用程序。

nginx有一个主进程和多个worker进程,主进程的主要任务是读取加载配置和维持worker进程,Worker进程负责处理实际的网络请求。 nginx使用了基于事件的模型和操作系统相关原型来高效在worker进程中分发请求。worker进程的数量定义在配置文件中,可能是固定的数值或自动的根据可用的CPU核心数调整(参见worker_processes)。

nginx和模块的运行方式由配置文件决定。默认情况下,配置文件名为nginx.conf,放在/usr/local/nginx/conf, /etc/nginx, 或/usr/local/etc/nginx

启动、停止、重新加载配置

以非服务形式启动:
想要启动nginx,执行可执行文件即可,一旦nginx启动,它可以通过调用可执行文件和-s参数来控制,语法如下:
nginx -s signal
在signal的位置可以是以下几种:

stop — 快速关闭
quit — 平滑的关闭
reload — 重新加载配置文件
reopen — 重新打开日志文件

例如,想等待worker处理完当前请求再退出可以这样写:
nginx -s quit
这个命令可以用启动nginx的同一个用户执行。
配置文件的更改不会立即生效,直到执行reload命令或重启nginx,命令如下:
nginx -s reload
一旦主进程收到重新加载配置文件的新号,它会检查新的配置文件语法是否正确并且尝试更新配置。如果成功了,主进程会开启新的worker进程并且向旧的worker进程发送关闭信号来重新加载配置文件。否则,主进程会回滚到之前的状态使用旧的配置继续工作。旧的worker进程接收到关闭信号后,停止接收新的连接请求并把当前的请求处理完,然后旧的进程会结束。

信号也可以在Unix工具的帮助下被发送给nginx,例如kill命令。在这种情况下信号会通过提供的PID直接发送给一个进程,这个PID默认被写入到了名为nginx.pid的文件中,默认情况下存在/usr/local/nginx/logs或者/var/run。例如如果主进程的PID是1628,想要发送QUIT信号的话,执行下面的命令:

kill -s QUIT 1628
想要获得所有运行中的nginx进程,可以使用ps命令如下:

ps -ax | grep nginx
想要知道更多的信息,请查看Controlling nginx章节

配置文件的结构

nginx由多个模块组成,这些模块通过配置文件中的指令控制。指令分为简单指令和块指令,一个简单指令由空格分隔的名称和参数组成,结尾是英文的分号(name parameter [parameter2];)。块指令和简单指令结构一样,但是最后不是分号,而是附加了一系列大括号括起来的附加指令。如果一个块指令可以在大括号中包含其他的指令,那么它可以被叫做上下文,例如events, http, server, and location。

指令放在配置文件中上下文之外,event和http指令属于主上下文、server属于http、location属于server。

以#开头的行为注释

提供静态内容服务

一个web服务器重要的任务就是提供文件(比如图片或静态的HTML页面)服务,你将会实现一个例子,web服务器会基于请求,从本地不同的文件夹中提供文件服务。/data/www (这里放着HTML文件)和 /data/images (包含了图片文件). 这要求你编辑配置文件并在http块下的server块中设置设置两个location块。
首先,创建 /data/www文件夹并且放进一个index.html文件,创建/data/images文件夹并且放入一些图片。

接下来,打开配置文件,默认的配置文件已经在server块写好了几个例子,大多数都被注释掉了。

一般来说,配置文件可能包括好几个server块用来区分不同的监听端口和服务器名称。一旦nginx决定哪个进程处理请求,它会测试在URI头部指定的参数是否和server块中location指令定义的参数不一致。
在server块下添加下面的location块:

这个location块指定要比较开头为“/”的URI请求。为了匹配请求,URL需要添加指定相对于根的路径。如果有多个location块匹配到了的话,nginx会选择匹配最长前缀的location。上面的location块指定了一个最短的前缀,所以当所有其他的location匹配失败的时候,这个location将会被使用。

接下来,添加第二个location块:

它会匹配开头为/images/的请求 (location / 也匹配这个请求,但是它是最短的前缀匹配).

最终的结果应该像下面这样。

这已经是一个可用的配置文件了,监听在默认的80端口,可以通过http://localhost/进行访问。
在所有开头为/images/的请求中,服务器会从/data/images文件夹中发送请求的文件。
例如:请求http://localhost/images/example.png的话,nginx会返回/data/images/example.png文件。如果这个文件不存在,nginx会返回404错误。

所有不以/images/开头的请求会被匹配到/data/www文件夹。
例如:请求http://localhost/some/example.html的话,nginx会返回/data/www/some/example.html文件。

为了应用新的设置,请重启nginx:
如果出现了某些异常,你可以尝试在access.log中找到原因,这个文件默认在/usr/local/nginx/logs或/var/log/nginx.

设置一个简单的代理服务器

一个常见的使用场景是nginx作为代理服务器,这意味着nginx服务器接收请求,转为其他服务器,接收结果后再发送给客户端。

我们接下来将会设置一个基本的代理服务器,这个服务器接收图片请求从本地获取文件,其他所有的请求会转给另一个服务器,在这个例子里,所有的服务将会被定义在一个nginx实例中。

首先,通过增加唉一个server块定义一个代理服务器,如下:

这将是一个监听8080端口的简单服务器并且匹配所有请求到/data/up1本地文件夹。创建这个文件夹并且放入index.html文件。注意root指令是放在server上下文下的,当备选location块的路径不包含自己的root指令的时候使用这样的root指令。

接下来,使用上一节的server配置,并更改它作为代理服务器。在第一个location块,增加proxy_pass指令,同时指定被代理服务器的协议、名称、端口。

我们要更改第二个location块的内容,它现在是匹配所有以/images/开头的请求,在/data/images文件夹寻找文件。想让它匹配常见的图片文件,更改成下面这样即可:

这个参数是一个正则表达式,匹配所有以.gif, .jpg, or .png结尾的请求,一个正则表达式应当在前面加个~符号,相应的请求会被匹配到/data/images文件夹。

当nginx选择一个location块处理一个请求时,它首先检查指定了前缀的location指令,记住最长匹配前缀的location,然后检查使用正则表达式的location。如果这里匹配到了使用正则表达式的location,那么nginx会选择使用正则表达式的location,否则就使用之前记住的那个。

最终的配置文件结果如下:

这个服务器会过滤所有结尾是.gif, .jpg, or .png的图片请求并匹配到/data/images文件夹(通过与root指令的参数拼接)并且转发所有其他的指令到上面配置的服务器。

为了应用新的设置,请重启nginx。

这里有更多的指令可能之后会在配置代理连接时用到。

设置FastCGI代理

nginx可以被用来作为路由请求多种框架和语言实现应用的FastCGI服务器,比如PHP。

和FastCGI运行最基本的配置是用fastcgi_pass指令代替proxy_pass指令。并且可以使用fastcgi_param指令设置转发给FastCGI服务器的参数。假设FastCGI服务器在localhost:9000。基于之前设置的代理服务器,用fastcgi_pass指令代替proxy_pass指令,并且更改参数为localhost:9000替换。在PHP中,SCRIPT_FILENAME蚕食是用来确定脚本名称的,QUERY_STRING参数是用来传递查询参数的。结果如下:

这样就设置了一个可以使用FastCGI协议转发所有非图片资源请求到localhost:9000的路由。

Apache2.4中文配置文档1

本文主要翻译一部分常用的apache2.4配置文档,因为之前在搭建个人博客的时候发现2.4的中文文档还还不多。
在某个版本后apache本身的的目录结构有点变化,而网上能搜到的方法很多都是直接更改主配置文件,这样并不好。
以下所有例子均以本站实际需求为例,结合官方文档进行说明。
环境:
Ubuntu14.04 x64
apache2.4

参考内容:
官方文档:http://httpd.apache.org/docs/2.4/zh-cn/
本站配置参考:http://blog.hylstudio.cn/archives/383
相关概念:http://blog.hylstudio.cn/archives/380

apache的初步使用

安装:配置好apt源后,执行sudo apt-get install apache2即可
启动:sudo service apache2 start
重启:sudo service apache2 restart
关闭:sudo service apache2 stop
查看状态:sudo service apache2 status

默认目录

网站根目录:/var/www/html
日志目录:/var/log/apache2
配置文件目录:/etc/apache2
配置文件目录结构如下
├── apache2.conf
├── conf-available
├── conf-enabled
├── envvars
├── magic
├── mods-available
├── mods-enabled
├── ports.conf
├── sites-available
└── sites-enabled

其中可以看到成对出现的文件夹有三对儿,分别是站点、模块、配置。
顾名思义,available下是可用的、enabled下是启用的。
相比直接更改主配置文件apache2.conf来说,修改这些更加方便。
启用的方法为进入到enable文件夹中执行软连接命令,把要启用的内容做个软连接到enabled目录下即可。
比如ln -s ../sites-enabled/000-default.conf .

接下来是常用的功能文档翻译

首先,配置文件的语法描述如下(巴克斯范式)

expr ::= “true” | “false”
| “!” expr
| expr “&&” expr
| expr “||” expr
| “(” expr “)”
| comp

comp ::= stringcomp
| integercomp
| unaryop word
| word binaryop word
| word “in” “{” wordlist “}”
| word “in” listfunction
| word “=~” regex
| word “!~” regex

stringcomp ::= word “==” word
| word “!=” word
| word “<” word
| word “<=” word | word “>” word
| word “>=” word

integercomp ::= word “-eq” word | word “eq” word
| word “-ne” word | word “ne” word
| word “-lt” word | word “lt” word
| word “-le” word | word “le” word
| word “-gt” word | word “gt” word
| word “-ge” word | word “ge” word

wordlist ::= word
| wordlist “,” word

word ::= word “.” word
| digit
| “‘” string “‘”
| “”” string “””
| variable
| rebackref
| function

string ::= stringpart
| string stringpart

stringpart ::= cstring
| variable
| rebackref

cstring ::= …
digit ::= [0-9]+

variable ::= “%{” varname “}”
| “%{” funcname “:” funcargs “}”

rebackref ::= “$” [0-9]

function ::= funcname “(” word “)”

listfunction ::= listfuncname “(” word “)”

端口监听

当apache启动的时候会绑定在本地机器上的一些端口和地址等待请求。默认情况下,它会监听本地所有的地址,然而实际需求可能只需要监听某些特定的端口、特定的地址,或者特定地址上的特定端口。这经常和虚拟主机(Virtual Host)特性结合在一起使用,端口监听决定了apache服务器在不同的IP地址、hostname、端口上如何响应。

Listen指令告诉服务器在特定的地址、特定的端口、或者特定地址的特定端口上接受请求,如果Listen命令仅指定了一个特定的端口,那么服务器会监听所有地址上的这个端口,如果同时指定了IP地址和端口,那么服务器将会监听指定地址上的指定端口,多个Listen指令可以被用来监听指定的多个地址和端口。服务器将会在任意指定监听的地址和端口上响应请求。

例如,如果想让服务器同时在80和8000端口响应请求,使用如下写法
Listen 80
Listen 8000

让服务器在192.0.2.1:80和192.0.2.5:8000响应请求,使用如下写法
Listen 192.0.2.1:80
Listen 192.0.2.5:8000

IPv6的地址必需用方括号括起来,如下
Listen [2001:db8::a00:20ff:fea7:ccea]:80

应当避免重复监听同一个地方,否则服务器启动时会看到下面的错误
(48)Address already in use: make_sock: could not bind to address [::]:80

IPv6相关事宜

越来越多的平台已经实现了IPv6,并且在这些平台上也支持APR、允许服务器申请IPv6套接字连接、处理、发送请求。

对服务器管理员来说一个复杂的因素是apache是否可以同时处理IPv4和IPv6的连接,在IPv6下处理IPv4套接字使用IPv4-mapped IPv6地址,这在很多平台上默认是可以的,但是在FreeBSD、NetBSD、OpenBSD上默认是不可以的。为了遵循操作系统方面的原则,一个特别的配置参数可以更改apache服务器的行为。

另一方面,在某些平台上,比如Linux和Tru64,同时处理IPv6和IPv4的方法有且仅有使用地址匹配。如果你想让apache用最少的套接字链接处理IPv6和IPv4,这要求必需使用IPv4-mapped IPv6地址,使用–enable-v4-mapped 参数即可。

–enable-v4-mapped这个参数除了在FreeBSD、NetBSD、OpenBSD上都是可以的。

如果你只想让apache服务器处理IPv4连接,无论你的平台是什么都可以被支持。使用Listen指令指定一个IPv4地址即可,如下
Listen 0.0.0.0:80
Listen 192.0.2.1:80

如果你的平台支持并且你想用独立的套接字处理IPv4和IPv6连接(例如禁用掉IPv4-mapped addresses),指定–disable-v4-mapped这个配置选项即可。

指定监听协议

监听指令的第二个可选参数是协议,如果没有指定,https默认是443,其他的默认为http,协议是用来决定哪个模块应该处理请求并且可以通过AcceptFilter指令来应用最优化的协议。
只要当你没有使用默认端口的时候才需要指定协议,例如在8443端口使用https协议:

Listen 192.170.2.1:8443 https

怎么和虚拟主机同时工作

Listen指令并没有实现虚拟主机,它仅仅告诉主服务器应该监听什么地址和端口。如果没有使用指令,服务器用同样的方式对所有的请求进行相应。然而可以被用来为一个或多个不同的端口和地址指定不同的行为。为了实现VirtualHost,服务器必须先监听一个地址或端口。在接下来的章节将会介绍使用VirtualHost指定地址和端口来设置不同的行为。注意如果使用了但是没有监听任何端口,那么服务器将不能被访问。

虚拟主机

如果你要调试虚拟主机配置,Apache 的命令行参数 -S 非常有用。即输入以下命令:
/usr/local/apache2/bin/httpd -S
这个命令将会显示 Apache 是如何解析配置文件的。仔细检查 IP 地址与服务器名称可能会帮助你发现配置错误 (参见 httpd 程序文档,以便了解其它命令行选项)。

虚拟主机分为两种,一种是基于名称的,一种是基于IP的
基于IP的虚拟主机:
它使用连接的IP地址来决定正确的主机用来服务,所以你需要为每个主机分配不同的IP地址。

基于名称的虚拟主机:
服务器依赖于客户端在HTTP请求头部报告的hostname来使用正确的主机,使用这个技术,不同的站点可以使用相同的IP。例如本站只有一个公网IP地址,却可以使用blog.hylstudio.cn、files.hylstudio.cn、tomcat.hylstudio.cn等不同的域名来共享一个公网IP地址。

基于名称的虚拟主机通常来说更简单一些,因为你仅需要配置你的DNS服务器解析不同的hostname到正确的IP地址并且配置apache服务器区分这些不同的地址即可。例如本站的多个二级域名都通过A记录解析到了同一个公网IP地址。基于名称的虚拟主机更加适应稀缺IP地址的需求,所以除非你使用的设备确实需求基于IP的虚拟主机,那么就应该使用基于名称的虚拟主机。由于历史原因,基于IP的虚拟主机的需要客户端的支持,现在已经不再适应一般情况下的web服务器了。

基于名称的虚拟主机建立于基于IP的虚拟主机选择算法上,这意味着搜索合适的servername仅会发生在基于IP的主机之间。
在这里主要介绍基于名称的虚拟主机。

服务器如何选择合适的基于名称的虚拟主机

要认识到,很重要的一点的:基于名称的虚拟主机解析的第一步是基于IP的解析。基于名称的虚拟主机解析仅仅是在缩小基于IP的虚拟主机的候选范围之后再选择最合适主机,在基于IP的虚拟主机地址中使用通配符(*)是不合适的。

当一个请求到来之后,服务器会根据请求中使用的IP地址和端口根据虚拟主机的配置参数匹配最佳(最具体)的虚拟主机。如果有一个以上的最佳匹配组合出现,apache服务器会继续比较ServerName和ServerAlias命令指定的名称。

如果你在基于名称的虚拟主机配置中省略了ServerName指令,服务器默认会从hostname得到主机的FQDN(完全合格域名/全称域名)。这种隐式的设置servername可能会导致与预期相反的虚拟主机匹配匹配,并且不鼓励这样。

IP地址和端口的组合的基于名称的默认虚拟主机
如果没有在包括具体IP地址和端口组合的虚拟主机设置中匹配到ServerName或者ServerAlias,那么列表中的第一个虚拟主机将会被使用。

基于名称的虚拟主机 (每个 IP 多个站点)

第一部是在配置文件为每个虚拟主机添加一块,在每个内部,你至少需要ServerName和DocumentRoot命令。ServerName指定指明了服务哪个站点,DocumentRoot指明了这个站点默认展示本地文件系统哪个路径下的东西。

Main host goes away(我实在不知道这段怎么翻译合适了=-=)
任意一个未被存在的匹配的请求都由全局的服务器配置来处理,无论hostname和ServerName是什么。
当你添加一个基于名称的虚拟主机时,如果这个虚拟主机的参数和一个已存在的IP端口组合重复了,那么请求将会由一个具体的虚拟主机处理。在这种情况下,一个机智的做法是创建一个默认的虚拟主机指定一个ServerName来匹配基本的站点。新的域名在同样的接口和端口上,但是要求独立的设置,他们可以作为子虚拟主机(不是默认的)被加入。

ServerName的继承

在每一个基于名称的虚拟主机中最好永远有一个具体的ServerName的列表。
如果一个虚拟主机没有指定具体的ServerName,那么将会从服务器的全局配置文件继承下来。如果没有全局的ServernName,当启动的时候会从DNS反向解析第一个监听的地址。 在这两种情况下,这个继承下来的SserverName会影响基于名称的虚拟主机的解析。所以最好在每一个基于名称的虚拟主机中最好永远有一个具体的ServerName的列表。

例如,假设你已经有了www.example.com,然后你想添加other.example.com虚拟主机,它们解析到了相同的IP地址。那么你仅需要简单的在配置文件中添加以下内容:

# This first-listed virtual host is also the default for *:80
ServerName www.example.com
ServerAlias example.com
DocumentRoot “/www/domain”
ServerName other.example.com
DocumentRoot “/www/otherdomain”

你可以灵活的在指令中星号的位置指定一个具体的IP地址。For example, you might want to do this in order to run some name-based virtual hosts on one IP address, and either IP-based, or another set of name-based virtual hosts on another address.(这句没看懂=_=求大神翻译)
ZHRMoe的翻译(他的博客:http://zhrmoe.com/):
比如,你这么做可以在一个IP地址上运行一些基于域名的虚拟主机(也可以是基于IP的),或者是在其他的地址上运行其他基于域名的虚拟主机。

许多服务想要通过一个以上的名称被访问,这可以通过ServerAlias指令实现。例如在第一个中,ServerAlias指定了一个其他的名称,那么用户就可以使用这个地址来访问同样的网站。
ServerAlias example.com *.example.com

加上这行之后,所有在example.com下的请求都会由www.example.com这个虚拟主机处理。通配符星号和问号可以用来被匹配名称。当然你不能仅仅把名称放在ServerName和ServerAlias后面,首先你要先让你的DNS按正确的规则解析这些域名。

基于名称的虚拟主机的匹配按照在配置文件中的出现顺序处理,第一个匹配到的ServerName或SrverAlias将被使用,它们没有和带通配符的域名没有优先级之分,同样ServerName和ServerAlias之间也没有优先级。所有域名的列表会和ServerAlias同等对待。

最后,你可以其他指令自由设置不同的虚拟主机,大多数指令都可以被使用,这些指令仅改变相关的虚拟主机。要确定一个指令是否被允许只用,检查这个指令的上下文即可。在之外的指令当没有被覆盖的时候会生效。

本站站配置参考

Apache多站点及反向代理 配置

 

Django入门1

参考资料:http://www.ziqiangxuetang.com/django/django-tutorial.html

所用python版本为2.7.9
django版本为1.8.16
平台:Windows8.1工业版
本文为纯手工搭建环境,也就是命令行+编辑器(Atom或VsCode)
安装好python环境后
配置环境变量
PATH=E:\Program Files\Python27\Scripts;E:\Program Files\Python27\;

注意:如果装过LoadRunner,这两项会和pip会有冲突
要把python的放到最前面才行
E:\Program Files (x86)\HP\LoadRunner\strawberry-perl\perl\bin\pip
E:\Program Files (x86)\HP\LoadRunner\strawberry-perl\perl\bin\pip.bat

在win下使用where pip即可看到pip命令执行的实际程序
机智如我23333

新建项目
django-admin.py startproject testproject
执行过后在当前文件夹下会多出manage.py和一个testproject文件夹
文件夹内部为__init__.pysettings.pyurls.pywsgi.py

新建 app
django-admin.py startproject testname
或者执行刚刚生成的manage.py
python manage.py startproject testname

执行后多出一个testname文件夹
内部为__init__.pyadmin.pymodels.pytests.pyviews.py
同时在settings.py中更新INSTALLED_APPS

同步数据库
python manage.py syncdb
注意:Django 1.7.1及以上的版本需要用以下命令
python manage.py makemigrations
python manage.py migrate

启动项目
默认监听8000
python manage.py runserver 8000

清空数据库
python manage.py flush

创建管理员
python manage.py createsuperuser
# 按照提示输入用户名和对应的密码就好了邮箱可以留空,用户名和密码必填
修改密码
python manage.py changepassword username

数据迁移
python manage.py dumpdata appname > appname.json

python manage.py loaddata appname.json

项目终端
python manage.py shell
安装bpython
pip install bpython

数据库终端
python manage.py dbshell

大致流程分析

服务器启动后
通过wsgi.py中指定的settings文件读取项目配置并加载所有模块
urls作为网址分发器匹配用户的HTTP请求分配到指定的模板上(即业务逻辑层)
然后再调用模板引擎绘制html返回

所以,在views.py中增加

更新urls.py

再使用

注意这时候没有单引号

或者直接写

这个index对应views中的index方法

模板渲染
为了方便更改url格式,可以动态渲染页面中的url
在views.py中这么写

在testname文件夹下新建templates文件夹
新建test.html,内容为

注意:{%url (只有这个空格是必需的)’name’%}
在urls.py中这么写

这样就能动态渲染url了

在代码中写法为

另外
获取HTTP参数写法为

模板引擎
在代码中传入变量

在html中显示变量
{{key}}
循环
{% for i in TutorialList %}
{{ i }}
{% endfor %}

block继承和文件引用

其中include可以套用其他模板
block可以被子模板继承覆盖
继承写法为
{% extends ‘base.html’ %}
{% block blockname %}写相同的blockname即可覆盖

其他类比JavaWeb即可,思路是一样的

本地虚拟机远程桌面穿透内网

1.注册花生壳账号。http://hsk.oray.com/
2.登录路由器配置界面。
3.绑定虚拟机网卡MAC和IP。
4.添加转发规则,把3389端口转发到外网。
5.配置花生壳账户,启用DDNS。
6.把自己的子域名加CNAME解析记录指向花生壳的动态域名。
7.更改虚拟机网卡设置,改成桥接模式。
8.更改系统设置,允许远程桌面访问。
9.开启Windows防火墙,配置规则。
10.关掉虚拟机和主机之间的所有共享文件夹。
这样在公网上即可使用自定义的域名连接家里的虚拟机了。

数据结构——线性结构

终于可以开始填这个坑了233333
————————————
像上一篇文章说的数据结构要解决的问题是数据如何在内存中存储,以什么结构存储。
用张仰森老师的话来说,就是“数据以及数据之间的关系。”
今天主要要聊的就是线性结构。

这里说的线性结构,是指从逻辑结构上来划分的。
说到这,就不得不提下物理结构。所谓逻辑结构,就是在逻辑、理论上定义的结构,而物理结构是指在实际的内存中数据的存储结构。

比如,有这么一种结构,每个元素只有唯一的前驱、唯一的后继、第一个元素没有前驱、最后一个元素没有后继。满足这样要求的结构就是线性结构。
而上面所说的结构仅仅是逻辑上的结构,而不是物理上的结构。之前已经学过的数组、链表,都可以表示这种结构。但是数组在物理结构上来说每个元素就是相邻摆放的,而链表的节点在实际内存中的分布却是分散的,仅仅是由于指针的存在好像使得前后有了关系。

C语言已经内置支持了最简单的线性结构,就是数组。
声明一个数组之后,就能得到N个相邻的物理空间。这N个空间中的变量就满足之前说的规律。
而概念里说的元素,可以是一个int,也可以是一个结构体。在本系列文章或者代码、我通常会用一个整数来代表一个元素。
而实际的应用中,一个元素可能是一个结构体、指针(最常见的是结构体的指针)。

说完了数据和数据之间的个关系,那么这个数据结构就已经快说完了,还差对应的一系列操作。
这里仅列出简单的几个操作,也就是增删改查,实际实现时候包括但不限于以下几种,候根据需要来写。
向线性表插入一个元素
从线性表删除一个元素
从线性表中查找关键字为i的元素
修改线性表中某个元素

套路:确定操作之后如何开始写代码
0.定义自己的数据结构(这里以C为例,所以写的是结构体。不排除以后用Java类的可能性=-=)
然后对每个操作按下面四个步骤
1.确定函数名、参数类型、参数数量
2.预想函数执行前内存的状态
3.确定函数执行后预期的内存状态
4.返回值类型极其含义

接下来将以两种实现方式进行说明,参考代码在github(求star求follow):
第一种:用数组实现的线性表
头文件:https://github.com/956237586/DataStructure-C/blob/master/DataStructure-C/1.1.linearlist.h
源文件:https://github.com/956237586/DataStructure-C/blob/master/DataStructure-C/1.1.linearlist.c

0.定义一个新的类型,叫List
//我默认大家都能看懂C语言,看不懂的请回上一篇看基础测试或者重新看下C的教程=-=
如上面代码中5-9行所示,我把一个数组和数组的长度定义为一个List。
createList,创建一个列表,
参数:长度
执行前状态:无
执行后状态:初始化一个指定长度的List
返回值定义 返回一个List
其他的同理。。。。

定义完了函数先写测试程序,如上面的主函数。
然后依次实现每个函数,createList的时候注意,在申请完内存后一定要初始化内存中每个地址的默认值,要么用NULL要么用0要么用参数,不要啥都不做,免得给自己挖坑
其实这也就是构造函数做的事情。。。
(代码中createList的时候其实应该返回指针更好一些,不然会再复制一份函数内部的List再return回去,然而这是很久之前的代码了,我懒得重写了=-=凑合着看吧233333)
代码中的问题(现在看当时写的代码简直是naive=-=):
风格不是很好。。。比如我省略了一些大括号,这是不好的习惯。。。
容错处理并没有做到最好,有些地方并不是一定会成功的操作我都没有做判断,比如realloc之后的返回值可能为NULL然而我没判断。。。

第二种实现方法,用链表实现线性表:
参考代码我就不贴上来了,去github看吧。。。
地址:
头文件:https://github.com/956237586/DataStructure-C/blob/master/DataStructure-C/1.2.linearlist.h
源文件:https://github.com/956237586/DataStructure-C/blob/master/DataStructure-C/1.2.linearlist.c

这是最基本的线性结构,之后所有复杂的结构都是这两种结构的组合、延伸,说白了再复杂的结构最终也能用这两种形式来组合表达。
其实计算机内存是线性的,所以某种意义上来说,所有的存储都是在把非线性的结构转换成线性结构来表达、然后存储、运算。

建议自己亲手仿写一个自己版本的线性表。。。。
写完后再继续往下看。
刚刚的线性表我们可以对对任意位置、任意元素进行操作。
如果我们加一点点限制,就出现了新的数据结构(其实并不是新的数据结构,只是操作操作受限的线性表而已)
也就是栈、和队列。
如果我们限制只能在一端增加和删除元素,那么就是栈。
如果我们限制只能在一端增加、在另一端删除,那么就是队列。
代码稍稍改一改就能搞定,参考代码地址如下:
https://github.com/956237586/DataStructure-C/tree/master/DataStructure-C
其中2.1是用数组实现的栈。
2.2是用链表实现的栈、也叫链栈。
(待补充详细说明,链栈的部分有个经典写法。。。)
3.1是用数组实现的队列,一般来说为了节省空间,数组会重复利用已有的空余内存,所以一般是循环队列。
(待补充详细说明,循环队列的关键在push和pop如何复用空余空间。。。。)
3.2是用链表实现的队列。(未完待续)
——————————–
今天先写到这=-=之后再继续写。。。。

CDH5性能调优

为了增加pipeline的运算速度,所以利用集群来进行日志的分析统计。测试数据规模:某机构edX的D版在真实场景下一年多使用记录。
开始日期 2016/11/27
开始时间 2:26:00
结束日期 2016/11/28
结束时间 3:34:00
总时间 23:10:54
日志开始日期 2015/6/7
日志结束日期 2016/11/24
在没有任何设置的情况下,运行完所有任务的时间如上表。。。。将近一天的时间=-=太慢了。
经过不断的尝试、分析如下:
慢的原因是每个任务都会有很多的map和reduce任务生成、而每个mapreduce任务都会占用一个worker节点的容器、每个服务器能申请到的容器数量和每个mapreduce占用的内存CPU资源,决定了同时运行的容器数量。
所以,想提高速度,就要尽可能多的让每个mapreduce节省内存、让容器的大小和mapreduce任务所需内存大小尽可能相等。
以我实验的集群规模为例进行参数设置方法。
1.资源计算
3台worker服务器,每个服务器CPU有8个core,16GB内存。
所以一共有24个CPU核心、48GB内存
虚拟cpu系数定为2,每个服务器预留两个核心给操作系统
所以每个服务器CPU vcore数量为8 * 2 – 2 = 14
内存留8G给操作系统,剩下12GB给Container
所以总memory为12 * 3 = 36GB
2.参数配置
需要配置YARN的参数如下(均为CDH5中YARN2的配置)
yarn.app.mapreduce.am.resource.mb 1024//这是Resource Manager需要的内存、我给了1G
yarn.app.mapreduce.am.resource.cpu-vcores 2//这是Resource Manager需要的CPU、我给了2
ApplicationMaster Java 最大堆栈 819.2 //这个数字是yarn.app.mapreduce.am.resource.mb * 0.8得到的
mapreduce.map.memory.mb 640 //这个是每个map任务需要的内存,实测在512时候会有个reduce任务失败,所以给了600多
mapreduce.map.cpu.vcores 2 //这个是每个map任务需要的CPU
mapreduce.reduce.memory.mb 640 //这个是每个reduce任务需要的内
mapreduce.reduce.cpu.vcores 2 //这个是每个reduce任务需要的CPU
mapreduce.map.java.opts.max.heap 512 //这是mapreduce.map.memory.mb * 0.8得到的
mapreduce.reduce.java.opts.max.heap 512 //这是mapreduce.reduce.memory.mb * 0.8得到的
客户端 Java 堆大小(字节) 512 //这里的客户端指的是yarn客户端的大小
JobHistory Server 的 Java 堆栈大小(字节) 1024
NodeManager 的 Java 堆栈大小(字节) 512
yarn.nodemanager.resource.memory-mb 12288 //这个是刚刚说的12G
yarn.nodemanager.resource.cpu-vcores 14 //这是刚刚说的14个vcore
ResourceManager 的 Java 堆栈大小(字节) 1024
yarn.scheduler.minimum-allocation-mb 1024 //一个容器最小内存占用
yarn.scheduler.increment-allocation-mb 128 //一个容器每次多申请多少内存
yarn.scheduler.maximum-allocation-mb 2048 //一个容器最大内存占用
yarn.scheduler.minimum-allocation-vcores 1 //一个容器最小CPU占用
yarn.scheduler.increment-allocation-vcores 1 //一个容器每次多申请多少CPU
yarn.scheduler.maximum-allocation-vcores 4 //一个容器最大内存占用

这样配置的实验结果时间为
开始日期 2016/12/2
开始时间 12:02:00
结束日期 2016/12/2
结束时间 15:34:00
总时间 3:06:50
日志开始日期 2015/6/7
日志结束日期 2016/11/24

比最开始节省了很多时间。。。因为同时在运行的container增加了,所以速度也变快了。
问题:发现map任务的数量每次处理的数据并不多,能不能合并一些数据,而不是每个map只处理一个文件?并且内存占用我觉得还可以在省一些,因为每个map的数据量不是很大。。。待解决=-=

Linux常用软件(更新ing)

是的=-=我又来挖坑了。。争取慢慢填233333

本文记录Ubuntu Linux下比较好用的软件
软件大部分可以通过apt-get install命令安装,如果你在校内,建议更换清华源(参考基本配置:http://blog.hylstudio.cn/archives/452),如果在校外可以用网易源。

之前还几篇可以参考。。之后会写的更详细的=-=嗯,相信我,一定会写的

 

Linux常用命令备忘录(更新ing)

 

Linux笔记1(Linux运维、大数据相关工具)

Linux笔记2(Linux运维、大数据相关工具)

XShell
远程终端,可以同步操作N个终端,在懒得写ansible的时候简直是神器

git
先继续挖坑23333之后再说
可以参考廖雪峰教程http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000

tree
可以显示指定目录结构的工具
常用命令:tree .

ansible
可以批量操作多个远程电脑,批量部署、自动化运维必备
批量执行命令:ansible all -a 'date'
批量分发文件:ansible -m copy -a 'src=/tmp/file1 dest=/tmp/file1'

fish
漂亮、方便的终端,比bash智能、颜值高
进入终端:fish

tmux
长时间脚本执行的神器(学长说screen也行,然而我没试过)
常用操作命令:
进入tmux:tmux
让tmux在后台运行:先按Ctrl+B,再按d
回到后台运行的tmux:tmux attach
tmux内新建一个窗口:先按Ctrl+B,再按c
切换窗口:先按Ctrl+B,再按对应的窗口编号
关闭当前窗口:先按Ctrl+B,再按&符号(Shift + 7)
滚动查看之前的输出:先按Ctrl+B,再按[(左方括号)
退出滚动模式:在滚动模式下按q

参考:http://www.kancloud.cn/kancloud/tmux/62459

make
make做构建工具的神器
参考:http://blog.csdn.net/ruglcc/article/details/7814546/
http://blog.csdn.net/liang13664759/article/details/1771246

 

 
supervisor
后台控制程序
参考
http://www.supervisord.org/