分布式系统部署、监控与进程管理的几重境界

陈硕 (giantchen_AT_gmail)

Blog.csdn.net/Solstice  t.sina.com.cn/giantchen

陈硕关于分布式系统的系列文章:http://blog.csdn.net/Solstice/category/802325.aspx

本作品采用“Creative Commons 署名-非商业性使用-禁止演绎 3.0 Unported 许可协议(cc by-nc-nd)”进行许可。 
http://creativecommons.org/licenses/by-nc-nd/3.0/

约定:本文只考虑 Linux 系统,文中涉及的“服务程序”是以 C++ 或 Java 编写,编译成二进制可执行文件(binary 或 jar),程序启动的时候一般会读取配置文件(或者以其他方式获得配置信息),同一个程序每个服务进程的配置文件可能略有不同。“服务器”这个词有多重含义,为避免混淆,本文以 host 指代服务器硬件,以“服务端程序/进程”指代服务器软件(或者具体说 Web Server 和 Sudoku Solver,这两个都是服务软件)。

 

在进入正题之前,先看一个虚构但典型的例子:Sudoku Solver。(Sudoku Solver 是个均质的无状态服务,分布式系统中进程的状态迁移不是本文的主题。)

假设你们公司的分布式系统中有一个专门求解数独(Sudoku)的服务程序,这个程序是你们团队开发并维护的。通常 Web Server 会使用这个 Sudoku Solver 提供的服务,用户通过 web 页面提交一个 Sudoku 谜题,web server 转而向 Sudoku Solver 寻求答案。每个 Web Server 会同时跟多个 Sudoku Solver 联系,以实现负载均衡。系统的消息结构大致如下,每个圆角矩形是一个进程,运行在各自的 host 上:

幻灯片18

上图中的 Web Server 请不要简单理解为 httpd + cgi,它其实泛指一切客户端,本身可能是个 stateful 的服务程序。

当然,系统不是一开始就是这样,它经历了多步演化。

four

一开始 (a),只有一个 Sudoku Solver,也只有一台 Web Server,是个简单的一对一 (1:1) 的使用关系;

随后 (b),随着业务量增加,一台 host 不堪重负,于是又部署了几台 Sudoku Solver,变成了一对多 (1:n) 的使用关系;

再后来 (c),一台 Web Server 撑不住了,于是部署了几台 Web Server,形成了我们一开始看到的多对多 (m:n) 的使用关系;

(d) 中的情况留到文末再讲。

 

在分布式系统中部署并运行 Sudoku Solver,需要考虑以下几个问题:

  • Sudoku Solver 如何部署到多台 host 上运行?是把可执行文件拷过去吗?程序用到的库怎么办?配置文件怎么办?
  • 如何启动服务程序 Sudoku Solver ?如果每个 Solver 的配置文件稍有不同(比如每个 Solver 有自己的 service name),那么配置文件是自动生成吗?
  • Sudoku Solver 的 listening port 如何配置?如何保证它不与其他服务程序重复?
  • 如果程序 crash,谁来重启?能否自动重启?开发/运维人员能否及时收到 alert?
  • 如果想主动重启 Sudoku Solver,要不要登录到那台 host 上去 kill ?还是能够远程控制?
  • 如果要升级 Sudoku Solver 程序,如何重新部署?如何(尽量)做到不中断服务?
  • Web Server 如何知道那些 Sudoku Solver 的地址?是不是静态写到 Web Server 的配置文件里?
  • 如果 Sudoku Solver 所在的 host 发生硬件故障,管理人员是否能立刻得知这一状况?Web Server 能否自动 fail over 到其他 alive 的 Solver 上?
  • 部署新的 Sudoku Solver 之后,Web Server 能否自动开始使用新的 Solver 而无需重启?(重启 Web Server 似乎不是大问题,这里我们进一步考虑 client 是个有状态的服务,应该尽量避免重启。)
  • 程序可否安全地退役?比方说公司不再做求解 Sudoku 的业务,那么关闭全部 Sudoku Solver 会不会对其他业务造成影响?

这些问题可以大致归结为几个方面:部署(含升级)可执行文件与配置文件、监控进程状态、管理服务进程,合起来可称为运维 operation。

根据公司的规模和技术水平不同,分布式系统的运维分为几重境界,以下是我对各重境界的简要描述。

 

