0%

Semaphore,是一种带计数的线程同步机制,当调用release时,增加计数,当acquire时,减少计数,当计数为0时,自动阻塞,等待release被调用。

在Python中存在两种Semaphore,一种就是纯粹的Semaphore,另一种是BoundedSemaphore。

  • Semaphore: 在调用release()函数时,不会检查,增加的计数是否超过上限(没有上限,会一直上升)
  • BoundedSemaphore: 在调用release()函数时,会检查,增加的计数是否超过上限,这样就保证了使用的计数

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
maxconnections = 5
# ...
pool_sema = BoundedSemaphore(value=maxconnections)

# ...

with pool_sema:
# 这里需要注意,使用with语句块,会自动帮你执行acquire()和release()
conn = connectdb()
try:
# ... use connection ...
finally:
conn.close()

zabbix是一个基于WEB界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案。

zabbix能监视各种网络参数,保证服务器系统的安全运营;并提供灵活的通知机制以让系统管理员快速定位以及解决存在的各种问题。

zabbix由2部分构成,zabbix server与可选组件zabbix agent。

zabbix server可以通过SNMP,zabbix agent,ping,端口监视等方法提供对远程服务器、网络状态的监视,数据收集等功能, 它可以运行在Linux,Solaris,HP-UX,AIX,Free BSD,Open BSD,OS X等平台上。

Read more »

JavaScript中模仿接口的三种方法:注释法、属性检查法和鸭式辩型法。没有哪种技术是完整的,但三者结合使用基本上可以令人满意。

用注释描述接口

用注释模仿接口是最简单的方法,但效果却是最差的。 这种方法模仿其他面向对象语言中的做法,使用了interfaceimplements关键字, 但把它们放在注释中,以免引起语法错误。下面的示例演示了如何把这些关键字添加到代码中以描述所要求的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/*
interface Composite {
function add(child);
function remove(child);
function getChild(index);
}

interface FormItem {
function save();
}
*/

// implements Composite, FormItem
var CompositeForm = function(id, method, action) {
...
};

// Implement the Composite interface.

CompositeForm.prototype.add = function(child) {
...
};
CompositeForm.prototype.remove = function(child) {
...
};
CompositeForm.prototype.getChild = function(index) {
...
};

// Implement the FormItem interface.

CompositeForm.prototype.save = function() {
...
};

这种模仿并不是很好。它没有为确保CompositeForm真正实现了正确的方法集而进行检查,也不会抛出错误以告知程序员程序中有错误。 说到底它只要还是属于程序文档范畴。在这种做法中,对接口约定的遵守完全依靠自觉。

尽管如此。这种方法也有其优点。它易于实现,不需要额外的类或函数。 它可以提高代码的课重用性,因为现在哪些类实现的接口都有说明,程序员可以把它们与实现了同样接口的类互换使用。 这种方法并不影响文件尺寸或执行速度,因为它所使用的注释可以在对代码进行部署时不费吹灰之力地予以剔除。 但是,由于不会提供错误信息,它对测试和调试没有什么帮助。

Read more »

Java虽然入门要容易, 然而要精通它, 要成为专家却很难. 主要原因是Java所涉及的技术面比较宽, 人的精力总是有限的. 有些Java方面的技术是必须要要掌握的, 钻研得越深入越好, 比如多线程技术.

基础阶段

基础阶段, 可能需要经历1-2年吧. 这个时段, 应该多写一些基础的小程序(自己动手写的越多越好). 计算机是一门实践性很强的学科, 自己动手的东西, 记忆非常深刻, 效果要胜过读好多书. 当然, 学Java基础的时候, 书籍的选择也非常重要, 好的书籍事半功倍, 能让你打个非常好的基础. 而差的书籍, 很容易将你带入歧途, 多走很多弯路. 书籍不在多, 而在乎读得精(有些书, 你读十遍都不为过). 我记得我学Java的第一本书是的中文版, 网上有很多人都建议不要把这本书作为第一本的入门教程来看, 太难. 我却想在此极力推荐它, 这本书确实是本经典之作. 而且书中确实讲的也是Java中的一些基础技术, 没有什么太难的东西, 只不过比较厚, 学习周期比较长, 所以很多人中途会选择放弃. 其实, 这本书是一本难得的入门教程, 对Java一些基础的东西, 讲得很全, 而且也很清晰, 更重要的是, 这本书能让你养成很多好的编程习惯, 例子也很多. 建议你把大部分的例子自己去实现一遍. 我的亲身经历, 我记得当时认真的看了2遍, 花了大概7个月的时间, 不过真的有很好的效果. 另外一个教程, 就是<Java核心技术>卷一, 卷二的话可以不必要买. 卷一看完, 自己再钻研一下, 就已经能达到卷二的高度了:). 到那时, 你就会觉得看卷二没啥意思, 感觉浪费钱了. 还有一个, 就是张孝祥的Java视频, 看视频有个好处, 就是比看书的记忆要深刻, 还有很多你可以跟着视频的演示同步操作. 张孝祥的Java视频对初学者来说, 确实很有作用. 总结起来: 看这些资料的时候, 一定要多写例子, 写的越多越好!

Read more »

1
2
3
Syntax:  underscores_in_headers on | off;
Default: underscores_in_headers off;
Context: http, server

启用或禁用带下划线的请求头。当禁用下划线时,名称中包含下划线的请求头将被置为无效。

