关于server:关于自托管环境您了解多少

2024年2月,也就是一年不到,Atlassian将终止对Server产品及插件的所有反对。 此布告公布后,许多用户须要理解怎么的前进方向才是最适宜企业的。为此,Atlassian提供了本地部署的数据中心(Data Center)版以及云版两个抉择。许多企业都偏向于抉择自托管的环境,因为并不是每个企业都可能或者违心对其所有需要采纳SaaS办法满足其所有需要。 那么对于须要自托管的企业来说,数据中心版(中国企业25人以上即可应用)是不二之选。本篇文章将帮您解答一些对于Atlassian自托管数据中心产品的常见疑难。 自托管的软件只能部署在本地?现实情况:数据中心产品可能在AWS或Azure上部署 只能在本地部署自托管软件的限度已成为过来式。Atlassian数据中心产品使您可能在放弃对环境管制的同时现代化您的组织。您不再须要在本人的硬件上进行部署。通过利用AWS或Azure等IaaS供应商在云中部署Atlassian数据中心,您能够播种云计算提供的许多益处。 基础设施倒退 通过抉择在云上部署,您能够开始将基础设施虚拟化并利用云的劣势。但不用放心,基础设施性能不会隐没,您能够依照本人的节奏过渡到云上。 降低成本 不可否认,云计算能够节省成本。在AWS或Azure上部署能够帮忙升高与基础设施、保护或治理反对相干的老本,并显著进步投资回报率。 灵活性和可扩展性 部署在云上能提供一个灵便的平台,能够依据须要扩大或放大。这让您可能自信地依据业务变动进行扩大或缩减,例如谋求新的翻新、摸索新市场或收买新公司。 扩大规模是否既简单又艰难?现实情况:数据中心产品使扩大变得轻而易举 扩充企业规模是一项艰巨的工作,但扩大软件规模却不用如此。在扩大过程中,重要的是思考您的基础设施和应用程序是否反对企业的以后规模、长期愿景、新的业务需要以及与这些变动相干的老本。扩大没有一种“一刀切”的办法。每个企业和团队都有不同的流程、工作流和需要。Atlassian数据中心产品可能帮忙您布局将来,并满足您的扩大和其余独特需要。 部署灵活性 能够在本人的硬件上或在云中部署。随着业务的增长和对Atlassian应用程序需要的减少,您能够轻松地扩大本人的硬件,避免停机和生产力损失。如果抉择在云中部署,您能够利用AWS或Azure等IaaS供应商来缓解扩大容量、经营老本和保护等方面的问题。 自信地治理增长 规模化不仅仅是数量的增长。为了无效地进行扩大,您须要思考多个因素,例如老本、企业增长指标和行为。数据中心产品提供的性能可帮忙您治理扩大的各个方面,从卫生状况和数据管理到爱护、性能等。 是否须要寰球基础设施?现实情况:数据中心产品可能提供满足您需要的灵活性 最佳性能与您团队所处的地理位置无关。 在寰球各地堆放基础设施以充沛反对团队是个十分谬误的观点。服务器堆藏在团队桌子下的日子一去不复返了。不要让公司节约资金、工夫和精力去建设和保护寰球各地的基础设施。 Atlassian数据中心产品让您在基础设施上灵便部署,满足您的企业对翻新和自动化的独特需要,而且齐全不会就义性能。 云计算能力 在云上部署自托管应用程序,意味着您能够放弃齐全的管制和统一的性能,而不用在所有地位部署服务器。云提供商帮忙您保护服务器,相当于缩小了资本投资和工夫,从而提供了更高的投资回报率,让您可能专一于其余的业务要害需要。 反对分布式团队 不想在云上部署?没有问题。数据中心产品提供的性能使您可能运行高性能的自托管全局环境,无需在每个地位都部署服务器。这样,散布在各地的团队都能取得更好的性能,同时升高企业的总体基础设施需要和老本。 想要安全性只能自食其力?**现实情况:数据中心产品提供了多种平安选项**在爱护Atlassian应用程序的安全性方面,您无需单独承当。 您能够经营一个自托管的环境,同时还能取得额定的平安保障,远超您外部IT和平安团队所能提供的。 平安的概念非常宽泛,尽管网络攻击通常是每一位高层关注的焦点,但企业也容易受到外部威逼,例如合规违规或政策失误,这同样可能对企业造成重大侵害。 为了帮忙您的企业防止这些危险,数据中心产品提供了多种改良Atlassian应用程序安全性的选项。 潜在的云平安好处 在云上部署数据中心产品能够为您的Atlassian应用程序提供由您的IT团队启用的安全性,此外,还可能取得由AWS或Azure等云提供商提供的外在安全性组件。 数据中心产品的安全性好处 除了您企业为了平安的不懈努力外,数据中心产品还设计有平安、合规和用户治理性能,帮忙您更好地爱护您的人员、数据和工作流程。

April 17, 2023 · 1 min · jiezi

关于server:Server版vs数据中心版二者的区别在哪里

2024年2月,也就是一年不到,Atlassian将终止对Server产品及插件的所有反对。此布告公布后,许多用户须要理解怎么的前进方向才是最适宜企业的。为此,Atlassian提供了本地部署的数据中心(Data Center)版以及云版两个抉择。对于须要自托管的企业来说,数据中心版(中国企业25人以上即可应用)是不二之选。本篇文章将为您比照Server版与数据中心版,让您更深刻地理解其中差别,以便您做出更好的判断。Atlassian本地部署的数据中心版不仅蕴含了Server版中深受用户相熟和喜爱的性能,还减少了更多的个性和性能,以便更好地服务企业客户。 Server版和数据中心版有什么区别?简略地来说,数据中心版是专为企业打造的,具备高性能和高可用性、可扩展性、无缝用户治理、灵便的部署选项和牢靠的安全性等个性,可能满足企业大规模经营的需要。 此外,自2021年2月起,Team Calendars for Confluence和Jira Advanced Roadmaps等插件也蕴含在了数据中心版产品中。 如果想要更好地了解Server版和数据中心版之间的区别,请立刻分割Atlassian寰球白金合作伙伴、云业余搭档——龙智,咱们将为您提供数据中心版路线图,让您具体理解以后可用或行将推出的所有附加性能。降级到本地部署的数据中心版的益处数据中心产品的丰盛性能将为您的企业带来很多益处。其中,最次要的三大益处有: 提供疾速、牢靠和可扩大的产品 作为企业中的一份子,您可能须要与大型、简单、一直壮大或地理位置扩散的团队进行单干。如果这些团队须要应用Atlassian产品来实现工作,那么任何性能或可用性问题都可能导致生产力的巨大损失。如果您不还确定是否须要进步Atlassian产品的速度、可靠性或可扩展性,请思考以下问题: 您的用户是否经验了提早? 导致性能问题的一个次要起因是并发应用。在高负载或顶峰期间,您的产品性能兴许会有所降落,这会让您的团队感到丧气。然而,通过在集群环境中部署数据中心版,您能够更好地反对企业跨多个节点的扩大,为您的团队提供更快、更无缝的体验。 此外,所有本地部署的数据中心产品都具备进步性能的个性。在Jira Software和Jira Service Management中,您能够将我的项目和问题进行存档,以清理空间和实例,并进步产品性能。 对于远离服务器物理地位的员工来说,速度也可能是一个问题。为了帮忙您更好地为地理位置扩散的团队提供反对,本地部署的数据中心版反对Jira Software、Jira Service Management和Confluence中的内容交付网络(CDN),以及反对Bitbucket的智能镜像和镜像场。这些个性能够改良分布式用户的应用体验,让他们不会因为所在位置而受到不利影响。 您有经验过停机吗? 尽管速度和性能对于用户来说至关重要,然而停机工夫可能会对企业造成更大的影响。对于依赖Atlassian产品来实现工作的用户来说,即便是几分钟的停机工夫也可能对企业造成微小的经济损失。因而,确保Atlassian产品的可靠性和可用性十分重要。 应用流动集群时,负载均衡器能够主动将流量从故障节点重定向到集群中的流动节点,这意味着用户能够无间断地拜访产品。此外,一些针对于某些产品的个性,如Jira Software和Jira Service Management中的零停机降级以及Confluence中的只读模式,确保了对产品的统一拜访,即便您正在进行打算中的降级。 您是否正在(或打算)在Atlassian产品中增加新的用户和团队? 最初,如果您的企业正在不断扩大规模,并须要为Atlassian产品减少更多用户,那么扩大本地部署的数据中心版是一项疾速而简略的工作。您能够随时向现有集群中增加新节点,而无需停机工夫,从而轻松地扩大产品并将其交付给须要应用的团队和集体。 保障平安和合规 在当今的商业环境中,安全性对所有企业来说都至关重要的,但对于那些身处受特定法规束缚行业的企业来说,安全性和合规性则更是不能被忽视的问题。尽管本地部署的数据中心版曾经提供了帮忙您保护产品安全且合规的性能,但Atlassian仍在持续投资新性能,以一直晋升安全性和合规性。 确保只有适当的人员可能拜访您的Atlassian产品是解决平安难题的要害之一。为此,Atlassian反对SAML和OpenID Connect,以满足您的身份验证规范,并且能够轻松地配置,使受权新用户变成无缝的体验。 除了牢靠的安全性,证实合规对于受监管行业中的企业也至关重要。数据中心产品使您尽可能轻松地恪守并适应一直倒退的法规环境。通过数据中心产品中的高级审核性能,您能够获取与安全性相干的数字记录,这不仅能帮忙企业进步安全性,还能够证实合规性并进步可见性。 利用基础架构的灵活性 古代企业都须要具备软件方面的灵活性,因为每个企业都有其独特的需要,没有一种通用的解决方案实用于所有企业。Atlassian理解这一点,并提供了基础架构的灵活性,让您能够自行决定如何托管本地部署的数据中心产品。 除了在本人的硬件上部署数据中心产品,您还能够利用云计算的劣势,应用AWS、Azure等IaaS供应商来部署Atlassian产品。这样,您就能够在节约工夫和金钱的同时更轻松地扩大数据中心产品。

April 10, 2023 · 1 min · jiezi

关于server:Serverless-工程实践-零基础上手-Knative-应用