境界1:全手工操作

这个大概是高校实验室的水平,分布式系统的规模不大,可能十来台机器上下。分布式系统的实现者为在校学生。

系统完全是手工搭起来,host 的 IP 地址静态配置。

部署:编译之后手工把可执行文件拷贝到各台机器上,或者放到公用的 NFS 目录下。配置文件也手工修改并拷贝到各台机器上(或者放到每个 Sudoku Solver 自己单独的 NFS 目录下)。

管理:手工启动进程,手工在命令行指定配置文件的路径。重启进程的时候需要登陆到 host 上并 kill 进程。

升级:如果需要升级 Sudoku Solver,则需要手工登陆多台 hosts,可以拷贝新的可执行文件覆盖原来的,并重启。

配置:Web Server 的配置文件里写上 Sudoku Solver 的 ip:port。如果部署了新的 Sudoku Solver,多半要重启 Web Server 才能发挥作用。

监控:无。系统不是真实的商业应用,仅仅用作学习研究,发现哪儿不对劲了就登陆到那台 host 上去看看,手工解决问题。

这个级别可算是“过家家”,系统时零时不灵,可以跑跑测试,发发 paper。

境界2:使用零散的自动化脚本和第三方组件

这大概是刚起步的公司的水平,系统已经投入商业应用。公司的开发重心放在实现核心业务,添加新功能,暂时还顾不上高效的运维,或许系统的运维任务由开发人员或网管人员兼任。公司已经有了基本的开发流程,代码采用中心化的版本管理工具(比如 SVN),有比较正式的 QA sign-off 流程。

公司内网有 DNS,可以把 hostname 解析为 IP 地址,host 的 IP 地址由 DHCP 配置。公司内部的 host 的软硬件配置比较统一,比如硬件都是 x86-64 平台,操作系统统一使用 Ubuntu 10.04 LTS,每天机器上安装的 package 和第三方 library 也是完全一样的(版本号也相同),这样任何一个程序在任何一台 host 上都能启动,不需要单独的配置。

假设各台 host 已经配置好了 ssh authentication key 或者 GSSAPI,不需要手工输入密码。如果要在 host1, host2, host3, host4 上运行 md5sum 命令,看一下各台机器上的 SudokuSolver 可执行文件的内容是否相同,可以在本机执行:

for h in host1 host2 host3 host4; do ssh $h md5sum /path/to/SudokuSolver/version/bin/sudoku-solver ; done

公司的技术人员有能力配置使用 cron、at、logrotate、rrdtool 等标准的 linux 工具来将部分运维任务自动化。

部署:可执行文件必须经过 QA 签署放行才能部署到生产环境(如有必要,QA 要签署可执行文件的 md5)。为了可靠性,可能不会把可执行文件放到 NFS 上(如果 NFS 故障,整个系统就瘫痪了)。有可能采用 rsync 把可执行文件拷贝到本机目录(考虑到可执行文件比较大,估计不适合直接放到版本管理库里),并且用 md5sum 检查拷贝之后的文件是否与源文件相同。部署可执行文件这一步骤应该可以用脚本自动执行(比方说 ssh $host rsync /path/to/source/on/nfs /path/to/local/copy/)。为了让 C++ 可执行文件拷到 host 上就能用,那么通常采用静态链接,以避免 .so 版本不同造成故障。

Sudoku Solver 的配置文件会放到版本管理工具里,每个 Solver instance 可能有自己的 branch,每次修改都必须入库。程序启动的时候用的配置文件必须从 SVN 里 check-out,不能手工修改(减少人为错误)。

管理:第一次启动进程的时候,会从 SVN check-out 配置文件;以后重启进程的时候可以从本地 working copy 读取配置文件(以避免 SVN 服务器故障对系统造成影响),只在改过配置文件之后才要求 svn update。服务进程使用 daemon 方式管理 (/sbin/init 或 upright 工具),crash 之后会立刻自动重启(利用 respawn 功能)。服务进程一般会随 host 启动而启动(放到 /etc/init.d 里),如果要重启 hostA 上的服务进程,可以通过 ssh 远程操作(比如在本机运行 ssh hostA /etc/init.d/sudoku-solver restart )。进程管理是分散的,每台 host 运行哪些 service 完全由本机是的 /etc/init.d 目录决定。把一个 service 从一台 host 迁移到另一台 host,需要登录到这两台 host 上去做一些手工配置。