开发

  1. 从小事做起,然后再扩展

    无论是创建一个新的系统,还是添加功能到现有的系统中,我总是从一个简单到几乎没有任何所需功能的版本启动,然后再一步一步地解决问题,直到满意为止。 我从来没有妄想过能够一步登天。相反,我一边开发一边学习,同时新掌握的信息还可以用于解决方案中。

    我很喜欢John Gall的这句话:“复杂系统总是源于简单系统的演化。”

  2. 一次只改变一件事

    当我们在开发时,碰到测试失败和功能无效的情况,如果你一次只研究一个问题,那将会更容易找到问题的关键。 换言之,就是使用短迭代。必须确保这个问题解决之后,再转移到另一个问题上。这适用于向下提交。如果在你添加新功能之前需要先重构代码,那么先提交重构,然后再添加新的功能。

  3. 尽早地添加日志记录和错误处理

    在开发新系统时,我做的第一件事就是添加日志和错误处理,因为这两者从一开始就非常有用。如果系统不能照常工作, 那么你就需要知道程序中发生了什么——这是日志的作用。错误处理也是如此——错误和异常越早处理越好。

  4. 每一行新代码必须至少执行一次

    在你真正完成一个功能之前,你必须对它进行测试。不然,你怎么知道它是不是按照你的想法在执行呢? 通常情况下,最好的方法是通过自动测试,但并非总是如此。不过,不管怎么说,每一行新代码必须至少执行一次。

  5. 在整体测试之前先进行模块测试

    先进行部分模块测试可以节省时间。通常说来,我们在整合不同的模块时也会出现问题,例如模块之间的接口不匹配。 但是如果我们能够信任各个组件的话,那么跟踪集成问题就会变得简单得多。

  6. 所有事情所花费的时间总是比你预期的要长

    特别是在编程中,即使一切进展顺利,我们也很难对功能所需的时间做出正确的预算。并且,开发软件时碰到各种意想不到的问题是非常常见的。

    侯世达定律其实道出了真谛:做事所花费的时间总是比你预期的要长,即使你在预期中已经考虑了侯世达定律。

  7. 先了解现有的代码

    大多数的编码都需要以某种方式改变现有的代码。即使是新功能,也需要适应现有的程序。 所以,在你加进去新的内容前,首先需要了解当前的解决方案。否则,你一不小心就很有可能会打破现有的功能。 这意味着,阅读代码和编写代码都是必要的技能。这也是为什么看似微小的变化仍可能需要很长时间才能解决的原因之一——你首先必须了解上下文。

  8. 阅读和运行

    幸运的是,对于理解代码,我们有两种互补的方法。你可以阅读代码,也可以运行代码。运行代码的确是个非常棒的好方法。所以,请确保充分利用这两种方法。

Read more »

镜像构建上下文

我们在使用 docker build 命令去构建镜像时,经常会看到命令最后会有一个.号。

例如:

1
docker build -t xxx .

这里的.号是在指定镜像构建过程中的上下文环境的目录。

Docker在运行时分为Docker引擎(服务端守护进程)以及客户端工具,我们日常使用各种docker命令,其实就是在使用客户端工具与Docker引擎进行交互。 那么当我们使用docker build命令来构建镜像时,这个构建过程其实是在Docker引擎中完成的,而不是在本机环境。

那么如果在Dockerfile中使用了一些COPY等指令来操作文件,如何让Docker引擎获取到这些文件呢?

这里就有了一个镜像构建上下文的概念,当构建的时候,由用户指定构建镜像的上下文路径, 而docker build会将这个路径下所有的文件都打包上传给Docker引擎,引擎内将这些内容展开后,就能获取到所有指定上下文中的文件了。

例如说dockerfile中的COPY ./package.json /project,其实拷贝的并不是本机目录下的package.json文件, 而是docker引擎中展开的构建上下文中的文件,所以如果拷贝的文件超出了构建上下文的范围,Docker引擎是找不到那些文件的。

.dockerignore文件的作用

同其他ignore文件类似,在向Docker引擎发送构建上下文时,Docker会忽略.dockerignore文件中指定的文件和目录。

Moodle简介

Moodle是一个开源课程管理系统(CMS),也被称为学习管理系统(LMS)或虚拟学习环境(VLE)。

Moodle平台界面简单、精巧。使用者可以根据需要随时调整界面,增减内容。 课程列表显示了服务器上每门课程的描述,包括是否允许访客使用,访问者可以对课程进行分类和搜索,按自己的需要学习课程。

Moodle平台还具有兼容和易用性。可以几乎在任何支持PHP的平台上安装,安装过程简单。只需要一个数据库(并且可以共享)。 它具有全面的数据库抽象层,几乎支持所有的主流数据库(除了初始表定义)。 利用Moodle,现今主要的媒体文件都可以进行传送,这使可以利用的资源极大丰富。 在对媒体资源进行编辑时,利用的是用所见即所得的编辑器,这使得使用者无需经过专业培训,就能掌握Moodle的基本操作与编辑。 Moodle注重全面的安全性,所有的表单都被检查,数据都被校验,cookie是被加密的。 用户注册时,通过电子邮件进行首次登陆,且同一个邮件地址不能在同一门课程中进行重复注册,所有这些,都使得Moodle的安全性得到了加强。 目前,Moodle项目仍然在不断的开发与完善中。

Moodle是B/S模式的应用程序,但是一般而言,只适合于中小型学校。

Read more »

1
2
3
4
RUN apk update && apk add ca-certificates \
&& apk add tzdata \
&& ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo "Asia/Shanghai" > /etc/timezone

配置默认网络并设置子网:

1
2
3
4
5
6
7
networks:
default:
driver: bridge
ipam:
driver: default
config:
- subnet: 172.17.2.0/24

使用已存在的网络:

1
2
3
4
networks:
default:
external:
name: other-existing-network