关于swarm网络不能访问的问题

回复

ighack 发起了问题 • 1 人关注 • 0 个回复 • 8 次浏览 • 2019-06-19 11:57 • 来自相关话题

docker挂载mysql5.7日志无效

styshoo 回复了问题 • 2 人关注 • 1 个回复 • 99 次浏览 • 2019-06-19 08:22 • 来自相关话题

Shell-operator:用于简化Kubernetes operator的创建

dummy 发表了文章 • 0 个评论 • 137 次浏览 • 2019-06-18 17:24 • 来自相关话题

我们很高兴在此介绍我们新的开源方案,它能将Kubernetes中Operator的开发提升到一个全新的更简单的水平。它可以让你在15分钟内将你的小脚本变成完全成熟的Operator而吸引你。欢迎 ...查看全部

我们很高兴在此介绍我们新的开源方案,它能将Kubernetes中Operator的开发提升到一个全新的更简单的水平。它可以让你在15分钟内将你的小脚本变成完全成熟的Operator而吸引你。欢迎shell-operator




目标


shell-operator的思路很简单,它订阅来自Kubernetes对象的事件,并在事件发生后执行外部程序,为其提供有关事件的信息:




在我们运行Kubernetes集群期间,很多小任务开始显现。在Flant,我们迫切想要以正确的方式来自动化它们,因此我们觉得需要更智能的解决方案。通常你可以使用基本的bash脚本来解决所有这些任务,但是如你所知,更推荐的方式是使用Golang来编写Operators。很显然,为每个小任务分别开发成熟的Operator将会很低效。


15分钟内创建一个Operator


我们将举一个在Kubernetes集群中可以被自动化的例子,以及shell-operator可以如何帮助我们。我们将尝试复制用于访问Docker仓库的凭证。


使用私有仓库镜像的Pod应在其清单中包含指定的用于访问仓库的secret。这个secret必须在创建Pod之前先创建在每个命名空间中。你可以手动执行此操作,但是,如果我们将配置动态的多个环境,我们将为单个应用程序创建许多命名空间。在多个应用程序(甚至两个或三个)的情况下,secret的数量会变得巨大。关于secret还有一个需求:我们希望能够偶尔更改(注册表)仓库的访问密钥。因此,手动解决方案变得非常低效,你必须自动创建和更新secret。


简单的自动化


我们来写一个脚本,每N秒运行一次,并检查命名空间中secret是否存在。如果secret不存在,那么它将会被创建。这个解决方案的优势是它看起来就像是cron中的一个shell脚本,一种经典且易于理解的方法。缺点是在此脚本的两次启动之间的间隔期间可能会出现一些新的命名空间,因此在一段时间内它将不会持有这个secret。这种情况会导致启动Pod的过程中出错。


使用shell-operator进行自动化


为了使我们的脚本准确运行,经典的cron执行应该被当有新增命名空间事件发生时的执行所取代。在这种情况下,你可以在使用之前创建一个secret。让我们看看如何使用shell-operator来实现这个功能。


首先,我们先分析一下脚本,就shell-operator而言,脚本都被称之为“钩子“。每个钩子在使用--config标志执行时都会通知shell-operator将其绑定(即需要执行哪些事件)。在我们的例子中,我们将使用onKubernetesEvent


#!/bin/bash
if [[ $1 == "--config" ]] ; then
cat <

在这里,我们定义我们关注的namespace类型的添加(add)对象事件。


现在我们需要添加当事件发生时需要执行的代码:


#!/bin/bash
if [[ $1 == "--config" ]] ; then
# configuration
cat <

真棒!我们现在已有一个简洁且漂亮的脚本,想让它能真正发挥作用,我们需要准备一个镜像并将其跑在集群中。


使用钩子制作我们的镜像


你可以很轻易观察到我们在脚本里面使用了kubectljq命令。这意味着镜像中需要包含钩子,shell-operator二进制文件(它将监视事件并执行这个钩子),以及钩子需要用到的命令(kubectljq)。hub.docker.com上已提供了包含shell-operator,kubectl和jq的即用型镜像。现在是时候使用Dockerfile来添加一个钩子:


$ cat Dockerfile
FROM flant/shell-operator:v1.0.0-beta.1-alpine3.9
ADD namespace-hook.sh /hooks
$ docker build -t registry.example.com/my-operator:v1 .
$ docker push registry.example.com/my-operator:v1

在集群中运行


我们再来看看这个钩子,这次我们将关注具体的操作以及它在集群中执行的对象:



  1. 它订阅了namespace的创建事件;

  2. 它在不与它所运行的命名空间相同的空间创建一个secret。


这里我们会发现运行这个镜像的Pod需要有执行这些操作的权限。你可以授权给一个ServiceAccount。由于我们是关注整个集群中的对象,那么权限需要使用ClusterRoleClusterRoleBinding形式来配置。


YAML最终配置描述如下:


---
apiVersion: v1
kind: ServiceAccount
metadata:
name: monitor-namespaces-acc
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: monitor-namespaces
rules:
- apiGroups: [""]
resources: ["namespaces"]
verbs: ["get", "watch", "list"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list", "create", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: monitor-namespaces
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: monitor-namespaces
subjects:
- kind: ServiceAccount
name: monitor-namespaces-acc
namespace: example-monitor-namespaces

你可以将创建的镜像部署为一个简单的Deployment:


apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: my-operator
spec:
template:
spec:
containers:
- name: my-operator
image: registry.example.com/my-operator:v1
serviceAccountName: monitor-namespaces-acc

为方便起见,我们将创建一个单独的命名空间,用于运行shell-operator并应用创建的部署清单:


$ kubectl create ns example-monitor-namespaces
$ kubectl -n example-monitor-namespaces apply -f rbac.yaml
$ kubectl -n example-monitor-namespaces apply -f deployment.yaml

好了,shell-operator启动,它将订阅命名空间创建事件并在需要时执行钩子。



这样一个简单的shell脚本就变成了Kubernetes中一个真正的Operator,并成为集群的一部分。这样做的好处是我们避免了使用Golang来开发Operator的复杂过程:




过滤


关于对象的观察很棒,但我们通常需要响应对象中某些属性的更改,例如,增加/减少部署中的副本数量或对象对标签中的任何更新。


当一个事件发生时,shell-operator接收该对象的JSON清单。在此JSON中,你可以选择要监视的属性,并仅在更改时启动钩子。jqFilter字段可以帮助你完成这点:你应该输入将应用于JSON清单的jq表达式。


举个例子,要响应Deployment对象标签中的修改,你必须从metadata字段中提取labels字段。这个例子中你将需要如下的配置:


cat <

jqFilter表达式将Deployment的长长的JSON清单转换成带有标签的简短的JSON:




shell-operator将只会在这个简短的JSON发生变化时执行钩子。其它属性的变更将会被忽略。


钩子的执行上下文


钩子的配置允许你指定几种事件。例如你可以定义两个Kubernetes事件和两个计划调度:


{
"onKubernetesEvent": [
{
"name": "OnCreatePod",
"kind": "pod",
"event": [
"add"
]
},
{
"name": "OnModifiedNamespace",
"kind": "namespace",
"event": [
"update"
],
"jqFilter": ".metadata.labels"
}
],
"schedule": [
{
"name": "every 10 min",
"crontab": "0 */10 * * * *"
},
{
"name": "on Mondays at 12:10",
"crontab": "0 10 12 * * 1"
}
]
}

注意:shell-operator支持以crontab样式运行脚本!你可以在文档中找到额外的信息。


为了区分钩子执行的原因,shell-operator会创建一个临时文件并将其路径保存到BINDING_CONTEXT_TYPE变量中。此文件包含了执行钩子的原因的JSON描述。例如,每隔10分钟将会使用以下内容启动钩子:


[{ "binding": "every 10 min" }]

在周一的话它将以以下内容启动:


[{ "binding": "every 10 min" }, { "binding": "on Mondays at 12:10" }]

同时将有onKubernetesEvent调用的更详细的JSON,因为它包含了对象的描述:


[
{
"binding": "onCreatePod",
"resourceEvent": "add",
"resourceKind": "pod",
"resourceName": "foo",
"resourceNamespace": "bar"
}
]

你能通过名称来全面了解字段的内容(更多详细信息可在文档中找到)。使用jq从resourceName获取资源名称的示例已经在复制secret的钩子中展示:


jq -r '.[0].resourceName' $BINDING_CONTEXT_PATH

你可以通过类似的方式去获取到其它字段。


下一步是什么呢?


在该项目仓库中的/examples directory目录里包含了一些可以直接在集群中使用的示例。你可以将它们用作你开发自己的钩子的基础。


Shell-operator同样支持使用Prometheus来收集指标。METRICS章节已描述了这些可用的指标。


你能轻易想到,shell-operator是使用Go编写的,并根据开源许可证(Apache 2.0)的条款进行分发。我们非常感谢任何关于开发在Github上的这个项目的帮助。你可以通过给我们点Star,反馈问题或者是PR来支持我们!


原文链接:Announcing shell-operator to simplify creating of Kubernetes operators(翻译:冯旭松)


在Docker上编译OpenJDK 8

李颖杰 发表了文章 • 0 个评论 • 136 次浏览 • 2019-06-18 11:06 • 来自相关话题

以前曾经试过在VMware上安装Linux,但是每次都不顺利,例如Linux环境,预装依赖软件,OpenJDK源码的选择等环境都会遇到问题,一旦失败再重新开始挺费时间的,现在用Docker就省事多了,镜像和容器的创建和删除都比较简单干净,专心做好Dock ...查看全部

以前曾经试过在VMware上安装Linux,但是每次都不顺利,例如Linux环境,预装依赖软件,OpenJDK源码的选择等环境都会遇到问题,一旦失败再重新开始挺费时间的,现在用Docker就省事多了,镜像和容器的创建和删除都比较简单干净,专心做好Dockerfile就行,下面我们一起来实践一下吧。



本次实战用到的所有文件,已经打包到GitHub上,路径是git@github.com:zq2599/centos7_build_openjdk8.git,欢迎您来使用(git clone git@github.com:zq2599/centos7_build_openjdk8.git)。



本次编译实战的基本步骤如下:


编写的Dockerfile中要做的如下的事情:




  1. 安装依赖的软件;

  2. 把OpenJDK的源码复制到镜像中;



在编写Dockerfile之前要做三个重要的选择,如下:




  1. Linux:我选择了CentOS 7,之前试过Ubuntu 16.04,但是在Configure的时候提示”freetype”没有安装,我按照提示去装了,再次Configure的时候继续提示”freetype”没有安装……(此问题现在还没解决,如果您解决过相同问题,请您告诉一下解决方法,谢谢了!)

  2. OpenJDK源码,这次要编译的是OpenJDK 8,源码的下载地址在这里

  3. Bootstrap JDK:即编译时要用到的JDK,下载了OpenJDK的源码后,解压开可以看到“README-builds.html”这个文件,里面有对Bootstrap JDK的描述:




看得出,需要安装JDK 7来编译OpenJDK 8的源码。



OK,关键问题都已确认,即将开始Dockerfile制作,不过制作之前还有个小问题需要先想好:本次我打算把制作镜像所需的Dockerfile和依赖文件都放到GitHub上去,这样做的好处有两个:




  1. 读者们从Git上clone下来之后直接执行Docker build就能在本地构建镜像;

  2. daocloud.io网站上支持通过执行GitHub目录的方式在线构建镜像,后面我们会实践在daocloud.io上构建镜像并部署到腾讯云或者阿里云服务器上。



上传到Gith=Hub时,除了Dockerfile,还要上传的文件有两个:JDK 1.7和OpenJDK 8源码,都超过了100M,如下图:


这就麻烦了,GitHub上传文件的时候,单个文件不能超过100M,否则push的时候会被服务器拒绝,解决这个问题有两个办法:



1、构建镜像的时候不要把这两个文件复制到镜像中了,改为在Dockerfile中通过执行wget命令将这两个文件分别下载到镜像中,OpenJDK的下载路径是:http://www.java.net/download/openjdk/jdk8/promoted/b132/openjdk-8-src-b132-03_mar_2014.zip,而OpenJDK 1.7的下载路径就难办了,Oracle上下载历史版本的时候,是要做登录操作的,这个在Dockerfile中难以实现,找到了一个下载地址:https://mirror.its.sfu.ca/mirror/CentOS-Third-Party/NSG/common/x86_64/jdk-7u80-linux-x64.rpm,但是下载速度很慢,最少一个小时以上了,所以wget这种方法看似简单,但下载文件耗时实在太长;



2、第二种方法比较简单易用,就是在Mac或者Linux上先用split命令将文件分割成多个,再上传到GitHub上,在Dockerfile中有对应的命令将分割后的文件恢复成分割前的原文件,具体的分割命令如下:





split -b 50m jdk-7u71-linux-x64.rpm jdkrpm-


这个命令是将jdk-7u71-linux-x64.rpm分割成不超过50m的多个文件,分割后的文件以jdkrpm-作为文件名的前缀,如下图:


OpenJDK的源码用如下命令分割:





split -b 50m openjdk-8-src-b132-03_mar_2014.zip openjdksrc-


Dockerfile中,从分割文件恢复以上两个原文件的命令为:





cat jdkrpm-* > jdk-7u71-linux-x64.rpm
cat openjdksrc-* > openjdk-8-src-b132-03_mar_2014.zip


以上就是两种处理大文件的方法,本文用的是第二种,即先分割上传到Git,在Dockerfile中将已分割文件恢复成原文件再使用。



好了,前期的准备工作已经做完了,现在可以编写Dockerfile文件了,整个文件中要做的事情列出如下:



1、安装依赖软件,例如libXtst-devel,libXt-devel等等,这些都是编译前的Configure命令要检查的,检查不过无法进行编译;



2、把分割后的OpenJDK源码复制到镜像文件中,再合成,再解压;



3、安装JDK 7,把分割后的安装文件复制到镜像中合成,然后安装;



4、为了方便用户进入容器后快速开始编译,我们做了一个shell脚本start_make.sh,把这个脚本也要复制到镜像中,内容如下:





#!/bin/bash
$WORK_PATH/$OPENJDK_SRC_DIR/configure
echo "start make"
cd $WORK_PATH/$OPENJDK_SRC_DIR
make all ZIP_DEBUGINFO_FILES=0 DISABLE_HOTSPOT_OS_VERSION_CHECK=OK


5、清理无用的文件,例如OpenJDK源码的压缩文件,JDK 7的安装文件等;



按照以上步骤,最终写出的Dockerfile文件如下:





# Docker image of compile and build enviroment for openjdk8
# VERSION 0.0.1
# Author: bolingcavalry

#基础镜像使用CentOS 7
FROM centos:centos7

#作者
MAINTAINER BolingCavalry

#定义工作目录
ENV WORK_PATH /usr/local

#定义JDK 1.7的文件名
ENV JDK_RPM_FILE jdk-7u71-linux-x64.rpm

#定义OpenJDK源码的文件名
ENV OPENJDK_SRC_ZIP openjdk-8-src-b132-03_mar_2014.zip

#定义解压缩后的文件名
ENV OPENJDK_SRC_DIR openjdk

#yum更新
RUN yum -y update

#安装工具集
RUN yum -y groupinstall "Development Tools"

#安装即将用到的软件
RUN yum -y install unzip libXtst-devel libXt-devel libXrender-devel cups-devel freetype-devel alsa-lib-devel which

#把分割过的JDK 1.7安装文件复制到工作目录
COPY ./jdkrpm-* $WORK_PATH/

#用本地分割过的文件恢复原有的JDK 1.7的安装文件
RUN cat $WORK_PATH/jdkrpm-* > $WORK_PATH/$JDK_RPM_FILE

#本地安装JDK 1.7
RUN yum -y localinstall $WORK_PATH/$JDK_RPM_FILE

#把分割过的OpenJDK 8的源码压缩包复制到工作目录
COPY ./openjdksrc-* $WORK_PATH/

#用本地分割过的文件恢复原有的OpenJDK 8的源码压缩包
RUN cat $WORK_PATH/openjdksrc-* > $WORK_PATH/$OPENJDK_SRC_ZIP

#解压缩源码
RUN unzip $WORK_PATH/$OPENJDK_SRC_ZIP -d $WORK_PATH

#复制启动编译的shell
COPY ./start_make.sh $WORK_PATH/$OPENJDK_SRC_DIR/

#给执行文件增加可执行权限:Configure文件
RUN chmod a+x $WORK_PATH/$OPENJDK_SRC_DIR/configure

#给执行文件增加可执行权限:启动编译文件
RUN chmod a+x $WORK_PATH/$OPENJDK_SRC_DIR/start_make.sh

#删除分割文件
RUN rm $WORK_PATH/jdkrpm-*

#删除分割文件
RUN rm $WORK_PATH/openjdksrc-*

#删除JDK安装包文件
RUN rm $WORK_PATH/$JDK_RPM_FILE

#删除OpenJDK源码压缩文件
RUN rm $WORK_PATH/$OPENJDK_SRC_ZIP


至此,镜像文件制作所需的材料都已经齐全了,如下图:


现在让我们开始制作镜像吧,打开终端,进入Dockerfile所在目录,执行命令:





docker build -t bolingcavalryopenjdk:0.0.1 .


因为要在线安装不少的软件,所以可能耗时会略长,和网络带宽有关,我在住处用家庭网络大概10分钟左右构建成功,执行目录docker images查看镜像,新的镜像文件已经生成了,如下图:


现在启动一个容器试试吧:





docker run --name=jdk001 -idt bolingcavalryopenjdk:0.0.1


容器已经启动,再执行以下命令进入容器:





docker exec -it jdk001 /bin/bash


进去后,直接到/usr/local/openjdk目录下,执行./start_make.sh,开始编译了,整个过程的耗时和当前电脑的硬件配置有关,我用i7处理器的Mac Pro 15大约要用20多分钟,编译结束后会有类似下图的输出:


这时候去/usr/local/openjdk目录下看看,发现多了一个build目录,这里面就是编译好的结果,如下图:


build目录下只有一个linux-x86_64-normal-server-release目录,再进去就能看到JDK目录了,如下图:


进入/usr/local/openjdk/build/linux-x86_64-normal-server-release/jdk/bin目录,会发现里面有Java文件,执行./java -version输出如下:


新的JDK信息已经打印出来了,OpenJDK Runtime Enviroment信息已经说明了这是个最新构建的JDK环境。



至此我们的本次实战就结束了,面对如此干净的编译环境和现成的源码,读者您是否有一种改动一番源码的冲动,然后构建一个个性化的属于自己的JDK,建议您自己动手修改和编译OpenJDK源码,以加深对JVM的认识。

国内镜像源解决方式

徐新坤 发表了文章 • 0 个评论 • 207 次浏览 • 2019-06-17 09:25 • 来自相关话题

Azure China提供了目前用过的质量最好的镜像源,涵盖了docker.io,gcr.io,quay.io。无论是速度还是覆盖范围,体验都极佳。而且都支持匿名拉取,也就是不需要登录。这点特别友好。azk8s.cn支持的镜像代理转换如下列表。 ...查看全部

Azure China提供了目前用过的质量最好的镜像源,涵盖了docker.io,gcr.io,quay.io。无论是速度还是覆盖范围,体验都极佳。而且都支持匿名拉取,也就是不需要登录。这点特别友好。azk8s.cn支持的镜像代理转换如下列表。






globalproxy in Chinaformatexample
dockerhub (docker.io)dockerhub.azk8s.cndockerhub.azk8s.cn//:dockerhub.azk8s.cn/microsoft/azure-cli:2.0.61 dockerhub.azk8s.cn/library/nginx:1.15
gcr.iogcr.azk8s.cngcr.azk8s.cn//:gcr.azk8s.cn/google_containers/hyperkube-amd64:v1.13.5
quay.ioquay.azk8s.cnquay.azk8s.cn//:quay.azk8s.cn/deis/go-dev:v1.10.0



Note:
k8s.gcr.io would redirect to gcr.io/google-containers, following image urls are identical:



k8s.gcr.io/pause-amd64:3.1
gcr.io/google_containers/pause-amd64:3.1



这里,我开发了一个小的脚本azk8spull,这个脚本可以自动根据镜像名称进行解析,转换为azure的mirror镜像源域名。并进行拉取。拉取完成后会自动进行tag重命名为原本的镜像名。该脚本已经开源在 https://github.com/xuxinkun/littleTools#azk8spull 上。以下是使用样例。


[root@node-64-216 ~]# azk8spull quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.24.1
## azk8spull try to pull image from mirror quay.azk8s.cn/kubernetes-ingress-controller/nginx-ingress-controller:0.24.1.
0.24.1: Pulling from kubernetes-ingress-controller/nginx-ingress-controller
Digest: sha256:76861d167e4e3db18f2672fd3435396aaa898ddf4d1128375d7c93b91c59f87f
Status: Image is up to date for quay.azk8s.cn/kubernetes-ingress-controller/nginx-ingress-controller:0.24.1
## azk8spull try to tag quay.azk8s.cn/kubernetes-ingress-controller/nginx-ingress-controller:0.24.1 to quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.24.1.
## azk8spull finish pulling.

[root@node-64-216 ~]# azk8spull k8s.gcr.io/pause-amd64:3.1
## azk8spull try to pull image from mirror gcr.azk8s.cn/google_containers/pause-amd64:3.1.
3.1: Pulling from google_containers/pause-amd64
Digest: sha256:59eec8837a4d942cc19a52b8c09ea75121acc38114a2c68b98983ce9356b8610
Status: Image is up to date for gcr.azk8s.cn/google_containers/pause-amd64:3.1
## azk8spull try to tag gcr.azk8s.cn/google_containers/pause-amd64:3.1 to k8s.gcr.io/pause-amd64:3.1.
## azk8spull finish pulling.



参考资料: 


- Docker Registry Proxy Cache 帮助 http://mirror.azure.cn/help/docker-registry-proxy-cache.html 

- Azure China container registry proxy https://github.com/Azure/container-service-for-azure-china/tree/master/aks#22-container-registry-proxy


原文链接:docker/kubernetes国内源/镜像源解决方式

Go版微服务开发框架Micro及标准2019年大整合

cleverlzc 发表了文章 • 0 个评论 • 299 次浏览 • 2019-06-16 08:38 • 来自相关话题

【编者的话】Micro是构建微服务的最简单方式,并逐渐成为云计算中基于Go的微服务开发的实际标准。通过将我们的努力整合到一个开发框架和运行时中,我们使这个过程更加简单。 Micro作为[go-micro](https://gith ...查看全部

【编者的话】Micro是构建微服务的最简单方式,并逐渐成为云计算中基于Go的微服务开发的实际标准。通过将我们的努力整合到一个开发框架和运行时中,我们使这个过程更加简单。 

Micro作为[go-micro](https://github.com/micro/go-micro)——一个微服务框架开始了它的旅程,专注于提供微服务开发的核心需求。它通过抽象出分布式系统的复杂性,为构建微服务创造了更简单的体验。

随着时间的推移,我们已经从go-micro扩展到其他工具、库和插件。这导致了我们解决问题的方式和开发人员使用微服务工具的方式的分散化。我们现在正在整合所有这些工具,以简化开发人员的体验。

从本质上来说,Micro已经成为一个独立的开发框架和微服务开发的运行时。

在讨论整合之前,让我们回顾一下迄今为止的历程。

### 主要关注点

Go-micro最初主要专注于微服务的通信方面,我们一直努力做到这一点。到目前为止,这种固执己见的方法和关注点是驱动框架成功的真正驱动力。多年来,我们已经收到了无数的请求,要求解决第二天在go-micro中构建生产就绪软件的问题。其中大部分都与可伸缩性、安全性、同步和配置有关。


虽然增加所要求的额外特性是有好处的,但我们确实希望一开始就非常专注于很好地解决一个问题。所以我们采取了一种不同的方式来促进社区这样做。

### 生态系统和插件

投入生产所涉及的不仅仅是普通的服务发现、消息编码和请求-响应。我们真正明白这一点,希望使用户能够通过可插拔和可扩展的接口选择更广泛的平台需求。通过[资源管理器](https://micro.mu/explore/)促进生态系统,资源管理器聚合了GitHub上的基于微服务的开源项目,并通过[go-plugins](https://github.com/micro/go-plugins)扩展插件。


一般来说,Go插件已经取得了巨大的成功,因为它允许开发人员将大量的复杂性转移到为这些需求构建的系统上。例如用于度量的Prometheus、用于分布式跟踪的Zipkin和用于持久消息传递的Kafka。

### 交互点

Go Micro确实是微服务开发的核心,但是随着服务的编写,接下来的问题就转移到了:我如何查询它们,如何与它们交互,如何通过传统方式为它们服务。

鉴于go-micro使用了一个基于RPC/Protobuf的协议,该协议既可插拔又不依赖于运行时,我们需要某种方法来解决这个问题。这导致了微服务工具包[Micro](https://github.com/micro/micro)的产生。Micro提供了API网关、网络仪表板、cli命令行工具、slack bot机器人程序、服务代理等等。


Micro工具包通过http api、浏览器、slack命令和命令行接口充当交互点。这些是我们查询和构建应用程序的常见方式,对于我们来说,提供一个真正支持这一点的运行时非常重要。然而,但它仍然把重点放在通信上。

###其他工具

虽然插件和工具包极大地帮助了使用了Micro的用户,但在关键领域仍然缺乏。很明显,我们的社区希望我们能够围绕产品开发的平台工具来解决更多的问题,而不是必须在他们各自的公司中单独完成。我们需要为动态配置、分布式同步和为Kubernetes这样的系统提供更广泛的解决方案等方面提供相同类型的抽象。

于是我们创建了以下项目:


- [micro/go-config](https://github.com/micro/go-config): 一个动态配置库

- [micro/go-sync](https://github.com/asim/go-sync):一个分布式同步库

- [micro/kubernetes](https://github.com/micro/kubernetes):在Kubernetes平台上的初始化

- [examples](https://github.com/micro/examples):使用举例

- [microhq](https://github.com/microhq):微服务预构建


这些是一部分repos、库和工具,用于尝试解决我们社区更广泛的需求。在过去的四年里,repos的数量不断增长,新用户的入门体验也变得更加困难。进入壁垒急剧增加,我们意识到需要做出一些改变。

在过去的几周里,我们意识到[go-micro](https://github.com/micro/go-micro)确实是大多数用户开发微服务的焦点。很明显,他们想要额外的功能,作为这个库的一部分以及一个自我描述的框架,我们真的需要通过解决那些第二天的问题来实现这一点,而不要求开发人员寻求其他方法。

本质上,go-micro将成为微服务开发的全面和独立框架。

我们通过将所有库迁移到go-micro开始了整合过程,在接下来的几周里,我们将继续进行重构,以提供更简单的默认入门体验,同时还为日志记录、跟踪、度量、身份验证等添加更多功能。


不过,我们也没有忘记Micro。在我们看来,当构建了微服务之后,仍然需要一种查询、运行和管理它们的方法。所有人都认为Micro将是微服务开发的运行时。我们正在致力于提供一种更简单的方法来管理微服务开发的端到端流程,并且应该很快会有更多消息发布。

### 总结

Micro是构建微服务的最简单方式,并逐渐成为云计算中基于Go的微服务开发的实际标准。通过将我们的努力整合到一个开发框架和运行时中,我们使这个过程更加简单。

原文链接:Micro - The great consolidation of 2019


**译者**:Mr.lzc,软件工程师、DevOpsDays深圳核心组织者,目前供职于华为,从事云存储工作,以Cloud Native方式构建云文件系统服务,专注于Kubernetes、微服务领域。


睿云智合 | 开源项目Breeze成为Kubernetes认证安装工具

wise2c 发表了文章 • 0 个评论 • 388 次浏览 • 2019-06-14 11:46 • 来自相关话题

近日,睿云智合开源的Kubernetes图形化部署工具Breeze项目通过Kubernetes一致性认证成为认证Kubernetes安装工具。目前Breeze已经列入 Cloud Native Landscape 生态图谱的认证安装工具板块。 ...查看全部

近日,睿云智合开源的Kubernetes图形化部署工具Breeze项目通过Kubernetes一致性认证成为认证Kubernetes安装工具。目前Breeze已经列入 Cloud Native Landscape 生态图谱的认证安装工具板块。


Beeze项目是睿云智合(Wise2C)2018年5月所开源的Kubernetes图形化部署工具,能大大简化Kubernetes部署的步骤,支持全离线环境的部署,而且可以不需要翻墙获取Google的相应资源包,尤其适合中国金融、运营商、国有企业等不便访问互联网的私有数据中心部署环境场景。目前支持最新版Kubernetes、Etcd、Docker、Harbor以及Prometheus等云原生工具部署,同时支持Istio部署 (内置Kiali, Jaeger, Prometheus, Grafana)。推出至今获得开源技术社区用户的一致好评目前在Github上已获600余星。



功能亮点:

易于运行:

Breeze将您需要的所有资源(比如Kubernetes组件镜像以及用于部署Kubernetes集群的 ansible playbooks)组合为一个Docker镜像(wise2c/playbook)。它还可以作为本地yum存储库服务器工作。您只需要安装了Docker引擎的Linux服务器来运行Breeze。



简化了kubernetes集群部署的过程:


通过几个简单的命令,您可以轻而易举地运行,然后通过图形界面完成所有其他部署过程。



支持离线部署:

在部署服务器上加载了4个镜像(playbook、yum repo、pagoda、deploy ui)后,就可以在不接入互联网的情况下设置kubernetes集群。Breeze作为一个yum存储库服务器工作,部署一个本地的Harbor镜像仓库,并使用kubeadm来设置kubernetes集群。所有docker镜像将从本地镜像仓库提取。



支持多集群:

Breeze支持多个Kubernetes集群部署。

支持高可用架构:

通过Breeze,您可以设置Kubernetes集群,其中3台主服务器和3台ETCD服务器与Haproxy和Keepalived相结合。所有工作节点将使用虚拟浮动IP地址与主服务器通信。



Breeze项目是100%开源的云原生部署工具


GitHub项目地址:

https://github.com/wise2c-devops/breeze

安装过程演示视频在此:

 https://pan.baidu.com/s/1X0ZYt48wfYNrSrH7vvEKiw

常见排错说明在此:

https://github.com/wise2c-devops/breeze/blob/master/TroubleShooting-CN.md

PDF手册请在此处下载:

https://github.com/wise2c-devops/breeze/raw/master/manual/BreezeManual-CN.pdf

苹果宣布加入云原生计算基金会

大卫 发表了文章 • 0 个评论 • 408 次浏览 • 2019-06-13 08:27 • 来自相关话题

云原生计算基金会(简称CNCF)作为Kubernetes等顶级开源项目的运营方,今天宣布苹果公司即将以最高级白金用户的身份正式加盟。凭借这位新成员,CNCF如今已经拥有89位最终用户成员,其中还包括阿迪达斯、Atlassian、Box、GitHub、纽约 ...查看全部

云原生计算基金会(简称CNCF)作为Kubernetes等顶级开源项目的运营方,今天宣布苹果公司即将以最高级白金用户的身份正式加盟。凭借这位新成员,CNCF如今已经拥有89位最终用户成员,其中还包括阿迪达斯、Atlassian、Box、GitHub、纽约时报、Reddit、Spotify以及沃尔玛等。

与以往的作风一样,苹果公司并没有对此次公告做出评论。但CNCF方面指出,最终用户资格主要面向那些“对开源云原生技术高度依赖”且希望回馈整个社区的重度用户。作为CNCF最终用户成员,苹果公司实际上也正式加入了Linux基金会。

作为成员关系的一部分,苹果公司还在CNCF管理委员会当中获得一个席位,苹果方面的高级工程技术经理Tomer Doron将出任这一职位。

云原生计算基金会CTO Chris Aniszczyk表示,“吸引到苹果这样一家拥有丰富经验与庞大业务规模的企业作为最终用户成员,充分证明了云原生计算在未来基础设施与应用程序开发方面的可观潜力。我们很高兴能够获得苹果公司的支持,并期待着未来能够为更为广泛的云原生项目社区做出更多贡献。”

虽然很多朋友可能不会把苹果公司与开源参与企业联系起来,但事实上该公司确实已经开放了从Darwin操作系统的XNU内核到Swift编程语言等一系列内部成果。话虽如此,苹果方面一般不会参与开源云基础设施社区,而这次的举动可能预示着这位消费电子巨头正在迎来转变。苹果公司肯定拥有自己的数据中心,因此其确实有可能高度依赖着各类开源基础设施项目——当然,按照苹果的一贯风格,其对这类话题往往避而不谈。

原文链接:Apple joins the open-source Cloud Native Computing Foundation

基于Jenkins Pipeline自动化部署

尼古拉斯 发表了文章 • 0 个评论 • 484 次浏览 • 2019-06-05 23:53 • 来自相关话题

最近在公司推行Docker Swarm集群的过程中,需要用到Jenkins来做自动化部署,Jenkins实现自动化部署有很多种方案,可以直接在jenkins页面写Job,把一些操作和脚本都通过页面设置,也可以在每个项目中直接写Pipeline脚本,但像我 ...查看全部

最近在公司推行Docker Swarm集群的过程中,需要用到Jenkins来做自动化部署,Jenkins实现自动化部署有很多种方案,可以直接在jenkins页面写Job,把一些操作和脚本都通过页面设置,也可以在每个项目中直接写Pipeline脚本,但像我那么追求极致的程序员来说,这些方案都打动不了我那颗骚动的心,下面我会跟你们讲讲我是如何通过Pipeline脚本实现自动化部署方案的,并且实现多分支构建,还实现了所有项目共享一个Pipeline脚本。
#使用Jenkins前的一些设置

为了快速搭建Jenkins,我这里使用Docker安装运行Jenkins:

$ sudo docker run -it -d \
--rm \
-u root \
-p 8080:8080 \
-v jenkins-data:/var/jenkins_home \
-v /var/run/docker.sock:/var/run/docker.sock \
-v "$HOME":/home \
--name jenkins jenkinsci/blueocean

初次使用Jenkins,进入Jenkins页面前,需要密码验证,我们需要进入Docker容器查看密码:
$ sudo docker exec -it jenkins /bin/bash
$ vi /var/jenkins_home/secrets/initialAdminPassword

Docker安装的Jenkins稍微有那么一点缺陷,shell版本跟CentOS宿主机的版本不兼容,这时我们需要进入Jenkins容器手动设置shell:
$ sudo docker exec -it jenkins /bin/bash
$ ln -sf /bin/bash /bin/sh

由于我们的Pipeline还需要在远程服务器执行任务,需要通过SSH连接,那么我们就需要在Jenkins里面生成SSH的公钥密钥:
$ sudo docker exec -it jenkins /bin/bash
$ ssh-keygen -C "root@jenkins"

在远程节点的~/.ssh/authorized_keys中添加jenkins的公钥(id_rsa.pub)。

还需要安装一些必要的插件:

  1. Pipeline Maven Integration
  2. SSH Pipeline Steps

安装完插件后,还需要去全局工具那里添加Maven:


这里后面Jenkinsfile有用到。
#mutiBranch多分支构建

由于我们的开发是基于多分支开发,每个开发环境都对应有一条分支,所以普通的Pipeline自动化构建并不能满足现有的开发部署需求,所以我们需要使用Jenkins的mutiBranch Pipeline。如果你想和更多Jenkins技术专家交流,可以加我微信liyingjiese,备注『加群』。群里每周都有全球各大公司的最佳实践以及行业最新动态

首先当然是新建一个mutiBranch多分支构建Job:


接着设置分支源,分支源就是你项目的Git地址,选择Jenkinsfile在项目的路径:


接下来Jenkins会在分支源中扫描每个分支下的Jenkinsfile,如果该分支下有Jenkinsfile,那么就会创建一个分支Job:


该Job下的分支Job如下:


这里需要注意的是,只有需要部署的分支,才加上Jenkinsfile,不然Jenkins会将其余分支也创建一个分支Job。
#通用化Pipeline脚本

到这里之前,基本就可以基于Pipeline脚本自动化部署了,但如果你是一个追求极致,不甘于平庸的程序员,你一定会想,随着项目的增多,Pipeline脚本不断增多,这会造成越来越大的维护成本,业务的极速增长难免会在脚本中修改东西,这就会牵扯太多Pipeline脚本的改动,而且这些脚本基本都相同,那么对于我这么优秀的程序员,怎么会想不到这个问题呢,我第一时间就想到通用化Pipeline脚本。所幸,Jenkins已经看出了我不断骚动的心了,Jenkins甩手就给我一个Shared Libraries。

Shared Libraries是什么呢?顾名思义,它就是一个共享库,它的主要作用是用于将通用的Pipeline脚本放在一个地方,其它项目可以从它那里获取到一个全局通用化的Pipeline脚本,项目之间通过不通的变量参数传递,达到通用化的目的。

接下来我们先创建一个用于存储通用Pipeline脚本的Git仓库:


仓库目录就不能随便乱添加了,Jenkins有一个严格的规范,下面是官方说明:


官方已经讲得很清楚了,大概意思就是vars目录用于存储通用Pipeline脚本,resources用于存储非Groovy文件。所以我这里就把Pipeline需要的构建脚本以及编排文件都集中放在这里,完全对业务工程师隐蔽,这样做的目的就是为了避免业务工程师不懂瞎几把乱改,导致出bug。

创建完Git仓库后,我们还需要在Jenkins的Manage Jenkins » Configure System » Global Pipeline Libraries中定义全局库:


这里的name,可以在jenkinsfile中通过以下命令引用:

@Library 'objcoding-pipeline-library'

下面我们来看通用Pipeline脚本的编写规则:
#!groovy

def getServer() {
def remote = [:]
remote.name = 'manager node'
remote.user = 'dev'
remote.host = "${REMOTE_HOST}"
remote.port = 22
remote.identityFile = '/root/.ssh/id_rsa'
remote.allowAnyHosts = true
return remote
}

def call(Map map) {

pipeline {
agent any

environment {
REMOTE_HOST = "${map.REMOTE_HOST}"
REPO_URL = "${map.REPO_URL}"
BRANCH_NAME = "${map.BRANCH_NAME}"
STACK_NAME = "${map.STACK_NAME}"
COMPOSE_FILE_NAME = "" + "${map.STACK_NAME}" + "-" + "${map.BRANCH_NAME}" + ".yml"
}

stages {
stage('获取代码') {
steps {
git([url: "${REPO_URL}", branch: "${BRANCH_NAME}"])
}
}

stage('编译代码') {
steps {
withMaven(maven: 'maven 3.6') {
sh "mvn -U -am clean package -DskipTests"
}
}
}

stage('构建镜像') {
steps {
sh "wget -O build.sh https://git.x-vipay.com/docker/jenkins-pipeline-library/raw/master/resources/shell/build.sh"
sh "sh build.sh ${BRANCH_NAME} "
}
}

stage('init-server') {
steps {
script {
server = getServer()
}
}
}

stage('执行发版') {
steps {
writeFile file: 'deploy.sh', text: "wget -O ${COMPOSE_FILE_NAME} " +
" https://git.x-vipay.com/docker/jenkins-pipeline-library/raw/master/resources/docker-compose/${COMPOSE_FILE_NAME} \n" +
"sudo docker stack deploy -c ${COMPOSE_FILE_NAME} ${STACK_NAME}"
sshScript remote: server, script: "deploy.sh"
}
}
}
}
}


  1. 由于我们需要在远程服务器执行任务,所以定义一个远程服务器的信息其中remote.identityFile就是我们上面在容器生成的密钥的地址;
  2. 定义一个call()方法,这个方法用于在各个项目的Jenkinsfile中调用,注意一定得叫call;
  3. 在call()方法中定义一个Pipeline;
  4. environment参数即是可变通用参数,通过传递参数Map来给定值,该Map是从各个项目中定义的传参;
  5. 接下来就是一顿步骤操作啦,“编译代码”这步骤需要填写上面我们在全局工具类设置的maven,“构建镜像”的构建脚本巧妙地利用wget从本远程仓库中拉取下来,”执行发版“的编排文件也是这么做,“init-server”步骤主要是初始化一个server对象,供“执行发版使用”。

从脚本看出来Jenkins将来要推崇的一种思维:配置即代码。

写完通用Pipeline脚本后,接下来我们就需要在各个项目的需要自动化部署的分支的根目录下新建一个Jenkinsfile脚本了:


接下来我来解释一下Jenkinsfile内容:

#!groovy

// 在多分支构建下,严格规定Jenkinsfile只存在可以发版的分支上

// 引用在jenkins已经全局定义好的library
library 'objcoding-pipeline-library'
def map = [:]

// 远程管理节点地址(用于执行发版)
map.put('REMOTE_HOST','xxx.xx.xx.xxx')
// 项目gitlab代码地址
map.put('REPO_URL','https://github.com/objcoding/docker-jenkins-pipeline-sample.git')
// 分支名称
map.put('BRANCH_NAME','master')
// 服务栈名称
map.put('STACK_NAME','vipay')

// 调用library中var目录下的build.groovy脚本
build(map)


  1. 通过library 'objcoding-pipeline-library'引用我们在Jenkins定义的全局库,定义一个map参数;
  2. 接下来就是将项目具体的参数保存到map中,调用build()方法传递给通用Pipeline脚本。

Shared Libraries共享库极大地提升了Pipeline脚本的通用性,避免了脚本过多带来的问题,也符合了一个优秀程序员的审美观,如果你是一个有追求的程序员,你一定会爱上它。

附上一张价值连城的手稿图:



原文链接:https://mp.weixin.qq.com/s/2M2RQN-_2wmWf4OslIpuaA

DockOne微信分享(二一一):基于Actor模型的CQRS/ES解决方案分享

JetLee 发表了文章 • 0 个评论 • 442 次浏览 • 2019-06-05 16:17 • 来自相关话题

【编者的话】2017年加密货币比较流行,我曾有幸在加密货币交易所参与开发工作,为了应对交易系统高性能、高并发、高可用的要求,我们使用基于Actor模型的Orleans技术,采用CQRS/ES架构结合Service Fabric开展了富有挑战性的工作。本文 ...查看全部

【编者的话】2017年加密货币比较流行,我曾有幸在加密货币交易所参与开发工作,为了应对交易系统高性能、高并发、高可用的要求,我们使用基于Actor模型的Orleans技术,采用CQRS/ES架构结合Service Fabric开展了富有挑战性的工作。本文将从不同视角为大家介绍Actor模型、CQRS/ES架构以及Service Fabric在高并发场景中的考量和应用。



话题由三部分组成:




  • Actor模型&Orleans:在编程的层面,从细粒度-由下向上的角度介绍Actor模型;

  • CQRS/ES:在框架的层面,从粗粒度-由上向下的角度介绍Actor模型,说明Orleans技术在架构方面的价值;

  • Service Fabric:从架构部署的角度将上述方案落地上线。



群里的小伙伴技术栈可能多是Java和Go体系,分享的话题主要是C#技术栈,没有语言纷争,彼此相互学习。比如:Scala中,Actor模型框架有akka,CQRS/ES模式与编程语言无关,Service Fabric与Kubernetes是同类平台,可以相互替代,我自己也在学习Kubernetes。





Actor模型&Orleans(细粒度)





共享内存模型



多核处理器出现后,大家常用的并发编程模型是共享内存模型。


这种编程模型的使用带来了许多痛点,比如:




  • 编程:多线程、锁、并发集合、异步、设计模式(队列、约定顺序、权重)、编译

  • 无力:单系统的无力性:①地理分布型、②容错型

  • 性能:锁,性能会降低

  • 测试:



    • 从坑里爬出来不难,难的是我们不知道自己是不是在坑里(开发调试的时候没有热点可能是正常的)

    • 遇到bug难以重现。有些问题特别是系统规模大了,可能运行几个月才能重现问题

  • 维护:



    • 我们要保证所有对象的同步都是正确的、顺序的获取多个锁。

    • 12个月后换了另外10个程序员仍然按照这个规则维护代码。



简单总结:




  • 并发问题确实存在

  • 共享内存模型正确使用掌握的知识量多

  • 加锁效率就低

  • 存在许多不确定性





Actor模型



Actor模型是一个概念模型,用于处理并发计算。Actor由3部分组成:状态(State)+行为(Behavior)+邮箱(Mailbox),State是指Actor对象的变量信息,存在于Actor之中,Actor之间不共享内存数据,Actor只会在接收到消息后,调用自己的方法改变自己的state,从而避免并发条件下的死锁等问题;Behavior是指Actor的计算行为逻辑;邮箱建立Actor之间的联系,一个Actor发送消息后,接收消息的Actor将消息放入邮箱中等待处理,邮箱内部通过队列实现,消息传递通过异步方式进行。


Actor是分布式存在的内存状态及单线程计算单元,一个Id对应的Actor只会在集群种存在一个(有状态的 Actor在集群中一个Id只会存在一个实例,无状态的可配置为根据流量存在多个),使用者只需要通过Id就能随时访问不需要关注该Actor在集群的什么位置。单线程计算单元保证了消息的顺序到达,不存在Actor内部状态竞用问题。



Actor是分布式存在的内存状态及单线程计算单元,一个ID对应的Actor只会在集群种存在一个(有状态的 Actor在集群中一个ID只会存在一个实例,无状态的可配置为根据流量存在多个),使用者只需要通过ID就能随时访问不需要关注该Actor在集群的什么位置。单线程计算单元保证了消息的顺序到达,不存在Actor内部状态竞用问题。



举个例子:



多个玩家合作在打Boss,每个玩家都是一个单独的线程,但是Boss的血量需要在多个玩家之间同步。同时这个Boss在多个服务器中都存在,因此每个服务器都有多个玩家会同时打这个服务器里面的Boss。



如果多线程并发请求,默认情况下它只会并发处理。这种情况下可能造成数据冲突。但是Actor是单线程模型,意味着即使多线程来通过Actor ID调用同一个Actor,任何函数调用都是只允许一个线程进行操作。并且同时只能有一个线程在使用一个Actor实例。





Actor模型:Orleans



Actor模型这么好,怎么实现?



可以通过特定的Actor工具或直接使用编程语言实现Actor模型,Erlang语言含有Actor元素,Scala可以通过Akka框架实现Actor编程。C#语言中有两类比较流行,Akka.NET框架和Orleans框架。这次分享内容使用了Orleans框架。



特点:



Erlang和Akka的Actor平台仍然使开发人员负担许多分布式系统的复杂性:关键的挑战是开发管理Actor生命周期的代码,处理分布式竞争、处理故障和恢复Actor以及分布式资源管理等等都很复杂。Orleans简化了许多复杂性。



优点:




  • 降低开发、测试、维护的难度

  • 特殊场景下锁依旧会用到,但频率大大降低,业务代码里甚至不会用到锁

  • 关注并发时,只需要关注多个actor之间的消息流

  • 方便测试

  • 容错

  • 分布式内存



缺点:




  • 也会出现死锁(调用顺序原因)

  • 多个Actor不共享状态,通过消息传递,每次调用都是一次网络请求,不太适合实施细粒度的并行

  • 编程思维需要转变






第一小节总结:上面内容由下往上,从代码层面细粒度层面表达了采用Actor模型的好处或原因。





CQRS/ES(架构层面)





从1000万用户并发修改用户资料的假设场景开始







  1. 每次修改操作耗时200ms,每秒5个操作

  2. MySQL连接数在5K,分10个库

  3. 5 *5k *10=25万TPS

  4. 1000万/25万=40s

 

在秒杀场景中,由于对乐观锁/悲观锁的使用,推测系统响应时间更复杂。





使用Actor解决高并发的性能问题





1000万用户,一个用户一个Actor,1000万个内存对象。


200万件SKU,一件SKU一个Actor,200万个内存对象。




  • 平均一个SKU承担1000万/200万=5个请求

  • 1000万对数据库的读写压力变成了200万

  • 1000万的读写是同步的,200万的数据库压力是异步的

  • 异步落盘时可以采用批量操作



总结:



由于1000万+用户的请求根据购物意愿分散到200万个商品SKU上:每个内存领域对象都强制串行执行用户请求,避免了竞争争抢;内存领域对象上扣库存操作处理时间极快,基本没可能出现请求阻塞情况。



从架构层面彻底解决高并发争抢的性能问题。理论模型,TPS>100万+……





EventSourcing:内存对象高可用保障



Actor是分布式存在的内存状态及单线程计算单元,采用EventSourcing只记录状态变化引发的事件,事件落盘时只有Add操作,上述设计中很依赖Actor中State,事件溯源提高性能的同时,可以用来保证内存数据的高可用。






CQRS



上面1000万并发场景的内容来自网友分享的PPT,与我们实际项目思路一致,就拿来与大家分享这个过程,下图是我们交易所项目中的架构图:


开源版本架构图:


开源项目github:https://github.com/RayTale/Ray



第二小节总结:由上往下,架构层面粗粒度层面表达了采用Actor模型的好处或原因。





Service Fabric



系统开发完成后Actor要组成集群,系统在集群中部署,实现高性能、高可用、可伸缩的要求。部署阶段可以选择Service Fabric或者Kubernetes,目的是降低分布式系统部署、管理的难度,同时满足弹性伸缩。



交易所项目可以采用Service Fabric部署,也可以采用Kubernetes,当时Kubernetes还没这么流行,我们采用了Service Fabric,Service Fabric 是一款微软开源的分布式系统平台,可方便用户轻松打包、部署和管理可缩放的可靠微服务和容器。开发人员和管理员不需解决复杂的基础结构问题,只需专注于实现苛刻的任务关键型工作负荷,即那些可缩放、可靠且易于管理的工作负荷。支持Windows与Linux部署,Windows上的部署文档齐全,但在Linux上官方资料没有。现在推荐Kubernetes。



第三小节总结:




  1. 借助Service Fabric或Kubernetes实现低成本运维、构建集群的目的。

  2. 建立分布式系统的两种最佳实践:



    • 进程级别:容器+运维工具(Kubernetes/Service Fabric)

    • 线程级别:Actor+运维工具(Kubernetes/Service Fabric)

参考:




  1. ES/CQRS部分内容参考:《领域模型 + 内存计算 + 微服务的协奏曲:乾坤(演讲稿)》2017年互联网应用架构实战峰会

  2. 其他细节来自互联网,不一一列出





Q&A



Q:单点故障后,正在处理的cache数据如何处理的,例如,http、tcp请求……毕竟涉及到钱?

A:Actor有激活和失活的生命周期,激活的时候使用快照和Events来恢复最新内存状态,失活的时候保存快照。Actor框架保证系统中同一个key只会存在同一个Actor,当单点故障后,Actor会在其它节点重建并恢复最新状态。



Q:数据落地得策略是什么?还是说就是直接落地?

A:event数据直接落地;用于支持查询的数据,是Handler消费event后异步落库。



Q:Grain Persistence使用Relational Storage容量和速度会不会是瓶颈?

A:Grain Persistence存的是Grain的快照和event,event是只增的,速度没有出现瓶颈,而且开源版本测试中PostgreSQL性能优于MongoDB,在存储中针对这两个方面做了优化:比如分表、归档处理、快照处理、批量处理。



Q:Orleans中,持久化事件时,是否有支持并发冲突的检测,是如何实现的?

A:Orleans不支持;工作中,在事件持久化时做了这方面的工作,方式是根据版本号。



以上内容根据2019年6月4日晚微信群分享内容整理。分享人郑承良,上海某科技公司架构师,对高并发场景下的分布式金融系统拥有丰富的实战经验,曾为澳大利亚、迪拜多家交易所提供技术支持。DockOne每周都会组织定向的技术分享,欢迎感兴趣的同学加微信:liyingjiese,进群参与,您有想听的话题或者想分享的话题都可以给我们留言。