升级:可执行文件也有一套版本管理(不一定通过 SVN),发布新版本的时候严禁覆盖已有的可执行文件。比方说,现在运行的是

/path/to/SudokuSolver/1.0.0/bin/sudoku-solver

那么新版本的 Sudoku Solver 会发布到

/path/to/SudokuSolver/1.1.0/bin/sudoku-solver

这么做的原因是,对于 C++ 服务程序,如果在程序运行的时候覆盖了原有的可执行文件,那么可能会在一段时间之后出现 bus error,程序因 SIGBUS 而 crash。另外,如果程序发生 core dump,那么验尸 (post mortem) 的时候必须用“产生 core dump 的可执行文件”配合 core 文件。如果覆盖了原来的可执行文件,post mortem 无法进行。

配置:Web Server 的配置文件里写上 Sudoku Solver 的 host:port (比 境界1 有所提高,这里依赖 DNS,通常 DNS 有一主一备,可靠性足够高)。不过 Web Server 的配置文件和 Sudoku Solver 的配置文件是独立的,如果新增了 Sudoku Solver 或者迁移了 host,除了修改 Sudoku Solver 的配置文件,还有修改所有用到它的 Web Server 的配置文件。这在系统规模比较小的时候尚且可行,系统规模一大,这种服务之间的依赖关系会变得隐晦。如果关闭了某个服务程序,可能一不小心造成其他组的某个服务失灵。如孟岩在《通过一个真实故事理解SOA监管》举的那个例子一样。

监控:公司会使用一些开源的监控工具(以下以 Monit 为例)来监控每台 host 的资源使用情况(内存、CPU、磁盘空间、网络带宽等等)。必要的话可以写一些插件,使之能监控我们自己写的服务程序 (Sudoku Solver)。但是这些监控工具通常只是观察者,它们与进程管理工具是独立的,只能看,不能动。这些监控工具有自己的配置文件,这些配置需要与 Sudoku Solver 的配置同步修改。Monit 可以管理进程,但是它判断服务进程是否能正常工作是通过定时轮询,不一定能立刻(几秒钟)发现问题。

 

在这个境界,分布式系统已经基本可用了,但也有一些隐患。

配置零散

每个服务程序有自己独立的配置,但是整个系统没有全局的部署配置文件(比方说哪个服务程序应该运行在哪些 hosts 上)。

服务程序的配置文件和用到此服务的客户端程序的配置是独立的,如果把 Sudoku Solver 迁移到另一台 host,那么不仅要修改 Sudoku Solver 的配置,还要修改用到 Sudoku Solver 的 Web Server 的配置,以及监控 Sudoku Solver 的 Monit 的配置。如果忘记修改其中一处,就会造成系统故障。

分布式系统中服务程序的依赖关系是个令人头疼的问题,“依赖”还好办(程序的作者知道我这个服务程序会依赖哪些其他服务),“被依赖”则比较棘手(如何才能知道停掉我这个程序会不会让公司其他系统崩溃?)。这也从一个侧面证明使用 TCP 协议作为唯一的 IPC 手段的必要性,如果采用 TCP 通讯,为了查出有哪些程序用到了我的 Sudoku Solver (假设 listening port 是 9981),那么我只要运行 netstat -tpn |grep 9981 就能找到现在的客户;或者让 Sudoku Solver 自己打印 accept(2) log,连续检查一周或这一个月就能知道有哪些程序用到了 Sudoku Solver。

进程管理分散

如果 hostA 发生硬件故障,如何能快速地用一台备用服务器硬件顶替它?能否先把它上面原来运行的 Sudoku Solver 迁移到空闲的 hostB 上,然后通知 Web Server 用 hostB 上的 Sudoku Solver?“通知 Web Server”这一步要不要重启 Web Server?

境界3:自制机群管理系统,集中化配置

这可能是比较成熟的大公司的水平。

境界 2 中的分散式进程管理已经不能满足业务灵活性方面的需求,公司开始整合现有的运维工具,开发一套自己的机群管理软件。我还没有找到一个开源的符合我的要求的机群管理软件,以下虚构一套名为 Zurg (名字取自科幻电影《第五元素》,拼写稍有不同;Zurg 也是《玩具总动员》中的一个反派角色。)的分布式系统管理软件。

