Helm
Helm 是 k8s 中的包管理工具
mac 安装方法如下,
brew install helm
linux 安装方法如下,
brew install helm
Helm 使用的包称为 chart
Chart
多个资源的集合,解决资源部署的问题
创建和使用
- 创建
helm create mychart # 创建
.
├── Chart.yaml # 描述该Chart的基本信息,如名称、描述、版本等
├── charts
├── templates
│ ├── NOTES.txt
│ ├── _helpers.tpl
│ ├── deployment.yaml
│ ├── hpa.yaml
│ ├── ingress.yaml
│ ├── service.yaml
│ ├── serviceaccount.yaml
│ └── tests
│ └── test-connection.yaml
└── values.yaml
2.修改模版文件和 Value
可以参考已有的一些模版文件,魔改
修改 Chart
3.helm 模版调试
helm install --debug --dry-run ./mychart
4.测试打包
helm lint ./mychart # 静态检查
helm package ./mychart # 打包
5.安装
helm install -name mychart1
摘要
我们设计和实现了谷歌文件系统,一个面向大规模分布式数据密集型应用的可伸缩文件系统。即使在普通廉价的商用机器上,它也提供了容灾和高性能服务。
GFS的设计目标和传统分布式文件系统类似,但是我们的设计和实现是由我们的应用负载和技术环境驱动的。不管是现在还是将来,GFS和早起的设想都有出入,我们重新审视了传统文件系统在设计上的折中选择,并衍生出完全不同的设计思路。
GFS完全满足我们对存储的需求。Google内部广泛使用GFS生成和处理大数据集。最大的集群使用数千台机器,提供了数百T的存储空间,服务于数百台客户机。
本文介绍GFS对于分布式应用的接口支持和扩展,讨论GFS的设计思路和细节,列出小规模测试和生产环境中的性能数据。
1. Introduction
GFS的设计和实现是为了满足谷歌快速增长的数据处理需求。GFS和传统的分布式文件系统具有许多相同的设计目标,如性能、可伸缩性、可靠性、可用性。但是,其设计由我们的技术环境驱动而来,因此和早期的文件系统又有着标志性的不同。我们考虑了传统文件系统的折衷选择,并给出了完全不同的设计思路。
首先,组件失败被认为是常态事件,而非意外事件。GFS包括数百台甚至数千台机器,支持可观数量的客户机访问。在任何时刻,机器组件都有可能发生故障,或者无法恢复有效服务。我们曾经遇到过程序bug、操作系统bug、人为失误、磁盘损坏、内存损坏、网络故障、电源损坏等各种各样的问题。所以,持续的监控、错误检测、容错和自动恢复等机制需要集成到GFS中。
其次,以传统的角度看,我们的文件庞大,数G大小的文件非常普遍。。每个文件通常包含许多应用程序对象,比如web文档。当处理数亿个对象构成的数以TB的数据集时,采用管理数亿个KB大小的小文件的方式是不明智的,尽管有些文件系统支持。因此,I/O操作、文件块尺寸等因素都需要重新考虑。
第三,绝大多数文件通过在文件尾部添加新数据的方式修改,而不是覆写已有数据。对文件的随机写入,在实际生产环境中几乎不存在。一旦文件写入完成,那么这些文件通常是只读,并且是按顺序读。比如,数据分析程序扫描超大数据集;正在运行的程序不断生成数据流;已归档的数据;一台机器上生成的中间结果,会被
6.824实验的基础设施:RPC和线程
Go中的线程和RPC,以及Go Tour中的一些练习
为什么使用Go作为lab的编程语言
- Go对线程的良好支持
- 方便使用的RPC
- 具有垃圾回收机制
- 相对简单
- 本教程的Go编程规范和细则参考https://golang.org/doc/effective_go.html
线程
常用的结构化工具,但是使用起来会有各种各样的trick。在Go中,被称作goroutines。线程的存在,使得一个程序可以并发的处理多项任务。线程共享内存空间,线程不共享的有程序计数器、线程栈、寄存器。
在分布式系统中,我们需要线程的并行语义:
1. I/O并发。多个客户端发送请求并等待响应,服务端处理多个客户端请求。当在等待读取客户端X的数据时,可以利用等待的时间去处理客户端Y的请求。
2. 多核性能。代码可以并行地在多个cpu核里运行。
3. 便捷
线程有无替代品
事件驱动,就是线程的替代品。即,在一个线程中,活动状态交织,其实就是状态机。维护一个数据结构,保存每个活动的状态,比如,每个客户端请求。
开启一个事件循环,监听每个活动的输入(比如,服务端的响应到达),然后切换该活动到下一状态。
事件驱动,也可以实现I/O并发,并且避免线程切换的开销,但是浪费了多核编程环境。
多线程编程的难点
- 数据共享
- 比如,如果两个线程同时执行
n = n + 1
,或者,一个线程增加n时,另外一个线程读取n。这时候需要利用锁机制(Go里面有sync.Mutex),或者,避免共享可变对象数据。
- 比如,如果两个线程同时执行
- 线程之间的条件竞争
- 比如一个线程在生产数据,另外一个消耗数据。那么消费者怎么等待数据,生产者怎么唤醒消费者。Go中使用Go channel、sync.Cond、WaitGroup等数据结构解决该问题。
- 死锁
- RPC或者Go channels中可能产生死锁
Web Crawler
爬虫需要注意的两个问题:
1. I/O并发
多个线程,同时爬取多个网址
2. 每个URL只处理一次,避免重复处理
维护一个数据结构记录已经处理过的url,并且知道爬取程序的终止条件
crawler.go有两种解决方式
摘要
MapReduce是一种用来处理和生成大数据集的编程模型以及相关实现。用户选定一个map函数,该map函数的输入是一个键值对,输出是一系列中间键值对。然后用户选定一个reduce函数,该reduce函数用于处理具有相同键的所有中间键值对,并得到结果。实际生产中,有大量应用可以用此模型描述。
这种编程模型可以在集群上并行工作。运行时系统会自动分割输入数据、分发任务到各个机器、处理任务失败或者机器故障、管理必要的机器间通信。因此,即使没有分布式系统经验的程序员,也可以方便地利用分布式系统的资源。
现在每天有大量MapReduce模型的工程运行于谷歌集群,其具有高度的扩展性,一个典型的MapReduce计算可以利用集群处理TB级别的数据集。
1.介绍
过去数年,大量特殊目的的计算程序被设计出来,用于处理大量的原始数据集,比如爬虫结果、网络请求日志,来得到需要的衍生数据,比如倒排索引、web文档的图结构、某日查询最多的关键词。虽然这类计算在概念上非常直观,但是由于输入数据集非常庞大,因此需要将这些输入数据集切割、分发到多个机器上处理。但是除了原来本有的计算模型外,还需要编写大量复杂的代码去处理并行化计算、数据分发、故障处理等问题。
因此我们干脆设计一种新的抽象,将并行计算、容错、数据分发、负载均衡这些复杂技术细节隐藏起来,交给库去完成,我们只需要定义计算模型即可。这种抽象的灵感来自于Lisp等函数式编程语言中的Map和Reduce原语。我们意识到许多计算都需要对输入的每个记录应用一个"map"操作来得到中间一系列键值对,之后再对所有拥有相同键的值应用"reduce"操作,得到衍生数据集。因此如果一个编程模型,允许我们通过定义map操作和reduce操作,那我们就可以方便设计大量并行计算,并且我们可以使用重新执行作为主要的容错机制。
这次工作的主要贡献是提供一个简单而强大的接口,可以使用这个接口完成自动并行化和大规模分布式计算,并且该接口的实现在大型商用集群上性能卓然。
本文第二章给出基本编程模型以及一些栗子。第三章介绍为集群计算环境量身定做的MapReduce接口。第四章介绍一些对于编程模型的改进。第五章测试了我们的实现在不同任务
终端挂代理
因为electron-ssr已经提供了http的代理。
如需要在终端中挂上代理,输入
export http_proxy="http://127.0.0.1:12333"
export https_proxy="http://127.0.0.1:12333"
Go官网教程(A tour of Go)
从官网下载一个tour教程包
go get golang.org/x/tour
工作路径bin目录下会出现tour二进制,运行tour程序会打开一个本地站点
分三部分
1. 基本语法和数据结构
2. 方法和接口
3. 并发原语
学习过程中的一些笔记
第一部分
Go项目均由packages构成, 项目从main包开始运行
如果变量名以大写字母开头,则该变量对外可见,即导出。否则,外界不可见,且无法使用
为何go变量的类型声明与c系语言不同?go的类型声明在做复杂的函数签名时更易读
slice与array
map特性
make方法,既可以用来创建slice,也可以用来创建map
第二部分
方法:Go中没有类的概念,但是可以在函数的基础上得到方法。即,在func和函数名之间插入某个类型的调用者(receiver)。本质上,还是一个函数。等价于将receiver作为第一个参数传入函数。receiver的类型定义必须在同一个package中
接收器分为两种value receiver和point receiver。方法中对value receiver的修改不会影响到方法外,对point receiver的修改会影响到方法外
value receiver的调用可以被转换为对point receiver的调用
point receiver的调用可以被转化为对value receiver的调用
使用point receiver的两个优点:
1. 该方法需要修改receiver指向的值
2. 可以避免值拷贝
接口:一些方法签名的集合。也可以看作是一种类型。当某些类型实现了接口中的方法,那么这些类型可以赋值给接口类型定义的变量。
如果某些类型拥有相同的方法集合,那么可以定义一个