0%

cmake 是一个跨平台的编译安装工具,可以用简单的语句来描述所有平台的编译安装过程。

本文介绍 cmake 的基础语法。

第一个例子

使用任意的文本编辑器,输入:

1
message("Hello world!") 

然后保存为 hello.txt 文本文件,执行:

1
cmake -P hello.txt

输出:

Hello world!

所有变量都是字符串

在 cmake 中,所有变量都是字符串。可以使用 ${} 来引用一个变量。例如,修改 hello.txt

1
message("Hello ${NAME}!") 

然后在执行 cmake 命令时对变量 NAME 进行定义:

阅读全文 »

Dubbo 是一款微服务框架,提供高性能 RPC 通信,服务发现,流量管理等服务治理能力,提供构建大规模微服务集群所需的整套解决方案。

本文讲述如何利用 Dubbo 快速构建一个完整的服务端 - 客户端程序,包括基于 XML,注解和 API 的方式实现一个 Dubbo 的 demo。

配置开发环境

本文使用 IntelliJ IDEA 作为 Dubbo 应用程序开发的 IDE。

安装 ZooKeeper

Dubbo 推荐使用 ZooKeeper (下文简称为 zk)作用注册中心,为简单起见,本文搭建一个单机版的 zk 以供 Dubbo 应用程序使用。有关 zk 集群的搭建步骤,可参考 ZooKeeper的安装与部署

在 zk 官网下载最新版本的 zk 二进制安装包,解压,将 conf 目录下 zoo_sample.cfg 文件复制为 zoo.cfg,然后在 zk 主目录执行命令,将 zk 启动起来。此时 zk 会监听默认的 2181 端口。

1
bin/zkServer.sh start

下载源代码

本文的 Dubbo 入门应用程序很简单,服务端接收到客户端请求,然后直接将消息返回给客户端。应用程序可以通过 XML、注解和 API 三种方式编写。

本文示例应用程序在 https://github.com/zonghaishang/dubbo-samples 可以下载。

下载后,使用 IDEA 打开,导入 pom.xml 所需的依赖后显示如下:

阅读全文 »

文章 《Mac docker desktop 搭建 kubernetes 环境》 介绍了如何在 mac 上利用 docker desktop 搭建 k8s 运行环境,本文在此基础上,说明如何利用 k8s 部署 nginx 。

创建 pod

pod 是 k8s 最小的编排单位,通常来说不需要直接创建 pod。这里是为了演示 pod 的使用创建了一个 pod。

pod 的配置文件 nginx-pod.yml

1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80

其中配置项:

  • image:用于指定 nginx 容器使用的镜像
  • containerPort:容器内部监听端口,有关 k8s 各种 port 的使用,可以参考 链接

使用命令 kubectl apply 创建 pod:

1
kubectl apply -f nginx-pod.yml

为了检查创建的 pod 的状态,执行命令:

1
kubectl get pods nginx -o wide

可以看到 nginx pod 已处于 Running 状态,表示刚创建的 pod 已成功运行起来:

阅读全文 »

学习 kubernetes (下文简称为 k8s)的前提是需要一个 k8s 运行环境。k8s 官网上推荐使用 minikube 开始 k8s 的学习之旅。由于自己的 mac 上已安装了 docker desktop(下文简称 desktop),且 desktop 集成了 kubernetes 功能,可以满足最快完成 k8s 学习环境搭建的需求。

安装/更新 docker desktop

如果没有安装 docker desktop,可以直接下载最新版本进行安装。如果已安装 docker,为了更新至最新版本,也可以使用下载最新版本安装的方式进行版本更新。下载地址:https://www.docker.com/products/docker-desktop
成功安装 desktop,可以在 About 菜单中看到其版本号:

为了更顺畅地运行 k8s,调整 desktop 的资源配置:

阅读全文 »

最近搭建 kafka 集群环境以便于收集应用程序日志并进行个性化的处理,因此学习了 kafka 生产者和消费者 python 程序的实现。这篇文章当是 kafka 的学习笔记。

一、搭建 kafka 集群

为方便测试,我们在 MacOS 单机上搭建具有三个 kafka 节点的集群。如果在生产上部署 kafka ,请在不同的物理机上部署 kafka 集群。