Zurg 的架构很简单,典型的 master slave 结构,见陈硕在《多线程服务器的适用场合》中对“管理 Linux 服务器机群”的描述。

幻灯片32

在《分布式系统的工程化开发方法》中谈到了 Zurg 的功能需求:

幻灯片39

到了这一境界,日常的管理运维工作已经不再需要反复执行 ssh,常见任务都可以通过 Zurg 来完成。

部署:只需要向 master 发一条指令,master 会命令 slaves 从指定的地点 rsync 新的可执行文件到本地目录。

进程管理与监控:Zurg 的主要功能就是进程管理和监控,比起一般的开源工具,Zurg 更具备一些优势。由于 Sudoku Solver 是由 Zurg Slave fork() 而得,那么当 Sudoku Solver crash 的时候,Zueg Slave 会立刻收到 SIGCHLD,从而能立刻向管理员报告状态并重启。这比 munit 的轮询要迅速得多。(还可以在 fork() 之前做一些手脚,让 Zueg Slave 能更方便地获得 Sudoku Solver 的存活状态。)

为了安全起见,Zurg Slave 在启动可执行文件的时候可以验证其 md5,这样避免错误版本的服务程序运行在生产环境。

Zurg Master 可以提供一个 Web 页面以供查看本机群内各个服务程序是否正常运行。并且提供一个接口(可以是 HTTP)让我们能编写脚本来控制 Zurg master。

升级:如果要主动重启 Sudoku Solver,可以向 Zurg master 发出指令,不需要用 ssh & kill。Zurg 会保存每台 host 上服务进程的启动记录,以便事后分析。如果用境界 2 中的手动 /etc/init.d 管理方式,需要到每台机器上收集 log 才知道 Sudoku Solver 什么时候重启过。

另外也可以单独开发 GUI 程序,运行在运维人员的桌面上,重启多台 host 上的 Sudoku Solver 只需要点几下鼠标。

配置:零散的配置文件被集中的 Zurg 配置文件取代。

Zurg 配置文件会制定哪些 service 会在哪些 host 上运行,Zurg Master 读取配置文件,然后命令各个 Zurg Slave 启动相应的服务程序。比方说配置文件指定 Sudoku Solver 运行在 host1、host2、host3 上,那么 Zurg 会通知在 host1、host2、host3 上的 Zurg Slave 启动 Sudoku Solver。(当然,每台 host 上的 Zurg Slave 需要由 /etc/init.d 启动,其他的服务程序都由它负责启动。)

更重要的是,服务程序之间的依赖关系在 Zurg 配置文件里直接体现出来。比方说,在 Zurg 配置文件里指明 Web Server 依赖 Sudoku Solver,Web Server 的配置文件由 Zurg master 生成(可能会用到模板引擎,读入一个 Web Server 的配置模板),其中出现的 Sudoku Solver 的 host:port 由 Zurg master 自动填上,这样如果把 Sudoku Solver 从 hostA 迁移到 hostB,只需要改一处地方(Zurg 的配置),而 Sudoku Solver 和 Web Solver 的配置都由 Zurg master 自动生成。这样大大降低了犯错误的机会。

 

到了这一境界,分布式系统日常管理已经基本成熟,但在容错与负载均衡方面有较大的提升空间。

目前最大在障碍是 DNS,它限制了快速 Failover。比方说,如果 hostA 发生硬件故障,Zurg Master 固然可以在 hostB 上立刻启动 Sudoku Solver,但是如何通知 Web Server 到 hostB 上享用服务呢?修改 DNS entry 的话(把 hostA 的域名解析到 hostB 的 IP),可能要好几分钟才能完成更新,因为 DNS 没有推送机制。

如果思路受限制于 host:port,那么会采取一些看似高级,实则笨拙的高可用 (high availability) 解决方案。比方说在内核里做做手脚,设法让两台机器共享同一个 IP,然后通过专门的心跳连线来控制哪台 host 对外提供服务,哪台是备用机。如果那台“主机”发生故障,可以快速(几秒钟)切换到备用机,因为 hostname 和 IP 地址是相同的,客户端不用重新配置或重启,只要重新连接 TCP 就能完成 failover。如果在错误的道路上走得更远一点,可能还会设法把 TCP 连接一同迁移到备用机,这样客户端都不需要断开并重连。

 