Knative简介Knative是一款基于Kubernetes的Serverless框架。其指标是制订云原生、跨平台的Serverless编排规范。Knative通过整合容器构建(或者函数)、工作负载治理(动静扩缩)以及事件模型这三者实现其Serverless规范。在Knative体系架构下,各角色的协作关系如下图所示。 开发者是指Serverless服务的开发人员能够间接应用原生Kubernetes API基于Knative部署Serverless服务。贡献者次要是指社区的贡献者。Knative能够被集成到反对的环境中,例如云厂商或者企业外部。目前,Knative是基于Kubernetes来实现的,所以能够认为有Kubernetes的中央就能够部署Knative。用户指终端用户,其通过Istio网关拜访服务或者事件零碎触发Knative中的Serverless服务。作为一个通用的Serverless框架,Knative由3个外围组件组成。Tekton:提供从源码到镜像的通用构建能力。Tekton组件次要负责从代码仓库获取源码并编译成镜像,推送到镜像仓库。所有这些操作都是在Kubernetes Pod中进行的。Eventing:提供事件的接入、触发等一整套事件治理能力。Eventing组件针对Serverless事件驱动模式做了一套残缺的设计,包含内部事件源的接入、事件注册、订阅以及事件过滤等性能。事件模型能够无效地解耦生产者和消费者的依赖关系。生产者能够在消费者启动之前生成事件,消费者也能够在生产者启动之前监听事件。 在Knative体系架构下各角色的协作关系 Serving:治理Serverless工作负载,能够和事件很好地联合,并且提供了基于申请驱动的主动伸缩能力,而且在没有服务须要解决的时候能够缩容到零。Serving组件的职责是管理工作负载以对外提供服务。Serving组件最重要的个性就是主动伸缩的能力。目前,其伸缩边界无限度。Serving还具备灰度公布能力。Knative部署本节将会以在阿里云部署Kantive服务为例,具体阐明如何部署Knative相干服务。首先,登录到容器服务治理控制台,如图所示为阿里云容器服务治理控制台。如没有集群,能够先抉择创立集群,如图所示为配置与创立集群。 创立集群比拟迟缓,急躁期待集群创立实现,胜利之后如示意图所示。进入集群之后,抉择左侧的“利用”,找到“Knative”并点击“一键部署”,如图所示。稍等片刻,Knative装置实现之后,能够看到外围组件曾经处于“已部署”状态,如图所示。至此,咱们实现了Knative的部署。 体验测试首先须要创立一个EIP,并将其绑定到API Server服务上,如图所示为API Server绑定EIP。实现之后,进行Serverless利用的测试。抉择利用中的“Kantive利用”,并且在服务治理中抉择“应用模板创立”,如图疾速创立示例利用所示。创立实现之后,能够看到控制台曾经呈现一个Serverless利用,如图所示为示例利用创立胜利。此时,咱们能够点击利用名称查看该利用的详情,如图所示为查看示例利用详情。为了便于测试,能够在本地设置Host:101.200.87.158 helloworld-go.default.example.com设置实现之后,在浏览器中关上零碎调配的域名,能够看到曾经输入预期的后果,如图所示:浏览器测试示例利用。至此,咱们实现了一个基于Knative的Serverless利用的部署和测试。此时,咱们还能够通过CloudShell进行集群的治理等。在集群列表页面,抉择通过CloudShell进行治理,如图集群治理列表所示。通过CloudShell治理已创立的集群,如图CloudShell窗口。执行指令: kubectl get knative能够看到,刚部署的Knative利用,如图CloudShell查看Knative利用所示。

October 28, 2021 · 1 min · jiezi

MongoDB-BI-Connector-实战指南

MongoDB 使用 BI Connector 来支持 BI 组件直接使用 SQL 或 ODBC 数据源方式直接访问 MongoDB,在早期 MongoDB 直接使用 Postgresql FDW 来实现 SQL 到 MQL 的转换,后来实现更加轻量级的 mongosqld 来支持 BI 工具的连接。 安装 BI Connector参考 Install BI Connector wget https://info-mongodb-com.s3.amazonaws.com/mongodb-bi/v2/mongodb-bi-linux-x86_64-rhel70-v2.12.0.tgz$tar xvf mongodb-bi-linux-x86_64-rhel70-v2.12.0.tgzmongodb-bi-linux-x86_64-rhel70-v2.12.0/LICENSEmongodb-bi-linux-x86_64-rhel70-v2.12.0/READMEmongodb-bi-linux-x86_64-rhel70-v2.12.0/THIRD-PARTY-NOTICESmongodb-bi-linux-x86_64-rhel70-v2.12.0/example-mongosqld-config.ymlmongodb-bi-linux-x86_64-rhel70-v2.12.0/bin/mongosqldmongodb-bi-linux-x86_64-rhel70-v2.12.0/bin/mongodrdlmongodb-bi-linux-x86_64-rhel70-v2.12.0/bin/mongotranslatemongosqld 接受 SQL 查询,并将请求发到 MongoDB Server,是 BI Connector 的核心mongodrdl 工具生成数据库 schema 信息,用于服务 BI SQL 查询mongotranslate 工具将 SQL 查询转换为 MongoDB Aggregation Pipeline启动 mongosqld参考 Lauch BI Connector mongodb-bi-linux-x86_64-rhel70-v2.12.0/bin/mongosqld --addr 127.0.0.1:3307 --mongo-uri 127.0.0.1:9555--addr 指定 mongosqld 监听的地址--mongo-uri 指定连接的 MongoDB Server 地址默认情况下,mongosqld 自动会分析目标 MongoDB Server 里数据的 Schema,并缓存在内存,我们也可以直接在启动时指定 schema 影射关系。schema 也可以直接 mongodrdl 工具来生成,指定集合,可以将集合里的字段 shema 信息导出。 ...

October 8, 2019 · 2 min · jiezi

如何使用confdACM管理Nginx配置

Nginx 作为优秀的开源软件,凭借其高性能高并发等特点,常常作为web和反向代理服务部署在生产环境中。但是当 Nginx 的规模较大时, Nginx 的运维成本也是不断上升。本文介绍如何通过confd+ACM来管理 Nginx 配置,通过集中式的配置管理方式解决 Nginx 的大规模运维问题,运维和开发人员不用登陆到 Nginx 机器上,只需要配置好confd,然后在ACM上操作就可以动态修改 Nginx 的配置参数。 准备工作在操作本文的示例之前需要配置好开通ACM和对confd的使用有基本概念,ACM的开通及其基本使用可以参考:这里confd的基本使用可以参考:这里 Nginx 在日常开发中使用得比较多的功能是负载均衡、限流、缓存等, Nginx 的使用和安装可以在网上查阅相关资料。本文结合负载均衡和限流功能讲解如何使用confd+ACM实现 Nginx 的大规模运维操作。 创建confd配置文件创建confd所需的toml格式配置文件 vim /etc/confd/conf.d/myapp.tomlcheck_cmd用于检验 Nginx 配置的正确性,当src配置错误则不会覆盖 Nginx 配置reload_cmd用于reload Nginx 配置 [template]src = " Nginx .conf.tmpl"dest = "/usr/local/ Nginx /conf/ Nginx .conf"keys = ["/myapp/ Nginx /conf",]check_cmd = "/usr/local/ Nginx /sbin/ Nginx -t -c {{.src}}"reload_cmd = "/usr/local/ Nginx /sbin/ Nginx -s reload"创建模版文件vim /etc/confd/templates/ Nginx .conf.tmplgetv从ACM中获取对应dataId的配置,/myapp/ Nginx /conf对应的dataId为myapp. Nginx .conf,配置格式为json格式,模版文件包含了 Nginx 的upstream、限流、黑白名单配置内容,通过json指令解析配置文件。upstream后端ip通过从ACM的配置的backends数组中获取,同样地,白名单和黑名单ip分别存储在whiteList和blackList的数组中,限流的速率和并发数通过rateLimit和connectionLimit设置 ...

July 12, 2019 · 2 min · jiezi

K8S环境中NAS卷添加noresvport方法

通过K8S使用NAS卷,请区分以下场景: 静态存储卷: 使用阿里云ACK,PV、PVC方式,nfs驱动;使用阿里云ACK,PV、PVC方式,Flexvolume驱动;使用阿里云ACK,Volume方式,nfs驱动;使用阿里云ACK,Volume方式,Flexvolume驱动;自建K8S,PV、PVC方式,nfs驱动;自建K8S,Volume方式,nfs驱动;动态存储卷: 使用阿里云ACK使用自建K8S静态卷-使用阿里云Kubernetes(ACK)时1. 使用PV、PVC方式(nfs驱动)首先确认当前的挂载是否配置了noresvport参数,参考NAS团队提供的方式; 例如当前的pv如下面yaml: apiVersion: v1kind: PersistentVolumemetadata: name: pv-nasspec: accessModes: - ReadWriteOnce capacity: storage: 2Gi mountOptions: - vers=3 nfs: path: /default server: 2564f49129-ggu23.cn-shenzhen.nas.aliyuncs.com persistentVolumeReclaimPolicy: Retain编辑PV: kubectl edit pv pv-nas更新mountOptions:mountOptions: - vers=4.0 - noresvport或者: mountOptions: - vers=3 - nolock,tcp,noresvport重启使用这个pv的pod; 需要注意: 由于一个节点上,如果已经有某个挂载点挂载在一个目录下了,其他的挂载(相同挂载点)即使配置了noresvport参数,还是会follow以前的挂载参数。即noresvport不生效;解决方法:方法1:修改pv参数后,把所有使用这个挂载点的pod掉离这个节点,然后再调回来。方法2:使用新的挂载点创建新的pv使用(一个nas文件系统可以有2个挂载点); 示例方法1: 集群中有2个worker节点,部署一个deploy包含3个Pod;# kubectl get node | grep -v masterNAME STATUS ROLES AGE VERSIONcn-shenzhen.i-wz9c9m0m4oldr6mt89rd Ready <none> 55d v1.12.6-aliyun.1cn-shenzhen.i-wz9gvy73m4qyk03xzg1y Ready <none> 60d v1.12.6-aliyun.1# kubectl get podNAME READY STATUS RESTARTS AGEnas-static-784496fbb9-cqr97 1/1 Running 0 63mnas-static-784496fbb9-gljbq 1/1 Running 0 63mnas-static-784496fbb9-ngzkq 1/1 Running 0 63m编辑pv,添加- nolock,tcp,noresvport Options;编辑deploy,把这个deploy的pod都调度到节点:cn-shenzhen.i-wz9c9m0m4oldr6mt89rd上;> 在deploy中添加 nodeName: cn-shenzhen.i-wz9c9m0m4oldr6mt89rd> 如果您的集群节点较多,可以给一批节点添加label,然后通过nodeSelector把pod调度到这写节点;> 参考:https://kubernetes.io/zh/docs/tasks/configure-pod-container/assign-pods-nodes/注意:如果您用的时候statefulset的应用,需要把updateStrategy.type配置为RollingUpdate;然后再把pod调度到其他节点:cn-shenzhen.i-wz9gvy73m4qyk03xzg1y到节点cn-shenzhen.i-wz9gvy73m4qyk03xzg1y 上验证noresport,已经生效。2564f49129-ggu23.cn-shenzhen.nas.aliyuncs.com:/default on /var/lib/kubelet/pods/aa79e380-9bdb-11e9-a545-00163e0eff42/volumes/kubernetes.io~nfs/pv-nas type nfs (rw,relatime,vers=3,rsize=1048576,wsize=1048576,namlen=255,hard,nolock,noresvport,proto=tcp,timeo=600,retrans=2,sec=sys,mountaddr=192.168.0.11,mountvers=3,mountport=4002,mountproto=tcp,local_lock=all,addr=192.168.0.11)最后,由于当前使用nas的pod是有nodeName标签的,可以编辑deploy,把nodeName(nodeSelector)去掉。2. 使用PV、PVC方式(Flexvolume驱动)首先确认当前的挂载是否配置了noresvport参数,参考NAS团队提供的方式; ...