1. 下载 kafka 镜像

我们使用 wurstmeister/kafka 镜像来部署 kafka,由于 kafka 依赖于 zookeeper ,因此,我们需要下载 zookeeper 和 kafka 两个镜像。

1
2
docker pull wurstmeister/kafka
docker pull wurstmeister/zookeeper

2. 编写 docker-compopse.yml

我们搭建的 kafka 集群包括一个 zooker 节点和三个 kakfa 节点。

使用 ifconfig 命令获取本机的 ip 为 192.168.0.104,完整的 docker-compose.yml 文件如下。有关 docker-compose 的使用,可以参考 《Docker Compose 入门教程》

阅读全文 »

虽然 prometheus 已有大量可直接使用的 exporter 可供使用,以满足收集不同的监控指标的需要。例如,node exporter 可以收集机器 cpu,内存等指标,cadvisor 可以收集容器指标。然而,如果需要收集一些定制化的指标,还是需要我们编写自定义的指标。

本文讲述如何使用 prometheus python 客户端库和 flask 编写 prometheus 自定义指标。

安装依赖库

我们的程序依赖于 flaskprometheus client 两个库,其 requirements.txt 内容如下:

1
2
flask==1.1.2
prometheus-client==0.8.0

运行 flask

我们先使用 flask web 框架将 /metrics 接口运行起来,再往里面添加指标的实现逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/env python
# -*- coding:utf-8 -*-

from flask import Flask

app = Flask(__name__)


@app.route('/metrics')
def hello():
return 'metrics'


if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)

打开浏览器,输入 http://127.0.0.1:5000/metrics,按下回车后浏览器显示 metrics 字符。

阅读全文 »

最近在公司搭建 prometheus 监控平台。文章 《Prometheus 使用阿里云邮件推送发送告警邮件》 已说明如何实现 prometheus 发送邮件告警的功能,这篇文章说明如何实现发送企业微信告警的功能。

申请企业微信账号

为实现发送企业微信告警消息,需要一个企业微信账号,在页面 企业微信 可以免费申请一个测试账号。

进入应用管理 - 创建应用,创建一个用于接收告警消息的账号。创建成功后,可以看到该应用的 AgentId 和 Secret 串,如图所示:

配置 alertmanager

Alertmanager 用于接收 prometheus 的告警消息并将告警消息发送到指定的用户。为实现使用企业微信发送告警消息,需要在 alertmanager 增加企业微信的有关配置。

alertmanager.yml 增加企业微信的配置:

阅读全文 »

C++ 中,对于一个对象或一个表达式,如果可以对其使用调用运算符(()),则称它是可调用的。即,如果 e 是可调用的,则可以这样使用:

1
e(args)

其中,args 是一个逗号分隔的一个或多个参数的列表。

C++ 中可调用对象除了我们熟悉的函数或函数指针外,还包括函数对象以及 lambda 表达式。

本文重点讲述 lambda 表达式。

lambda 表达式表示一个可调用的代码单元,我们可以将其理解为一个未命名的内联函数。一个 lambda 表达式具有如下形式:

1
[capture list](parameter list) -> return type {function body}
  • capture list:捕获列表,lambda 表达式所在函数中定义的局部变量列表
  • parameter list:参数列表
  • return type:返回类型
  • function body:函数体

lambda 表达式可以忽略参数列表和返回类型,但必须包含捕获列表和函数体:

阅读全文 »

函数对象本质上是一个类对象,它重载了函数调用运算符 operator()。调用运算符的函数体实现函数的功能。

例如,我们定义类 LessThan

1
2
3
4
5
6
class LessThan {
public:
bool operator() (const string &s1, const string &s2) {
return s1.size() < s2.size();
}
};

LessThan 包含调用运算符的重载,调用运算符的函数体实现了函数的功能:小于操作。
调用运算符的定义第一次看起来有点令人迷惑,因为出现了两个小括号。第一个小括号:

1
operator()

告诉编译器我们在重载调用运算符。第二个小括号:

1
(const string &s1, const string &s2)

指定传递给调用运算符重载函数的形式参数。

函数对象的定义与普通类对象一样:

阅读全文 »