Load balance 也受限于 DNS。

如果发现现有的 4 个 Sudoku Solver 不堪重负,又部署了 4 台 Sudoku Solver,如何通知各个 Web Server 把新的 Sudoku Solver 加到连接池里?

有一些 ad hoc 的手段,比方说每个 Web Server 有一个管理接口,可以透过这个接口向它动态地增减 Sudoku Solver 的地址。借助这个管理接口,我们也可以做一些计划中的联机迁移。比方说要主动把某个 Sudoku Solver 从 hostA 迁移到 hostB,我们可以先在 hostB 上启动 Sudoku Solver,然后透过 Web Server 的管理接口把 hostB:9981 添加到 Web Server 的连接池中,再把 hostA:9981 从连接池中删掉,最后停掉 hostA 上的 Sudoku Solver。这对计划中的 Sudoku Solver 升级是可行的,能做到避免中断 Web Server 服务。对于 failover,这种做法似乎稍显不够方便,因为要让 Zurg Master 理解 Web Server 的管理接口,会给系统带来循环依赖。(正常情况下,Zurg Master 不应该知道/访问它管理的服务程序的接口细节,这样 Sudoku Solver 升级的时候不用升级 Zurg Master。)

这种做法要求 Web Server 在开发的时候留下适当的维修探查通道,见陈硕《构建易于维护的分布式程序》中的推荐做法。

另外一种 ad hoc 的手段,每个 Sudoku Solver 在启动的时候自己主动往某个数据库表里 insert 或 update 本程序的 host:port。Web Server 的配置里写的不是 host:port,而是一条 SELECT 语句,用于找出它依赖的 Sudoku Solver 的 host:port,Web Server 还可以通过数据库触发器来及时获知 Sudoku Solver address list 的变化。这样增加或减少 Sudoku Server 的话,Web Server 几乎可以立刻应对,也不需要透过管理接口来手工增减 Sudoku Solver 地址。数据库在这里扮演了 naming service 的角色,它的可用性直接影响了整个系统的可用性。

境界 3 是黎明前的黑暗,只要统一引入 naming service,抛开 DNS,容错和负载均衡的问题迎刃而解。

境界4:机群管理与 naming service 结合

这是业内领先的公司的水平。

前面分析到,使用 Zurg 机群管理软件能大大简化分布式系统的日常运维,但是它也有很大的缺陷——不能实现快速 failover。如果系统规模大到一定程度,机器出故障的频率会显著增加,这时候自动化的快速 failover 是必备的,否则运维人员疲于奔命救火。

实现简单而快速的 failover 不需要特殊的编程技巧,也不需要对 kernel 动手脚,只要抛弃传统的 DNS 观念,摆脱 host:port 的束缚,采用为分布式系统特制的 naming service 代替 DNS 即可。

幻灯片40

naming service 的功能是把一个 service_name 解析成 list of ip:port。比方说,查询 "sudoku_solver",返回 host1:9981、host2:9981、host3:9981。

naming service 与 DNS 最大的不同在于它能把新的地址信息推送给客户端。比方说,Web Server 订阅了 "sudoku_solver",每当 sudoku_solver 发生变化,Web Server 就会立刻收到更新。Web Server 不需要轮询,而是等候通知。

naming service 谁负责更新?

在境界 2 中,Sudoku Solver 会自己主动去 naming server 注册。到了境界 3,由于 Sudoku Solver 是有 Zurg 负责启动,那么 Zurg 知道 Sudoku Solver 运行在哪些 hosts 上,它会主动更新 naming service,不需要 Sudoku Solver 自己动手。

naming service 的可用性(availability)和一致性如何保证?

毫无疑问,一旦采用这种方案,naming service 是系统正常运转的关键,它的可用性决定了系统的可用性。naming service 绝对不能只 run 在一台服务器上,为了可靠性,应该用一组(通常是 5 台)服务器同时提供服务,当然,这需要解决一致性问题。目前实现高可用 naming service 的公认办法是 Paxos 算法,也有了一些开源的实现(ZooKeeper、KeySpace、Doozer)。

对程序设计的影响?