July 3, 2019 · 2 min · jiezi

Zinx第二章初识Zinx框架Golang轻量级并发服务器框架

【Zinx教程目录】Zinx源代码https://github.com/aceld/zinx (请拷贝网址,在浏览器打开[简书不让自动跳转])完整教程电子版(在线高清)-下载Zinx框架视频教程(框架篇)(完整版下载)链接在下面正文 Zinx框架视频教程(应用篇)(完整版下载)链接在下面正文 Zinx开发API文档Zinx第一章-引言Zinx第二章-初识Zinx框架Zinx第三章-基础路由模块Zinx第四章-全局配置Zinx第五章-消息封装 Zinx第六章-多路由模式 Zinx第七章-读写分离模型 Zinx第八章-消息队列及多任务 Zinx第九章-链接管理 Zinx第十章-连接属性设置 【Zinx应用案例-MMO多人在线游戏】(1)案例介绍(2)AOI兴趣点算法(3)数据传输协议protocol buffer(4)Proto3协议定义(5)构建项目及用户上线(6)世界聊天(7)上线位置信息同步(8)移动位置与AOI广播(9)玩家下线(10)模拟客户端AI模块 二、初识Zinx框架 这里先看一下Zinx最简单的Server雏形。 1. Zinx-V0.1-基础Server 为了更好的看到Zinx框架,首先Zinx构建Zinx的最基本的两个模块ziface 和znet。 ziface主要是存放一些Zinx框架的全部模块的抽象层接口类,Zinx框架的最基本的是服务类接口iserver,定义在ziface模块中。 znet模块是zinx框架中网络相关功能的实现,所有网络相关模块都会定义在znet模块中。 1.1 Zinx-V0.1 代码实现A) 创建zinx框架 在$GOPATH/src下创建zinx文件夹 B) 创建ziface、znet模块 在zinx/下 创建ziface、znet文件夹, 使当前的文件路径如下: └── zinx ├── ziface │   └── └── znet ├── C) 在ziface下创建服务模块抽象层iserver.gozinx/ziface/iserver.go package ziface//定义服务器接口type IServer interface{ //启动服务器方法 Start() //停止服务器方法 Stop() //开启业务服务方法 Serve()}D) 在znet下实现服务模块server.gopackage znetimport ( "fmt" "net" "time" "zinx/ziface")//iServer 接口实现,定义一个Server服务类type Server struct { //服务器的名称 Name string //tcp4 or other IPVersion string //服务绑定的IP地址 IP string //服务绑定的端口 Port int}//============== 实现 ziface.IServer 里的全部接口方法 ========//开启网络服务func (s *Server) Start() { fmt.Printf("[START] Server listenner at IP: %s, Port %d, is starting\n", s.IP, s.Port) //开启一个go去做服务端Linster业务 go func() { //1 获取一个TCP的Addr addr, err := net.ResolveTCPAddr(s.IPVersion, fmt.Sprintf("%s:%d", s.IP, s.Port)) if err != nil { fmt.Println("resolve tcp addr err: ", err) return } //2 监听服务器地址 listenner, err:= net.ListenTCP(s.IPVersion, addr) if err != nil { fmt.Println("listen", s.IPVersion, "err", err) return } //已经监听成功 fmt.Println("start Zinx server ", s.Name, " succ, now listenning...") //3 启动server网络连接业务 for { //3.1 阻塞等待客户端建立连接请求 conn, err := listenner.AcceptTCP() if err != nil { fmt.Println("Accept err ", err) continue } //3.2 TODO Server.Start() 设置服务器最大连接控制,如果超过最大连接,那么则关闭此新的连接 //3.3 TODO Server.Start() 处理该新连接请求的 业务 方法, 此时应该有 handler 和 conn是绑定的 //我们这里暂时做一个最大512字节的回显服务 go func () { //不断的循环从客户端获取数据 for { buf := make([]byte, 512) cnt, err := conn.Read(buf) if err != nil { fmt.Println("recv buf err ", err) continue } //回显 if _, err := conn.Write(buf[:cnt]); err !=nil { fmt.Println("write back buf err ", err) continue } } }() } }()}func (s *Server) Stop() { fmt.Println("[STOP] Zinx server , name " , s.Name) //TODO Server.Stop() 将其他需要清理的连接信息或者其他信息 也要一并停止或者清理}func (s *Server) Serve() { s.Start() //TODO Server.Serve() 是否在启动服务的时候 还要处理其他的事情呢 可以在这里添加 //阻塞,否则主Go退出, listenner的go将会退出 for { time.Sleep(10*time.Second) }}/* 创建一个服务器句柄 */func NewServer (name string) ziface.IServer { s:= &Server { Name :name, IPVersion:"tcp4", IP:"0.0.0.0", Port:7777, } return s}好了,以上我们已经完成了Zinx-V0.1的基本雏形了,虽然只是一个基本的回写客户端数据(我们之后会自定义处理客户端业务方法),那么接下来我们就应该测试我们当前的zinx-V0.1是否可以使用了。 ...

July 3, 2019 · 6 min · jiezi

ERROR-node-with-name-rabbit-already-running-on-localhost

rabbitmq-server使用rabbitmq-server启动RabbitMQ后,进行start、restart或stop都会提示错误ERROR: node with name "rabbit" already running on "localhost",原因是RabbitMQ已在localhost里运行了,但是停止不了。解决记录如下: zhangguoyedeMacBook-Pro:~ zhangguoye$ rabbitmq-serverERROR: node with name "rabbit" already running on "localhost"zhangguoyedeMacBook-Pro:~ zhangguoye$ ps aux|grep epmdzhangguoye 35736 0.0 0.0 4328468 676 ?? S 四03下午 0:00.08 /usr/local/Cellar/erlang/22.0.2/lib/erlang/erts-10.4.1/bin/epmd -daemonzhangguoye 67752 0.0 0.0 4268036 804 s009 S+ 10:05上午 0:00.00 grep epmdzhangguoyedeMacBook-Pro:~ zhangguoye$ ps aux|grep erlzhangguoye 65864 0.1 0.5 5517096 84836 s009 S 10:00上午 0:09.27 /usr/local/Cellar/erlang/22.0.2/lib/erlang/erts-10.4.1/bin/beam.smp -W w -A 128 -MBas ageffcbf -MHas ageffcbf -MBlmbcs 512 -MHlmbcs 512 -MMmcs 30 -P 1048576 -t 5000000 -stbt db -zdbbl 128000 -K true -B i -- -root /usr/local/Cellar/erlang/22.0.2/lib/erlang -progname erl -- -home /Users/zhangguoye -- -pa /usr/local/Cellar/rabbitmq/3.7.15/ebin -noshell -noinput -s rabbit boot -sname rabbit@localhost -boot /usr/local/opt/erlang/lib/erlang/bin/start_clean -kernel inet_default_connect_options [{nodelay,true}] -rabbit tcp_listeners [{"127.0.0.1",5672}] -sasl errlog_type error -sasl sasl_error_logger false -rabbit lager_log_root "/usr/local/var/log/rabbitmq" -rabbit lager_default_file "/usr/local/var/log/rabbitmq/rabbit@localhost.log" -rabbit lager_upgrade_file "/usr/local/var/log/rabbitmq/rabbit@localhost_upgrade.log" -rabbit enabled_plugins_file "/usr/local/etc/rabbitmq/enabled_plugins" -rabbit plugins_dir "/usr/local/Cellar/rabbitmq/3.7.15/plugins" -rabbit plugins_expand_dir "/usr/local/var/lib/rabbitmq/mnesia/rabbit@localhost-plugins-expand" -os_mon start_cpu_sup false -os_mon start_disksup false -os_mon start_memsup false -mnesia dir "/usr/local/var/lib/rabbitmq/mnesia/rabbit@localhost" -kernel inet_dist_listen_min 25672 -kernel inet_dist_listen_max 25672zhangguoye 35736 0.0 0.0 4328468 688 ?? S 四03下午 0:00.08 /usr/local/Cellar/erlang/22.0.2/lib/erlang/erts-10.4.1/bin/epmd -daemonzhangguoye 68953 0.0 0.0 4268036 804 s009 S+ 10:11上午 0:00.00 grep erlzhangguoye 65877 0.0 0.0 4270068 828 ?? Ss 10:00上午 0:00.36 erl_child_setup 7168zhangguoyedeMacBook-Pro:~ zhangguoye$ kill -9 65864zhangguoyedeMacBook-Pro:~ zhangguoye$ rabbitmq-server ## ## ## ## RabbitMQ 3.7.15. Copyright (C) 2007-2019 Pivotal Software, Inc. ########## Licensed under the MPL. See https://www.rabbitmq.com/ ###### ## ########## Logs: /usr/local/var/log/rabbitmq/rabbit@localhost.log /usr/local/var/log/rabbitmq/rabbit@localhost_upgrade.log Starting broker... completed with 6 plugins.brew管理RabbitMQ使用mac的用户可以直接使用brew进行安装与管理RabbitMQ1. 安装Homebrew安装:https://www.rabbitmq.com/inst... ...

June 11, 2019 · 2 min · jiezi

Schedulerx20分布式计算原理最佳实践