如果公司的网络库在设计的时候就考虑了 naming service,那么对程序设计来说是透明的。配置文件里写的不再是 host:port,而是 service_name,交给网络库去解析成 ip:port 地址列表。

为什么 muduo 网络库没有封装 DNS 解析?

一方面因为 gethostbyname() 和 getaddrinfo() 做 DNS 解析是阻塞的,我一时没有时间写一个非阻塞的 DNS 库;另一方面,因为在大规模分布式系统中 DNS 的作用不大,我宁愿花时间实现一个 naming service,并且为它编写 name resolve library。

 

在境界 3 中,每个项目组有自己的 hosts,只运行本项目中的服务程序,每个服务程序的 TCP 端口可以静态分配(比如 Sudoku Solver 固定使用 9981 端口),不担心端口冲突。如果公司规模继续扩大,迟早会把 16-bit 的 port 命名空间用完,这时候给新项目分配端口号将成为问题。

到了境界 4,这一限制将被打破,服务程序可以 run 在公司内任何一台 host 上,也不用担心端口冲突,因为 Zurg 会选择当前 host 的空闲端口来启动 Sudoku Solver,并且把选中的端口保存在 naming service 中。这样一来,TCP port 也实现了动态配置,Web Server 完全能自动适应 run 在不同 port 的 Sudoku Solver。

 

(待续,下一篇我打算谈谈分布式系统中心跳协议的设计。)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/351707.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

.net core mvc初级教程(六)

一、创建movie的视图 二、对cinema、movie视图添加‘添加信息’的操作 一、创建movie的视图 在views文件夹下添加Movie文件夹,在这个文件夹下添加Index.cshtml视图,为什么添加Index.cshtml这个名字的视图,可以看看我们写的MovieController控制…

apache camel_发掘Apache Camel的力量

apache camel最近几年,ESB软件越来越受欢迎。 如果大多数人通常知道什么是ESB,那么他们很少会清楚地了解这种体系结构的不同组件的确切作用。 例如,Apache ServiceMix由三个主要组件组成:Apache Karaf(OSGI容器&#…

角反射器的功能及应用

雷达反射器又名角反射器,它是通过金属板材根椐不同用途做成的不同规格的雷达波反射器。当雷达电磁波扫描到角反射后,电磁波会在金属角上产生折射放大,产生很强的回波信号,在雷达的屏幕上出现很强的回波目标。由于角反射器有极强的…

mysql卸载权限不够_Linu下启动MySQL结果显示:env: /etc/init.d/mysql:权限不够怎么解决?...

展开全部Linu下启动MySQL结果显示:env: /etc/init.d/mysql: 是脚本执行的问题解决办法:依次e69da5e887aa3231313335323631343130323136353331333365633936执行下面的命令(执行失败的话,检查路径是否正确):cp /etc/init.d/mysql /e…

GDAL/ORG之Python获取与安装

GDAL(Geospatial Data Abstraction Library)是一个的开源栅格空间数据读取/转换库。其中还有一系列命令行工具来进行数据转换和处理。而ORG项目是GDAL的一个分支,功能与GDAL类似,但其提供对矢量数据的支持。 也就是说,可以用ORG的库来读取、处…

Firewall配置

一、安装firewall #yum install -y firewalld firewall-config 二、启动并设置开机自启动# systemctl start firewalld# systemctl enable firewalld# systemctl stop firewalld# systemctl disable firewalld 三、firewall配置# firewall-config 防火墙图形配置界面# firewall…

网页cookie是什么?

Cookie 是用户访问的网站创建的文件,存储在用户电脑的硬盘中,用于保存浏览信息,例如您的网站偏好设置或个人资料信息。网站依靠Cookie辨认用户行踪,了解用户感兴趣内容,收集与用户有关的信息。用户访问查询网页上操作信…

使用基于微服务的流架构更好地进行大规模的复杂事件处理(第1部分)

基于微服务的流架构与开源规则引擎相结合,使实时业务规则变得容易 这篇文章旨在详细说明我将OSS业务规则引擎与Kafka风格的现代流消息传递系统集成在一起的项目。 该项目的目标(即众所周知的复杂事件处理(CEP))旨在实…

chown r mysql ._chown -R 用户名:组名 ./ 及 chown用法介绍

当我们在不通过yum(CentOS)、apt-get(Ubuntu)来安装MySQL的时候,通常执行以下命令来改变目录的拥有者:[rootlocalhost ~]# chown -R mysql:mysql ./这两个mysql谁是用户名谁是用户组呢?见chown详解。chown将指定文件的拥有者改为指定的用户或…

c语言abs和fabs的区别是什么?

abs是整数取绝对值,定义在stdlib.h头文件中。而fabs是指浮点数取绝对值,定义在math.h头文件中。 函数原型 int abs(int x) double fabs(double x)

Linux下编译GDAL

一、准备工作 从官网下载GDAL、PROJ.4和GEOS,将其存放在/home/liml/Work/3rdPart目录并解压,如下图所示。下载地址请自行Google。注:使用的系统是CentOS6.4 X64版本,其他的Linux系统都是一样的。 接下来检查系统中是否安装了开发…

PS提示错误1解决办法

重装电脑系统后,PS打不开了,提示错误1.在网上搜索,很多网友说要卸载重装。控制面板看不到ps,于是下载了Adobe卸载工具(点击链接下载),但是这个程序识别不了安装的ps.最后通过以下办法解决。 1.…

如何为你的博客园添加到百度统计

1.打开百度统计的地址 https://tongji.baidu.com/web/welcome/login?castkLTE%3D 2.注册,打开网址后,右面有注册按钮,点击注册 选择站长版,点击去 填写自己的注册信息 3.填完之后,登录进去,在管理标签下有…

mysql 左连接 重复_mysql左连接重复行

我正在设计一个类似于4个表格的字典数据库wordswordid | lemmasenseswordid | synsetidsynsetssynsetid | definitionsamplessynsetid | sample所以我使用下面的查询来获取所有意义定义和样本if(isset($searchterm)){echo "".$searchterm."";// QUERY TO F…

osgi java_使普通的旧Java OSGi兼容

osgi java尽管OSGi在Java世界中越来越流行,但仍有许多Java应用程序和库尚未设计成可在OSGi中使用。 有时您可能需要在OSGi环境中运行这样的代码,或者是因为您想利用OSGi本身提供的好处,或者因为您只需要此特定环境提供的某些功能。 通常&…

Matlab如何求离散点的导数

1.通过差分估算 已知同维度的x和y序列&#xff0c;则可使用diff(y)./diff(x)来估算。设x为n维向量&#xff0c;Dxdiff(x) 计算向量x的向前差分&#xff0c;DX(i)X(i1)-X(i)&#xff0c;0<i<n。 例一 y[7.86 7.84 7.82 7.77 7.72 7.68 7.61 7.51 7.42 7.33 7.21 7.07 6…

ERROR 6: GEOS support not enabled.

要学习GEOS库&#xff0c;肯定绕不开地理方面的东西。如果需要判断的两个多边形或几何图形&#xff0c;不是自己创建的&#xff0c;而是来自shapefile文件&#xff0c;那就得将GEOS库和GDAL/OGR库结合使用了。实际上只需要OGR就行了&#xff0c;但OGR和GDAL是放在一起的。OGR库…

java面向对象(this关键字)

一.this的作用 1.this 相当于是指向当前对象本身 2.成员变量和局部变量同名问题 class Person {private int age;private String name;// 给姓名和年龄初始化的构造方法Person(String name, int age) {// 当需要访问成员变量是&#xff0c;只需要在成员变量前面加上this.即可th…

c语言float二进制输出代码_下面C语言中这十四大谜题,不看答案你能做出来吗?...

C语言领取福利资料前往文末领取本篇文章《C语言的谜题》展示了14个C语言的迷题以及答案&#xff0c;代码应该是足够清楚的&#xff0c;而且我也相信有相当的一些例子可能是我们日常工作可能会见得到的。通过这些迷题&#xff0c;希望你能更了解C语言。如果你不看答案&#xff0…

平台策略:从Portlet到OpenSocial小工具再到渐进式Web应用程序:最新技术

介绍 由于世界仍在Java的掌控之中&#xff0c;因此我们经常定义所谓的基于组件的平台 。 我在2000年的OpenUSS&#xff08;开放大学支持系统&#xff09;方面拥有这一经验。 当时我有一个想法&#xff0c;就是开发一个可以使用组件体系结构和J2EE技术​​&#xff08; OpenUSS …