1. 前言Schedulerx2.0的客户端提供分布式执行、多种任务类型、统一日志等框架,用户只要依赖schedulerx-worker这个jar包,通过schedulerx2.0提供的编程模型,简单几行代码就能实现一套高可靠可运维的分布式执行引擎。 这篇文章重点是介绍基于schedulerx2.0的分布式执行引擎原理和最佳实践,相信看完这篇文章,大家都能写出高效率的分布式作业,说不定速度能提升好几倍:) 2. 可扩展的执行引擎Worker总体架构参考Yarn的架构,分为TaskMaster, Container, Processor三层: TaskMaster:类似于yarn的AppMaster,支持可扩展的分布式执行框架,进行整个jobInstance的生命周期管理、container的资源管理,同时还有failover等能力。默认实现StandaloneTaskMaster(单机执行),BroadcastTaskMaster(广播执行),MapTaskMaster(并行计算、内存网格、网格计算),MapReduceTaskMaster(并行计算、内存网格、网格计算)。Container:执行业务逻辑的容器框架,支持线程/进程/docker/actor等。Processor:业务逻辑框架,不同的processor表示不同的任务类型。以MapTaskMaster为例,大概的原理如下图所示: 3. 分布式编程模型之Map模型Schedulerx2.0提供了多种分布式编程模型,这篇文章主要介绍Map模型(之后的文章还会介绍MapReduce模型,适用更多的业务场景),简单几行代码就可以将海量数据分布式到多台机器上进行分布式跑批,非常简单易用。 针对不同的跑批场景,map模型作业还提供了并行计算、内存网格、网格计算三种执行方式: 并行计算:子任务300以下,有子任务列表。内存网格:子任务5W以下,无子任务列表,速度快。网格计算:子任务100W以下,无子任务列表。4. 并行计算原理因为并行任务具有子任务列表: 如上图,子任务列表可以看到每个子任务的状态、机器,还有重跑、查看日志等操作。 因为并行计算要做到子任务级别的可视化,并且worker挂了、重启还能支持手动重跑,就需要把task持久化到server端: 如上图所示: server触发jobInstance到某个worker,选中为master。MapTaskMaster选择某个worker执行root任务,当执行map方法时,会回调MapTaskMaster。MapTaskMaster收到map方法,会把task持久化到server端。同时,MapTaskMaster还有个pull线程,不停拉取INIT状态的task,并派发给其他worker执行。5. 网格计算原理网格计算要支持百万级别的task,如果所有任务都往server回写,server肯定扛不住,所以网格计算的存储实际上是分布式在用户自己的机器上的: 如上图所示: server触发jobInstance到某个worker,选中为master。MapTaskMaster选择某个worker执行root任务,当执行map方法时,会回调MapTaskMaster。MapTaskMaster收到map方法,会把task持久化到本地h2数据库。同时,MapTaskMaster还有个pull线程,不停拉取INIT状态的task,并派发给其他worker执行。6. 最佳实践6.1 需求 举个例子: 读取A表中status=0的数据。处理这些数据,插入B表。把A表中处理过的数据的修改status=1。数据量有4亿+,希望缩短时间。6.2 反面案例 我们先看下如下代码是否有问题? public class ScanSingleTableProcessor extends MapJobProcessor { private static int pageSize = 1000; @Override public ProcessResult process(JobContext context) { String taskName = context.getTaskName(); Object task = context.getTask(); if (WorkerConstants.MAP_TASK_ROOT_NAME.equals(taskName)) { int recordCount = queryRecordCount(); int pageAmount = recordCount / pageSize;//计算分页数量 for(int i = 0 ; i < pageAmount ; i ++) { List<Record> recordList = queryRecord(i);//根据分页查询一页数据 map(recordList, "record记录");//把子任务分发出去并行处理 } return new ProcessResult(true);//true表示执行成功,false表示失败 } else if ("record记录".equals(taskName)) { //TODO return new ProcessResult(true); } return new ProcessResult(false); }}如上面的代码所示,在root任务中,会把数据库所有记录读取出来,每一行就是一个Record,然后分发出去,分布式到不同的worker上去执行。逻辑是没有问题的,但是实际上性能非常的差。结合网格计算原理,我们把上面的代码绘制成下面这幅图: ...

May 31, 2019 · 2 min · jiezi

Nginx-静态文件服务配置及优化

原文链接: 何晓东 博客 根目录和索引文件root 指令指定将用于搜索文件的根目录。 为了获取所请求文件的路径,NGINX 将请求 URI 附加到 root 指令指定的路径。该指令可以放在 http {},server {} 或 location {} 上下文中的任何级别。在下面的示例中,为虚拟服务器定义了 root 指令。 它适用于未包含根指令的所有location {} 块,以显式重新定义根: server { root /www/data; location / { } location /images/ { } location ~ \.(mp3|mp4) { root /www/media; }}在这里,NGINX 针对 /images/ 开头的 URI 将在文件系统的 /www/ data/images/ 目录中搜索相应文件。 如果 URI 以 .mp3 或 .mp4 扩展名结尾,则 NGINX 会在 /www/media/ 目录中搜索该文件,因为它是在匹配的位置块中定义的。 如果请求以 / 结尾,则 NGINX 将其视为对目录的请求,并尝试在目录中查找索引文件。index 指令定义索引文件的名称(默认值为 index.html)。要继续该示例,如果请求 URI 是 /images/some/path/,则 NGINX 会返回文件 /www/data/images/some/path/index.html(如果存在)。如果没有,NGINX 默认返回 HTTP 404 错误(未找到)。要配置 NGINX 以返回自动生成的目录列表,请在 autoindex 指令中包含 on 参数: ...

May 23, 2019 · 2 min · jiezi

Apache-Cassandra-static-column-介绍与实战

假设我们有这样的场景:我们想在 Cassandra 中使用一张表记录用户基本信息(比如 email、密码等)以及用户状态更新。我们知道,用户的基本信息一般很少会变动,但是状态会经常变化,如果每次状态更新都把用户基本信息都加进去,势必会让费大量的存储空间。为了解决这种问题,Cassandra 引入了 static column。同一个 partition key 中被声明为 static 的列只有一个值的,也就是只存储一份。 定义 static column在表中将某个列定义为 STATIC 很简单,只需要在列的最后面加上 STATIC 关键字,具体如下: CREATE TABLE "iteblog_users_with_status_updates" ( "username" text, "id" timeuuid, "email" text STATIC, "encrypted_password" blob STATIC, "body" text, PRIMARY KEY ("username", "id"));iteblog_users_with_status_updates 表中我们将 email 和 encrypted_password 两个字段设置为 STATIC 了,这意味着同一个 username 只会有一个 email 和 encrypted_password 。 注意,不是任何表都支持给列加上 STATIC 关键字的,静态列有以下限制。 1、如果表没有定义 Clustering columns(又称 Clustering key),这种情况是不能添加静态列的。如下: cqlsh:iteblog_keyspace> CREATE TABLE "iteblog_users_with_status_updates_invalid" ( ... "username" text, ... "id" timeuuid, ... "email" text STATIC, ... "encrypted_password" blob STATIC, ... "body" text, ... PRIMARY KEY ("username") ... );InvalidRequest: Error from server: code=2200 [Invalid query] message="Static columns are only useful (and thus allowed) if the table has at least one clustering column"iteblog_users_with_status_updates_invalid 表只有 PRIMARY KEY,没有定义 clustering column,不支持创建 Static columns。这是因为静态列在同一个 partition key 存在多行的情况下才能达到最优情况,而且行数越多效果也好。但是如果没有定义 clustering column,相同 PRIMARY KEY 的数据在同一个分区里面只存在一行数据,本质上就是静态的,所以没必要支持静态列。 ...

April 30, 2019 · 3 min · jiezi

一致性协议浅析:从逻辑时钟到Raft

前言春节在家闲着没事看了几篇论文,把一致性协议的几篇论文都过了一遍。在看这些论文之前,我一直有一些疑惑,比如同样是有Leader和两阶段提交,Zookeeper的ZAB协议和Raft有什么不同,Paxos协议到底要怎样才能用在实际工程中,这些问题我都在这些论文中找到了答案。接下来,我将尝试以自己的语言给大家讲讲这些协议,使大家能够理解这些算法。同时,我自己也有些疑问,我会在我的阐述中提出,也欢迎大家一起讨论。水平有限,文中难免会有一些纰漏门也欢迎大家指出。逻辑时钟逻辑时钟其实算不上是一个一致性协议,它是Lamport大神在1987年就提出来的一个想法,用来解决分布式系统中,不同的机器时钟不一致可能带来的问题。在单机系统中,我们用机器的时间来标识事件,就可以非常清晰地知道两个不同事件的发生次序。但是在分布式系统中,由于每台机器的时间可能存在误差,无法通过物理时钟来准确分辨两个事件发生的先后顺序。但实际上,在分布式系统中,只有两个发生关联的事件,我们才会去关心两者的先来后到关系。比如说两个事务,一个修改了rowa,一个修改了rowb,他们两个谁先发生,谁后发生,其实我们并不关心。那所谓逻辑时钟,就是用来定义两个关联事件的发生次序,即‘happens before’。而对于不关联的事件,逻辑时钟并不能决定其先后,所以说这种‘happens before’的关系,是一种偏序关系。图和例子来自于这篇博客此图中,箭头表示进程间通讯,ABC分别代表分布式系统中的三个进程。逻辑时钟的算法其实很简单:每个事件对应一个Lamport时间戳,初始值为0如果事件在节点内发生,时间戳加1如果事件属于发送事件,时间戳加1并在消息中带上该时间戳如果事件属于接收事件,时间戳 = Max(本地时间戳,消息中的时间戳) + 1这样,所有关联的发送接收事件,我们都能保证发送事件的时间戳小于接收事件。如果两个事件之间没有关联,比如说A3和B5,他们的逻辑时间一样。正是由于他们没有关系,我们可以随意约定他们之间的发生顺序。比如说我们规定,当Lamport时间戳一样时,A进程的事件发生早于B进程早于C进程,这样我们可以得出A3 ‘happens before’ B5。而实际在物理世界中,明显B5是要早于A3发生的,但这都没有关系。逻辑时钟貌似目前并没有被广泛的应用,除了DynamoDB使用了vector clock来解决多版本的先后问题(如果有其他实际应用的话请指出,可能是我孤陋寡闻了),Google的Spanner 也是采用物理的原子时钟来解决时钟问题。但是从Larmport大师的逻辑时钟算法上,已经可以看到一些一致性协议的影子。Replicated State Machine说到一致性协议,我们通常就会讲到复制状态机。因为通常我们会用复制状态机加上一致性协议算法来解决分布式系统中的高可用和容错。许多分布式系统,都是采用复制状态机来进行副本之间的数据同步,比如HDFS,Chubby和Zookeeper。所谓复制状态机,就是在分布式系统的每一个实例副本中,都维持一个持久化的日志,然后用一定的一致性协议算法,保证每个实例的这个log都完全保持一致,这样,实例内部的状态机按照日志的顺序回放日志中的每一条命令,这样客户端来读时,在每个副本上都能读到一样的数据。复制状态机的核心就是图中 的Consensus模块,即今天我们要讨论的Paxos,ZAB,Raft等一致性协议算法。PaxosPaxos是Lamport大神在90年代提出的一致性协议算法,大家一直都觉得难懂,所以Lamport在2001又发表了一篇新的论文《Paxos made simple》,在文中他自己说Paxos是世界上最简单的一致性算法,非常容易懂……但是业界还是一致认为Paxos比较难以理解。在我看过Lamport大神的论文后,我觉得,除去复杂的正确性论证过程,Paxos协议本身还是比较好理解的。但是,Paxos协议还是过于理论,离具体的工程实践还有太远的距离。我一开始看Paxos协议的时候也是一头雾水,看来看去发现Paxos协议只是为了单次事件答成一致,而且答成一致后的值无法再被修改,怎么用Paxos去实现复制状态机呢?另外,Paxos协议答成一致的值只有Propose和部分follower知道,这协议到底怎么用……但是,如果你只是把Paxos协议当做一个理论去看,而不是考虑实际工程上会遇到什么问题的话,会容易理解的多。Lamport的论文中对StateMachine的应用只有一个大概的想法,并没有具体的实现逻辑,想要直接把Paxos放到复制状态机里使用是不可能的,得在Paxos上补充很多的东西。这些是为什么Paxos有这么多的变种。Basic-PaxosBasic-Paxos即Lamport最初提出的Paxos算法,其实很简单,用三言两语就可以讲完,下面我尝试着用我自己的语言描述下Paxos协议,然后会举出一个例子。要理解Paxos,只要记住一点就好了,Paxos只能为一个值形成共识,一旦Propose被确定,之后值永远不会变,也就是说整个Paxos Group只会接受一个提案(或者说接受多个提案,但这些提案的值都一样)。至于怎么才能接受多个值来形成复制状态机,大家可以看下一节Multi-Paxos.Paxos协议中是没有Leader这个概念的,除去Learner(只是学习Propose的结果,我们可以不去讨论这个角色),只有Proposer和Acceptor。Paxos并且允许多个Proposer同时提案。Proposer要提出一个值让所有Acceptor答成一个共识。首先是Prepare阶段,Proposer会给出一个ProposeID n(注意,此阶段Proposer不会把值传给Acceptor)给每个Acceptor,如果某个Acceptor发现自己从来没有接收过大于等于n的Proposer,则会回复Proposer,同时承诺不再接收ProposeID小于等于n的提议的Prepare。如果这个Acceptor已经承诺过比n更大的propose,则不会回复Proposer。如果Acceptor之前已经Accept了(完成了第二个阶段)一个小于n的Propose,则会把这个Propose的值返回给Propose,否则会返回一个null值。当Proposer收到大于半数的Acceptor的回复后,就可以开始第二阶段accept阶段。但是这个阶段Propose能够提出的值是受限的,只有它收到的回复中不含有之前Propose的值,他才能自由提出一个新的value,否则只能是用回复中Propose最大的值做为提议的值。Proposer用这个值和ProposeID n对每个Acceptor发起Accept请求。也就是说就算Proposer之前已经得到过acceptor的承诺,但是在accept发起之前,Acceptor可能给了proposeID更高的Propose承诺,导致accept失败。也就是说由于有多个Proposer的存在,虽然第一阶段成功,第二阶段仍然可能会被拒绝掉。下面我举一个例子,这个例子来源于这篇博客假设有Server1,Server2, Server3三个服务器,他们都想通过Paxos协议,让所有人答成一致他们是leader,这些Server都是Proposer角色,他们的提案的值就是他们自己server的名字。他们要获取Acceptor1~3这三个成员同意。首先Server2发起一个提案【1】,也就是说ProposeID为1,接下来Server1发起来一个提案【2】,Server3发起一个提案【3】.首先是Prepare阶段:假设这时Server1发送的消息先到达acceptor1和acceptor2,它们都没有接收过请求,所以接收该请求并返回【2,null】给Server1,同时承诺不再接受编号小于2的请求; 紧接着,Server2的消息到达acceptor2和acceptor3,acceptor3没有接受过请求,所以返回proposer2 【1,null】,并承诺不再接受编号小于1的消息。而acceptor2已经接受Server1的请求并承诺不再接收编号小于2的请求,所以acceptor2拒绝Server2的请求; 最后,Server3的消息到达acceptor2和acceptor3,它们都接受过提议,但编号3的消息大于acceptor2已接受的2和acceptor3已接受的1,所以他们都接受该提议,并返回Server3 【3,null】; 此时,Server2没有收到过半的回复,所以重新取得编号4,并发送给acceptor2和acceptor3,此时编号4大于它们已接受的提案编号3,所以接受该提案,并返回Server2 【4,null】。接下来进入Accept阶段,Server3收到半数以上(2个)的回复,并且返回的value为null,所以,Server3提交了【3,server3】的提案。 Server1在Prepare阶段也收到过半回复,返回的value为null,所以Server1提交了【2,server1】的提案。 Server2也收到过半回复,返回的value为null,所以Server2提交了【4,server2】的提案。 Acceptor1和acceptor2接收到Server1的提案【2,server1】,acceptor1通过该请求,acceptor2承诺不再接受编号小于4的提案,所以拒绝; Acceptor2和acceptor3接收到Server2的提案【4,server2】,都通过该提案; Acceptor2和acceptor3接收到Server3的提案【3,server3】,它们都承诺不再接受编号小于4的提案,所以都拒绝。 此时,过半的acceptor(acceptor2和acceptor3)都接受了提案【4,server2】,learner感知到提案的通过,learner开始学习提案,所以server2成为最终的leader。Multi-Paxos刚才我讲了,Paxos还过于理论,无法直接用到复制状态机中,总的来说,有以下几个原因Paxos只能确定一个值,无法用做Log的连续复制由于有多个Proposer,可能会出现活锁,如我在上面举的例子中,Server2的一共提了两次Propose才最终让提案通过,极端情况下,次数可能会更多提案的最终结果可能只有部分Acceptor知晓,没法达到复制状态机每个instance都必须有完全一致log的需求。那么其实Multi-Paxos,其实就是为了解决上述三个问题,使Paxos协议能够实际使用在状态机中。解决第一个问题其实很简单。为Log Entry每个index的值都是用一个独立的Paxos instance。解决第二个问题也很简答,让一个Paxos group中不要有多个Proposer,在写入时先用Paxos协议选出一个leader(如我上面的例子),然后之后只由这个leader做写入,就可以避免活锁问题。并且,有了单一的leader之后,我们还可以省略掉大部分的prepare过程。只需要在leader当选后做一次prepare,所有Acceptor都没有接受过其他Leader的prepare请求,那每次写入,都可以直接进行Accept,除非有Acceptor拒绝,这说明有新的leader在写入。为了解决第三个问题,Multi-Paxos给每个Server引入了一个firstUnchosenIndex,让leader能够向向每个Acceptor同步被选中的值。解决这些问题之后Paxos就可以用于实际工程了。Paxos到目前已经有了很多的补充和变种,实际上,之后我要讨论的ZAB也好,Raft也好,都可以看做是对Paxos的修改和变种,另外还有一句流传甚广的话,“世上只有一种一致性算法,那就是Paxos”。ZABZAB即Zookeeper Atomic BoardCast,是Zookeeper中使用的一致性协议。ZAB是Zookeeper的专用协议,与Zookeeper强绑定,并没有抽离成独立的库,因此它的应用也不是很广泛,仅限于Zookeeper。但ZAB协议的论文中对ZAB协议进行了详细的证明,证明ZAB协议是能够严格满足一致性要求的。ZAB随着Zookeeper诞生于2007年,此时Raft协议还没有发明,根据ZAB的论文,之所以Zookeeper没有直接使用Paxos而是自己造轮子,是因为他们认为Paxos并不能满足他们的要求。比如Paxos允许多个proposer,可能会造成客户端提交的多个命令没法按照FIFO次序执行。同时在恢复过程中,有一些follower的数据不全。这些断论都是基于最原始的Paxos协议的,实际上后来一些Paxos的变种,比如Multi-Paxos已经解决了这些问题。当然我们只能站在历史的角度去看待这个问题,由于当时的Paxos并不能很好的解决这些问题,因此Zookeeper的开发者创造了一个新的一致性协议ZAB。ZAB其实和后来的Raft非常像,有选主过程,有恢复过程,写入也是两阶段提交,先从leader发起一轮投票,获得超过半数同意后,再发起一次commit。ZAB中每个主的epoch number其实就相当于我接下来要讲的Raft中的term。只不过ZAB中把这个epoch number和transition number组成了一个zxid存在了每个entry中。ZAB在做log复制时,两阶段提交时,一个阶段是投票阶段,只要收到过半数的同意票就可以,这个阶段并不会真正把数据传输给follower,实际作用是保证当时有超过半数的机器是没有挂掉,或者在同一个网络分区里的。第二个阶段commit,才会把数据传输给每个follower,每个follower(包括leader)再把数据追加到log里,这次写操作就算完成。如果第一个阶段投票成功,第二个阶段有follower挂掉,也没有关系,重启后leader也会保证follower数据和leader对其。如果commit阶段leader挂掉,如果这次写操作已经在至少一个follower上commit了,那这个follower一定会被选为leader,因为他的zxid是最大的,那么他选为leader后,会让所有follower都commit这条消息。如果leader挂时没有follower commit这条消息,那么这个写入就当做没写完。由于只有在commit的时候才需要追加写日志,因此ZAB的log,只需要append-only的能力,就可以了。另外,ZAB支持在从replica里做stale read,如果要做强一致的读,可以用sync read,原理也是先发起一次虚拟的写操作,到不做任何写入,等这个操作完成后,本地也commit了这次sync操作,再在本地replica上读,能够保证读到sync这个时间点前所有的正确数据,而Raft所有的读和写都是经过主节点的RaftRaft是斯坦福大学在2014年提出的一种新的一致性协议。作者表示之所以要设计一种全新的一致性协议,是因为Paxos实在太难理解,而且Paxos只是一个理论,离实际的工程实现还有很远的路。因此作者狠狠地吐槽了Paxos一把:Paxos协议中,是不需要Leader的,每个Proposer都可以提出一个propose。相比Raft这种一开始设计时就把选主和协议达成一致分开相比,Paxos等于是把选主和propose阶段杂糅在了一起,造成Paxos比较难以理解。最原始的Paxos协议只是对单一的一次事件答成一致,一旦这个值被确定,就无法被更改,而在我们的现实生活中,包括我们数据库的一致性,都需要连续地对log entry的值答成一致,所以单单理解Paxos协议本身是不够的,我们还需要对Paxos协议进行改进和补充,才能真正把Paxos协议应用到工程中。而对Paxos协议的补充本身又非常复杂,而且虽然Paxos协议被Lamport证明过,而添加了这些补充后,这些基于Paxos的改进算法,如Multi-Paxos,又是未经证明的。第三个槽点是Paxos协议只提供了一个非常粗略的描述,导致后续每一个对Paxos的改进,以及使用Paxos的工程,如Google的Chubby,都是自己实现了一套工程来解决Paxos中的一些具体问题。而像Chubby的实现细节其实并没有公开。也就是说要想在自己的工程中使用Paxos,基本上每个人都需要自己定制和实现一套适合自己的Paxos协议。因此,Raft的作者在设计Raft的时候,有一个非常明确的目标,就是让这个协议能够更好的理解,在设计Raft的过程中,如果遇到有多种方案可以选择的,就选择更加容易理解的那个。作者举了一个例子。在Raft的选主阶段,本来可以给每个server附上一个id,大家都去投id最大的那个server做leader,会更快地达成一致(类似ZAB协议),但这个方案又增加了一个serverid的概念,同时在高id的server挂掉时,低id的server要想成为主必须有一个等待时间,影响可用性。因此Raft的选主使用了一个非常简单的方案:每个server都随机sleep一段时间,最早醒过来的server来发起一次投票,获取了大多数投票即可为主。在通常的网络环境下,最早发起投票的server也会最早收到其他server的赞成票,因此基本上只需要一轮投票就可以决出leader。整个选主过程非常简单明了。除了选主,整个Raft协议的设计都非常简单。leader和follower之间的交互(如果不考虑snapshot和改变成员数量)一共只有2个RPC call。其中一个还是选主时才需要的RequestVote。也就是说所有的数据交互,都只由AppendEntries 这一个RPC完成。理解Raft算法,首先要理解Term这个概念。每个leader都有自己的Term,而且这个term会带到log的每个entry中去,来代表这个entry是哪个leader term时期写入的。另外Term相当于一个lease。如果在规定的时间内leader没有发送心跳(心跳也是AppendEntries这个RPC call),Follower就会认为leader已经挂掉,会把自己收到过的最高的Term加上1做为新的term去发起一轮选举。如果参选人的term还没自己的高的话,follower会投反对票,保证选出来的新leader的term是最高的。如果在time out周期内没人获得足够的选票(这是有可能的),则follower会在term上再加上1去做新的投票请求,直到选出leader为止。最初的raft是用c语言实现的,这个timeout时间可以设置的非常短,通常在几十ms,因此在raft协议中,leader挂掉之后基本在几十ms就能够被检测发现,故障恢复时间可以做到非常短。而像用Java实现的Raft库,如Ratis,考虑到GC时间,我估计这个超时时间没法设置这么短。在Leader做写入时也是一个两阶段提交的过程。首先leader会把在自己的log中找到第一个空位index写入,并通过AppendEntries这个RPC把这个entry的值发给每个follower,如果收到半数以上的follower(包括自己)回复true,则再下一个AppendEntries中,leader会把committedIndex加1,代表写入的这个entry已经被提交。如在下图中,leader将x=4写入index=8的这个entry中,并把他发送给了所有follower,在收到第一台(自己),第三台,第五台(图中没有画index=8的entry,但因为这台服务器之前所有的entry都和leader保持了一致,因此它一定会投同意),那么leader就获得了多数票,再下一个rpc中,会将Committed index往前挪一位,代表index<=8的所有entry都已经提交。至于第二台和第四台服务器,log内容已经明显落后,这要么是因为前几次rpc没有成功。leader会无限重试直到这些follower和leader的日志追平。另外一个可能是这两台服务器重启过,处于恢复状态。那么这两台服务器在收到写入index=8的RPC时,follower也会把上一个entry的term和index发给他们。也就是说prevLogIndex=7,prevLogTerm=3这个信息会发给第二台服务器,那么对于第二台服务器,index=7的entry是空的,也就是log和leader不一致,他会返回一个false给leader,leader会不停地从后往前遍历,直到找到一个entry与第二台服务器一致的,从这个点开始重新把leader的log内容发送给该follower,即可完成恢复。raft协议保证了所有成员的replicated log中每个index位置,如果他们的term一致,内容也一定一致。如果不一致,leader一定会把这个index的内容改写成和leader一致。其实经过刚才我的一些描述,基本上就已经把Raft的选主,写入流程和恢复基本上都讲完了。从这里,我们可以看出Raft一些非常有意思的地方。第一个有意思的地方是Raft的log的entry是可能被修改的,比如一个follower接收了一个leader的prepare请求,把值写入了一个index,而这个leader挂掉,新选出的leader可能会重新使用这个index,那么这个follower的相应index的内容,会被改写成新的内容。这样就造成了两个问题,首先第一个,raft的log无法在append-only的文件或者文件系统上去实现,而像ZAB,Paxos协议,log只会追加,只要求文件系统有append的能力即可,不需要随机访问修改能力。第二个有意思的地方是,为了简单,Raft中只维护了一个Committed index,也就是任何小于等于这个committedIndex的entry,都是被认为是commit过的。这样就会造成在写入过程中,在leader获得大多数选票之前挂掉(或者leader在写完自己的log之后还没来得及通知到任何follower就挂掉),重启后如果这个server继续被选为leader,这个值仍然会被commit永久生效。因为leader的log中有这个值,leader一定会保证所有的follower的log都和自己保持一致。而后续的写入在增长committedIndex后,这个值也默认被commit了。举例来说,现在有5台服务器,其中S2为leader,但是当他在为index=1的entry执行写入时,先写到了自己的log中,还没来得及通知其他server append entry就宕机了。 当S2重启后,任然有可能被重新当选leader,当S2重新当选leader后,仍然会把index=1的这个entry复制给每台服务器(但是不会往前移动Committed index)此时S2又发生一次写入,这次写入完成后,会把Committed index移动到2的位置,因此index=1的entry也被认为已经commit了。这个行为有点奇怪,因为这样等于raft会让一个没有获得大多数人同意的值最终commit。这个行为取决于leader,如果上面的例子中S2重启后没有被选为leader,index=1的entry内容会被新leader的内容覆盖,从而不会提交未经过表决的内容。虽然说这个行为是有点奇怪,但是不会造成任何问题,因为leader和follower还是会保持一致,而且在写入过程中leader挂掉,对客户端来说是本来就是一个未决语义,raft论文中也指出,如果用户想要exactly once的语义,可以在写入的时候加入一个类似uuid的东西,在写入之前leader查下这个uuid是否已经写入。那么在一定程度上,可以保证exactly once的语义。Raft的论文中也比较了ZAB的算法,文中说ZAB协议的一个缺点是在恢复阶段需要leader和follower来回交换数据,这里我没太明白,据我理解,ZAB在重新选主的过程中,会选择Zxid最大的那个从成为主,而其他follower会从leader这里补全数据,并不会出现leader从follower节点补数据这一说。后话目前,经过改进的Paxos协议已经用在了许多分布式产品中,比如说Chubby,PaxosStore,阿里云的X-DB,以及蚂蚁的OceanBase,都选用了Paxos协议,但他们都多多少少做了一些补充和改进。而像Raft协议,普遍认为Raft协议只能顺序commit entry,性能没有Paxos好,但是TiKV中使用了Raft,其公开的文章宣传对Raft做了非常多的优化,使Raft的性能变的非常可观。阿里的另外一个数据库PolarDB,也是使用了改进版的Parallel-Raft,使Raft实现了并行提交的能力。相信未来会有更多的基于Paxos/Raft的产品会面世,同时也对Raft/Paxos也会有更多的改进。参考文献《Time, clocks, and the ordering of events in a distributed system》《Implementing fault-tolerant services using the state machine approach- A tutorial》《Paxos Made Simple》《Paxos made live- An engineering perspective》《Multi-Paxos》(Standford大学的一个ppt)《Zab- High-performance broadcast for primary-backup systems》《In search of an understandable consensus algorithm》(raft)本文作者:正研阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

February 19, 2019 · 1 min · jiezi

Flask 学习笔记(3) --- 申请和部署HTTPS证书

简介现在已经进入 HTTPS 的时代, HTTPS 证书 目前应用广泛, 发展迅速. 相较于明文传输的 HTTP, HTTPS 更加安全. HTTPS 即 Hypertext Transfer Protocol Secure, 由于其安全层使用的是 TLS/SSL, 因此 HTTPS 也可以称为 HTTP over TLS 或 HTTP over SSL. 关于 HTTPS 证书的分类, 可以参考这篇博客HTTPS 证书 需要向国际公认的证书证书认证机构 Certificate Authority (CA) 申请.接下来, 我们将使用自动化证书管理工具 acme.sh 为我们的域名申请 Let’s Encrypt 颁发的 HTTPS 证书, 然后将其部署在我们的网站上.本文假设我们的域名为 www.awesome.com开发环境在前文的基础上, 我们只需增加 acme.sh 2.8.0 这个工具. 它的中文文档在这里. 安装 acme.sh 的过程很简单, 在 Terminal 中输入如下命令 acme.sh 即可.curl https://get.acme.sh | sh生成证书我们使用 http 方式来验证我们对域名的所有权.如果只申请单域名证书(Single Domain Certificate, www.awesome.com), 那么在 Terminal 中运行如下命令即可acme.sh –issue -d www.awesome.com –standaloneacme 会在当前目录生成一个验证文件, 然后运行一个监听 80 端口的 server, 如果 Let’s Encrypt 成功地通过域名下载了这个文件, 就验证了我们对域名的所有权, 就可以签发证书了.我们也可以运行一个 file server 监听 80 端口cd ~/webapppython3 -m http.server 80然后在另一个 Terminal 里输入如下命令cd ~acme.sh –issue -d www.awesome.com –webroot ~/webapp如果要申请通配符证书(Wildcard Certificate, .awesome.com), 则需要用 dns 方式. 首先我们在 Godaddy 上申请开发者 API key & secret, 然后参考 acme.sh 的文档 readme 和 dnsapi, 执行如下命令export GD_Key=“xxxxxxxx"export GD_Secret=“yyyyy"acme.sh –issue –dns dns_gd -d “.awesome.com” -d awesome.com如果 DNS txt record 记录添加成功, acme 会先等待 120s 以待其生效, 然后验证我们对域名的所有权.下一节, 我们将讲述如何安装和部署证书安装和部署证书对于单域名证书, 根据 acme 的文档, 我们需要执行以下命令, 将证书和公钥放到 ~/ssl/ 文件夹中acme.sh –installcert -d www.awesome.com –key-file ~/ssl/server.key –fullchain-file ~/ssl/server.cer对于通配符证书, 操作也是类似的, 把域名换成 “.awesome.com” 就好了acme.sh –installcert -d “.awesome.com” –key-file /ssl/server.key –fullchain-file /sslwebsite/server.cer然后, 在之前编写的 server 中, 我们需要引入证书和公钥, 从而将明文的消息用 ssl/tls 包裹起来. 根据 Stack Overflow, 这篇文章下面的 Comments, 以及 werkzeug docs, 我们只需要在 app.run() 中加上 ssl_context=(’/ssl/server.cer’, ‘/ssl/server.key’) 参数即可# class IndexHandler(…):# …if name == ‘main’: app.add_url_rule(’/’, view_func=IndexHandler.as_view(‘index’)) context = (’./server.cer’, ‘./server.key’) app.run(port=443, host=‘0.0.0.0’, debug=True, threaded=True, ssl_context=context)至此, 我们的 HTTPS 证书已经申请和部署完成了. 但是我们的 server 目前还存在一个问题, 就是只能访问 https://www.awesome.com, 而原来的 http://www.awesome.com 已经无法访问了, 因为我们的 server 现在只能监听 443 端口而不能监听 80 端口. 下一篇文章, 我们将解决这个问题, 也就是另外写一个 server 来监听 80 端口, 并将 http 服务重定向为 https. 同时, 我们还将学习如何使用 HSTS, 使浏览器默认以更安全的 https 的方式访问我们的网站.参考链接https://imququ.com/post/letse…https://github.com/Neilpang/a...https://github.com/Neilpang/a...https://github.com/Neilpang/a...https://letsencrypt.org/https://stackoverflow.com/que...http://flask.pocoo.org/docs/1...http://flask.pocoo.org/snippe...http://werkzeug.pocoo.org/doc...http://werkzeug.pocoo.org/doc...https://jjayyyyyyy.github.io/… ...

February 15, 2019 · 2 min · jiezi

Flask 学习笔记(2) --- 申请域名和公网 IP

申请域名入门的话可以使用 GoDaddy 的域名, 挑最便宜的那种就好了, 7 块钱能用一年. 另外 Godaddy 也有一整套完整的建站方案, 不过价格略贵.公网 IP可以选择租赁附赠公网 IP 的 VPS, 阿里云腾讯云啥的可能还会有一整套的解决方案, 不过价格会贵一点. 也可以尝试国外的 VPS 厂商, 如 digitalocean, vultr, linode, bandwagon等等, 总之选择一个价格实惠, 而且 IP 可以 ping 通的 VPS 即可.设置 DNS假设你已经获得了域名 awesome.com 的使用权.以 Godaddy 的 dashboard 为例, 点击头像进入【My Product (我的产品)】, 点击域名 awesome.com 中的【DNS】选项, 然后在 Records (记录) 中点击【add (添加)】.接下来, 【Type (类型)】选择 A, 也就是把 domain -> ip 的映射记录.【host (主机)】填写 @, 也就是域名 awesome.com 本身.【Points to (指向)】填写你的 VPS 的 IP 地址.【TTL】选择 1 Hour.按照上述方法, 再添加一条记录, 其中【host (主机)】填写 www, 也就是把 www.awesome.com 也解析到你的 IP.最后, 回到你的 VPS 所在的 Dashboard, 进行类似的 DNS 解析设置即可.最后, 启动我们的 httpserverpython3 server.py稍等几分钟, 在浏览器中输入 http://awesome.com:8080 即可访问我们的网站 ...

February 13, 2019 · 1 min · jiezi

Flask 学习笔记(1) --- 搭建你的第一个 web server

开发环境Ubuntu 16.04Python 3.5Flask 1.0.2命令如下sudo apt-get upgradesudo apt-get install python3-setuptoolssudo apt-get install python3-devsudo apt-get install python3-pipsudo pip3 install pip –upgradesudo pip3 install flask第一个 server首先我们创建一个文件夹 webapp, 并在其中新建一个 main.py 文件mkdir ~/webappcd ~/webapptouch main.py接着, 我们打开 main.py, 按照 Flask Quickstart 的示例, 开始编写第一个 serverfrom flask import Flaskapp = Flask(name)@app.route(’/’, methods=[‘GET’])# methods 默认是 GET 因此可以简写为如下形式# @app.route(’/’)def hello(): return ‘Hello’if name == ‘main’: app.run(host=‘0.0.0.0’, port=8080, debug=True)保存文件后, 在 Terminal 中输入如下命令, 即可运行 webapp. 我们在浏览器中输入 http://server_ip:8080 即可访问网站, 页面的内容就是 Hellopython3 main.py编写 IndexHandler在上一节中, 我们使用了 @ decorator 来指定某个路由对应的处理函数, 这样的写法非常方便. 同时, 我们也可以编写我们自己的 Handler 来处理各个不同的页面(路径). 比如, 对于首页 Index, 即 http://server_ip:8080/, 我们可以编写一个 class IndexHandler, 注意这是一个 MethodView 的子类, 也就是说这是一个 View Handlerfrom flask import Flaskfrom flask.views import MethodViewapp = Flask(name)class IndexHandler(MethodView): def init(self, name): print(name) def get(self): return ‘It is a GET request’ def post(self): return ‘It is a POST request’if name == ‘main’: app.add_url_rule(’/’, view_func=IndexHandler.as_view(‘index’)) app.run(port=8080, host=‘0.0.0.0’, debug=True)根据 flask docs, 传给 as_view() 的参数 name 会转发给构造函数, 我们暂时用不到这个参数 name , 但是为了保持命名的一致性, 我们将其设置为 index保存文件后, 在 Terminal 中输入如下命令, 即可运行 webapp. 我们在浏览器中输入 http://server_ip:8080 即可访问网站, 页面的内容是 It is a GET requestpython3 main.py参考资料quickstart, flask docsas_view, flask docsflask/flask/views.py ...

February 13, 2019 · 1 min · jiezi

Apache 工作的三种模式:Prefork、Worker、Event

Apache 的三种工作模式(Prefork、Worker、Event)Web服务器Apache目前一共有三种稳定的MPM(Multi-Processing Module,多进程处理模块)模式。它们分别是prefork,worker、event,它们同时也代表这Apache的演变和发展。本文原文转自米扑博客:Apache 工作的三种模式:Prefork、Worker、Event如何查看我们的Apache的工作模式呢?可以使用httpd -V 命令查看,如我安装的Apache 2.4版本。# httpd -VServer version: Apache/2.4.34 (Unix)Server built: Aug 2 2018 19:44:29Server’s Module Magic Number: 20120211:79Server loaded: APR 1.6.3, APR-UTIL 1.6.1Compiled using: APR 1.6.3, APR-UTIL 1.6.1Architecture: 64-bitServer MPM: event threaded: yes (fixed thread count) forked: yes (variable process count)或者,更直接的命令 httpd -l 或 apachectl -V | grep -i mpm# httpd -lCompiled in modules: core.c mod_so.c http_core.c event.c# apachectl -V | grep -i mpmServer MPM: event这里使用的是event模式,在apache的早期版本2.0默认prefork,2.2版本是worker,2.4版本是event,详见米扑博客:Apache 服务器负载低访问慢的原因分析和优化方案在configure配置编译参数的时候,可以使用–with-mpm=prefork|worker|event 来指定编译为那一种MPM,当然也可以用编译为三种都支持:–enable-mpms-shared=all,这样在编译的时候会在modules目录下自动编译出三个MPM文件的so,然后通过修改httpd.conf配置文件更改MPM1、Prefork MPM Prefork MPM实现了一个非线程的、预派生的web服务器。它在Apache启动之初,就先预派生一些子进程,然后等待连接;可以减少频繁创建和销毁进程的开销,每个子进程只有一个线程,在一个时间点内,只能处理一个请求。这是一个成熟稳定,可以兼容新老模块,也不需要担心线程安全问题,但是一个进程相对占用资源,消耗大量内存,不擅长处理高并发的场景。图片描述如何配置在Apache的配置文件httpd.conf的配置方式:<IfModule mpm_prefork_module> StartServers 5 MinSpareServers 5 MaxSpareServers 10 MaxRequestWorkers 250 MaxConnectionsPerChild 1000 </IfModule> StartServers 服务器启动时建立的子进程数量,prefork默认是5,MinSpareServers 空闲子进程的最小数量,默认5;如果当前空闲子进程数少于MinSpareServers ,那么Apache将以最大每秒一个的速度产生新的子进程。此参数不要设的太大。MaxSpareServers 空闲子进程的最大数量,默认10;如果当前有超过MaxSpareServers数量的空闲子进程,那么父进程会杀死多余的子进程。次参数也不需要设置太大,如果你将其设置比MinSpareServers 小,Apache会自动将其修改为MinSpareServers +1的数量。MaxRequestWorkers 限定服务器同一时间内客户端最大接入的请求数量,默认是256;任何超过了MaxRequestWorkers限制的请求都要进入等待队列,一旦一个个连接被释放,队列中的请求才将得到服务,如果要增大这个数值,必须先增大ServerLimit。在Apache2.3.1版本之前这参数MaxRequestWorkers被称为MaxClients。MaxConnectionsPerChild 每个子进程在其生命周期内允许最大的请求数量,如果请求总数已经达到这个数值,子进程将会结束,如果设置为0,子进程将永远不会结束。在Apache2.3.9之前称之为MaxRequestsPerChild。这里建议设置为非零,注意原因: 1)能够防止(偶然的)内存泄漏无限进行,从而耗尽内存。 2)给进程一个有限寿命,从而有助于当服务器负载减轻的时候减少活动进程的数量(重生的机会)。2、Worker MPM 和prefork模式相比,worker使用了多进程和多线程的混合模式,worker模式也同样会先预派生一些子进程,然后每个子进程创建一些线程,同时包括一个监听线程,每个请求过来会被分配到一个线程来服务。线程比起进程会更轻量,因为线程是通过共享父进程的内存空间,因此,内存的占用会减少一些,在高并发的场景下会比prefork有更多可用的线程,表现会更优秀一些;另外,如果一个线程出现了问题也会导致同一进程下的线程出现问题,如果是多个线程出现问题,也只是影响Apache的一部分,而不是全部。由于用到多进程多线程,需要考虑到线程的安全了,在使用keep-alive长连接的时候,某个线程会一直被占用,即使中间没有请求,需要等待到超时才会被释放(该问题在prefork模式下也存在)。图片描述如何配置在Apache的配置文件httpd.conf的配置方式:<IfModule mpm_worker_module> StartServers 3 ServerLimit 16 MinSpareThreads 75 MaxSpareThreads 250 ThreadsPerChild 25 MaxRequestWorkers 400 MaxConnectionsPerChild 1000 </IfModule> 配置参数解释:StartServers 服务器启动时建立的子进程数量,在workers模式下默认是3.ServerLimit 系统配置的最大进程数量,默认不显示,自己添加上MinSpareThreads 空闲子进程的最小数量,默认75MaxSpareThreads 空闲子进程的最大数量,默认250ThreadsPerChild 每个子进程产生的线程数量,默认是64MaxRequestWorkers / MaxClients 限定服务器同一时间内客户端最大接入的请求数量.MaxConnectionsPerChild 每个子进程在其生命周期内允许最大的请求数量,如果请求总数已经达到这个数值,子进程将会结束,如果设置为0,子进程将永远不会结束。在Apache2.3.9之前称之为MaxRequestsPerChild。这里建议设置为非零,注意原因:1)能够防止(偶然的)内存泄漏无限进行,从而耗尽内存; 2)给进程一个有限寿命,从而有助于当服务器负载减轻的时候减少活动进程的数量(重生的机会)。Worker模式下所能同时处理的请求总数是由子进程总数乘以ThreadsPerChild值决定的,应该大于等于MaxRequestWorkers。如果负载很大,现有的子进程数不能满足时,控制进程会派生新的子进程。默认ServerLimit 最大的子进程总数是16,加大时也需要显式声明ServerLimit(最大值是20000)。需要注意的是,如果显式声明了ServerLimit,那么它乘以 MaxRequestWorkers必须是hreadsPerChild的整数倍,否则 Apache将会自动调节到一个相应值。3、Event MPM 这是Apache最新的工作模式,它和worker模式很像,不同的是在于它解决了keep-alive长连接的时候占用线程资源被浪费的问题,在event工作模式中,会有一些专门的线程用来管理这些keep-alive类型的线程,当有真实请求过来的时候,将请求传递给服务器的线程,执行完毕后,又允许它释放。这增强了在高并发场景下的请求处理。图片描述如何配置在Apache的配置文件httpd.conf的配置方式:<IfModule mpm_event_module> StartServers 3 ServerLimit 16 MinSpareThreads 75 MaxSpareThreads 250 ThreadsPerChild 25 MaxRequestWorkers 400 MaxConnectionsPerChild 1000 </IfModule> event 模式与 worker 模式完全一样,参考 worker 模式参数即可,这里不再重复。Apache httpd 能更好的为有特殊要求的站点定制。例如,要求更高伸缩性的站点可以选择使用线程的 MPM,即 worker 或 event; 需要可靠性或者与旧软件兼容的站点可以使用 prefork。常见问题查看apache的error日志,可以发现许多系统运行中的问题。server reached MaxRequestWorkers setting[mpm_prefork:error] [pid 1134] AH00161: server reached MaxRequestWorkers setting, consider raising the MaxRequestWorkers setting进程或者线程数目达到了MaxRequestWorkers,可以考虑增加这个值,当然先考虑增加硬件,如内存大小、CPU、SSD硬盘等。scoreboard is full[mpm_event:error] [pid 7555:tid 140058436118400] AH00485: scoreboard is full, not at MaxRequestWorkers这个问题好像是apache2自带的bug,我们无力解决。好在这个问题一般只会影响单个线程,所以暂时可以忍。StackOverflow: Scoreboard is full,not at MaxRequestWorkers 1、I had this same problem. I tried different Apache versions and MPMs. I seem to get this alot with MPM Worker. Also error does not reoccur using Apache 2.2.2,Are you using cPanel? IF so try /upcp –force and increase StartServers to a higher amount like 50 as that’s all I did to get this error away.2、Try EnableMMAP Off in 00_default_settings.confapache 主要版本有:Version 2.4 (Current)Version 2.2 (Historical)Version 2.0 (Historical)Version 1.3 (Historical)参考:https://httpd.apache.org/docs/ 关于 Apache 配置优化,请参见米扑博客:Apache 服务器负载低访问慢的原因分析和优化方案 ...

January 6, 2019 · 2 min · jiezi

浅谈easy-mock 最好的备胎没有之一

引言 今天我们来聊聊Mock,随着互联网发展,这两年前后端分离的开发模式兴起,Mock也从以住的幕后走上了台面,让更多的人而得知,以前传统的开发方式Mock大多局限在后端人员接触较多一些。 Mock已经是老生常谈了,网上一搜索就很多,各位前辈们都讲的很到位,但今天我只讲它——easy-mock。 为什么会突然来聊它,这个就说来话长了,个人简介里就说过,专注于分享工作中遇到的坑,但这一次不是我的坑,来源于QQ群友(# 如果您有想知道的故事,而正好我也会,那么就由我为您讲出来吧,欢迎留言哦 # ),请看下图:这里是@IT·平头哥联盟,我是首席填坑官—苏南,用心分享 做有温度的攻城狮。什么是Mock 什么是Mock?? Mock其实就是真实数据存在之前,即调试期间的代替品,是个虚拟的存在,用人话讲它就是个备胎,如女生长的好看,追她的人多,但又不是很满意但也不拒绝,在自己心仪的小哥哥出现之前,一直吊着你????!如何Mock数据?不要告诉我 new 一个哦,对象可以 new,备胎可new不出来呢????;方法一:最low的方式将 Mock 数据写在代码里、json文件里;方法二:利用 Charles 、Fiddler等代理工具,将 URL 映射到本地文件;方法三:本地起 Mock Server,即mockjs,有点麻烦每次修改了后还要重启服务,nodemon能解决,但开的东西多了,电脑卡出翔,维护也麻烦;方法四:规范些的公司自己已经集成了一套mock数据体系;重点来了:easy-mock一个在线 Mock 平台,活儿好又性感是你备胎的最佳选择。当然优秀的你可能还有很多其他的方式,欢迎补充。//mock 基本使用示例import Mock from “mockjs”;Mock.mock({ “code”: 0, “message”: “请求成功”, “data|20”: [{ “name”: “@cname”,//cname 中文,name 英文 “userId”: “@id”, “lastDate”: “@datetime” }]})什么是easy-mock,能给我们带来什么?Easy Mock 是一个可视化,并且能快速生成 模拟数据 的持久化服务,Easy Mock 支持基于 Swagger 创建项目,以节省手动创建接口的时间;简单点说:Easy Mock就是一个在线创建mock的服务平台,帮你省去你 配置、安装、起服务、维护、多人协作Mock数据不互通等一系列繁琐的操作, 它能在不用1秒钟的时间内给你所要的一切,呼之即来、挥之即去的2018最优秀备胎没有之一,完全不用担心负任何责任哦。更多优点它在等你去发现哦……深入浅出 - 简介就跟人一样长的再好看,了解过后才懂,一样东西也是如何,谁用谁知道;Easy Mock支持团队协作,也可以是个人项目,以下以个人项目为例,与多人协作没有区别,只是少了成员邀请;深入浅出 - Mock语法回顾@ip -> 随机输出一个ip;@id -> 随机输出长度18的字符,不接受参数;“array|1-10” -> 随机输出1-10长度的数组,也可以直接是固定长度;“object|2” -> 输出一个两个key值的对象,"@image()" 返回一个占位图url,支持size, background, foreground, format, text;等等,这里就不再一一介绍。深入浅出 - 创建一个接口它的写法,跟Mock.js一模一样,上面代码已经展示过,更多示例使用Easy Mock创建一个接口,请看下图:深入浅出 - 高阶用法 Function在线编辑,它也能支持 function ,是不是很优秀,能获取到全部请求头,可以让我们像写在js里一样写逻辑,写运算,当然它肯定是还有很多局限性的,如并不支持ES6,有一点需要注意的是 function 里要写传出Mock对象,不能直接@…,来看示例:对象描述MockMock 对象_req.url获得请求 url 地址_req.method获取请求方法_req.params获取 url 参数对象_req.querystring获取查询参数字符串(url中?后面的部分),不包含 ?_req.query将查询参数字符串进行解析并以对象的形式返回,如果没有查询参数字字符串则返回一个空对象_req.body当 post 请求以 x-www-form-urlencoded 方式提交时,我们可以拿到请求的参数对象…_req.cookies、ip、host等等,我只是一个代码的搬运,更详细请看这里//简单模拟登录,根据用户传入的参数,返回不同逻辑数据{ defaultName:function({_req}){ return _req.query.name; }, code: function({_req}){ return this.defaultName ? 0 : -97; }, message: function({_req}) { return this.defaultName ? “登录成功” : “参数错误”; }, data: function({req,Mock}){ return this.defaultName ? { token: Mock.mock("@guid()"), userId: Mock.mock("@id(5)"), cname: Mock.mock("@cname()"), name: Mock.mock("@name()"), avatar: Mock.mock("@image(200x100, #FF6600)"), other:"@IT·平头哥联盟-首席填坑官∙苏南 带你再谈Mock数据之easy-mock" }:{} }}深入浅出 - 在线调试再优秀的工程师写出的代码也一样要测试,没有人敢说自己的代码无Bug,Easy Mock 它是真的懂你的,已经为你准备好了,接口编写好后,立马就能让你测试,是不是觉得很棒棒呢??如果是你自己本地写mock数据,你需要重启服务、手动写参数、可能还需要整个测试页,知道你已经非常饥渴迫切的想要知道,具体的调试方式了:看不清吗??已经为你备好在线调试链接,支持POST、GET、PUT等方式,因gif图加载比较大,就不一一演示了结尾: 天下无不散之宴席,又到说再见的时候了,以上就是今天苏南为大家带来的分享,您GET到了吗?Easy Mock更多强大之处自己去折腾吧,#用心分享 做有温度的攻城狮#,希望今天的分享能给您带来些许成长,如果觉得不错记得点个赞哦,,顺便关注下方公众号就更棒了呢,每周为您推最新分享????????。更多文章:immutability因React官方出镜之使用总结分享!小程序项目之做完项目老板给我加了6k薪资~小程序项目之填坑小记面试踩过的坑,都在这里了~你应该做的前端性能优化之总结大全!如何给localStorage设置一个过期时间?动画一点点 - 如何用CSS3画出懂你的3D魔方?动画一点点 - 手把手教你如何绘制一辆会跑车SVG Sprites Icon的使用技巧作者:苏南 - 首席填坑官链接:https://blog.csdn.net/weixin…交流群:912594095、公众号:honeyBadger8本文原创,著作权归作者所有。商业转载请联系@IT·平头哥联盟获得授权,非商业转载请注明原链接及出处。 ...

November 7, 2018 · 1 min · jiezi