基于C#+Thrift操作HBase实践

在基于HBase数据库的开发中,对应Java语言来说,可以直接使用HBase的原生API来操作HBase表数据,当然你要是不嫌麻烦可以使用Thrift客户端Java API,这里有我曾经使用过的 HBase Thrift客户端Java API实践,可以参考。对于具有其他编程语言背景的开发人员,为了获取HBase带来的好处,那么就可以选择使用HBase Thrift客户端对应编程语言的API,来实现与HBase的交互。
这里,我们使用C#客户端来操作HBase。HBase的Thrift接口的定义,可以通过链接http://svn.apache.org/viewvc/hbase/trunk/hbase-server/src/main/resources/org/apache/hadoop/hbase/thrift/Hbase.thrift?view=markup看到,我们需要安装Thrift编译器,才能生成HBase跨语言的API,这里,我使用的版本是0.9.0。需要注意的是,一定要保证,安装了某个版本Thrift的Thrift编译器,在导入对应语言库的时候,版本一定要统一,否则就会出现各种各样的问题,因为不同Thrift版本,对应编程语言的库API可能有变化。
首先,下载上面链接的内容,保存为Hbase.thrift。
然后,执行如下命令,生成C#编程语言的HBase Thrift客户端API:

1 [hadoop@master hbase]$ thrift --gen csharp Hbase.thrift
2 [hadoop@master hbase]$ ls
3 gen-csharp

这里,我们基于C#语言,使用HBase 的Thrift 客户端API访问HBase表。事实上,如果使用Java来实现对HBase表的操作,最好是使用HBase的原生API,无论从性能还是便利性方面,都会提供更好的体验。使用Thrift API访问,实际也是在HBase API之上进行了一层封装,可能初次使用Thrift API感觉很别扭,有时候还要参考Thrift服务端的实现代码。
准备工作如下:

    1. 下载Thrift软件包,解压缩后,拷贝thrift-0.9.0/lib/java/src下面的代码到工作区(开发工具中)
    2. 将上面生成的gen-csharp目录中代码拷贝到工作区
    3. 保证HBase集群正常运行,接着启动HBase的Thrift服务,执行如下命令:
1 bin/hbase thrift -b master -p 9090 start

上面,HBase的Thrift服务端口为9090,下面通过Thrift API访问的时候,需要用到,而不是HBase的服务端口(默认60000)。
接着,实现一个简单的例子,访问Hbase表。
首先,我们通过HBase Shell创建一个表:

1 create 'test_info', 'info'

表名为test_info,列簇名称为info。
然后,我们开始基于上面生成的Thrift代码来实现对HBase表的操作。
这里,我们实际上是对HBase Thrift客户端Java API实践中的Java代码进行了翻译,改写成C#语言的相关操作。我们在客户端,进行了一层抽象,更加便于传递各种参数,抽象类为AbstractHBaseThriftService,对应的命名空间为HbaseThrift.HBase.Thrift,该类实现代码如下所示:

01 using System;
02 using System.Collections.Generic;
03 using System.Linq;
04 using System.Text;
05 using System.Threading.Tasks;
06
07 using Thrift.Transport;
08 using Thrift.Protocol;
09
10 namespace HbaseThrift.HBase.Thrift
11 {
12 public abstract class AbstractHBaseThriftService
13 {
14 protected static readonly string CHARSET = "UTF-8";
15 private string host = "localhost";
16 private int port = 9090;
17 private readonly TTransport transport;
18 protected readonly Hbase.Client client;
19
20 public AbstractHBaseThriftService() : this("localhost", 9090)
21 {
22
23 }
24
25 public AbstractHBaseThriftService(string host, int port)
26 {
27 this.host = host;
28 this.port = port;
29 transport = new TSocket(host, port);
30 TProtocol protocol = new TBinaryProtocol(transport, true, true);
31 client = new Hbase.Client(protocol);
32 }
33
34 public void Open() {
35 if (transport != null)
36 {
37 transport.Open();
38 }
39 }
40
41 public void Close()
42 {
43 if (transport != null)
44 {
45 transport.Close();
46 }
47 }
48
49 public abstract List<string> GetTables();
50
51 public abstract void Update(string table, string rowKey, bool writeToWal,
52 string fieldName, string fieldValue, Dictionary<string, string> attributes);
53 public abstract void Update(string table, string rowKey, bool writeToWal,
54 Dictionary<string, string> fieldNameValues, Dictionary<string, string> attributes);
55
56 public abstract void DeleteCell(string table, string rowKey, bool writeToWal,
57 string column, Dictionary<string, string> attributes);
58 public abstract void DeleteCells(string table, string rowKey, bool writeToWal,
59 List<string> columns, Dictionary<string, string> attributes);
60
61 public abstract void DeleteRow(string table, string rowKey,
62 Dictionary<string, string> attributes);
63
64 public abstract int ScannerOpen(string table, string startRow, List<string> columns,
65 Dictionary<string, string> attributes);
66 public abstract int ScannerOpen(string table, string startRow, string stopRow, List<string> columns,
67 Dictionary<string, string> attributes);
68 public abstract int ScannerOpenWithPrefix(string table, string startAndPrefix,
69 List<string> columns, Dictionary<string, string> attributes);
70 public abstract int ScannerOpenTs(string table, string startRow,
71 List<string> columns, long timestamp, Dictionary<string, string> attributes);
72 public abstract int ScannerOpenTs(string table, string startRow, stringstopRow,
73 List<string> columns, long timestamp, Dictionary<string, string> attributes);
74
75 public abstract List<TRowResult> ScannerGetList(int id, int nbRows);
76 public abstract List<TRowResult> ScannerGet(int id);
77
78 public abstract List<TRowResult> GetRow(string table, string row,
79 Dictionary<string, string> attributes);
80 public abstract List<TRowResult> GetRows(string table,
81 List<string> rows, Dictionary<string, string> attributes);
82 public abstract List<TRowResult> GetRowsWithColumns(string table,
83 List<string> rows, List<string> columns, Dictionary<string, string> attributes);
84
85 public abstract void ScannerClose(int id);
86
87 /**
88 * Iterate result rows(just for test purpose)
89 * @param result
90 */
91 public abstract void IterateResults(TRowResult result);
92
93 }
94 }

这里,简单叙述一下,我们提供的客户端API的基本功能:

  • 建立到Thrift服务的连接:Open()
  • 获取到HBase中的所有表名:GetTables()
  • 更新HBase表记录:Update()
  • 删除HBase表中一行的记录的数据(cell):DeleteCell()和DeleCells()
  • 删除HBase表中一行记录:deleteRow()
  • 打开一个Scanner,返回id:ScannerOpen()、ScannerOpenWithPrefix()和ScannerOpenTs();然后用返回的id迭代记录:ScannerGetList()和ScannerGet()
  • 获取一行记录结果:GetRow()、GetRows()和GetRowsWithColumns()
  • 关闭一个Scanner:ScannerClose()
  • 迭代结果,用于调试:IterateResults()

比如,我们想要实现分页的逻辑,可能和传统的关系型数据库操作有些不同。基于HBase表的实现是,首先打开一个Scanner实例(例如调用ScannerOpen()),返回一个id,然后再使用该id,调用ScannerGetList()方法(可以指定每次返回几条记录的变量nbRows的值),返回一个记录列表,反复调用该ScannerGetList()方法,直到此次没有结果返回为止。后面会通过测试用例来实际体会。
现在,我们基于上抽象出来的客户端操作接口,给出一个基本的实现,代码如下所示:

001 using System;
002 using System.Collections.Generic;
003 using System.Linq;
004 using System.Text;
005 using System.Threading.Tasks;
006
007 namespace HbaseThrift.HBase.Thrift
008 {
009 class HBaseThriftClient : AbstractHBaseThriftService
010 {
011 public HBaseThriftClient() : this("localhost", 9090)
012 {
013
014 }
015
016 public HBaseThriftClient(string host, int port) : base(host, port)
017 {
018
019 }
020
021 public override List<string> GetTables()
022 {
023 List<byte[]> tables = client.getTableNames();
024 List<String> list = new List<String>();
025 foreach(byte[] table in tables)
026 {
027 list.Add(Decode(table));
028 }
029 return list;
030 }
031
032 public override void Update(string table, string rowKey, bool writeToWal,string fieldName, string fieldValue, Dictionary<string, string> attributes)
033 {
034 byte[] tableName = Encode(table);
035 byte[] row = Encode(rowKey);
036 Dictionary<byte[], byte[]> encodedAttributes = EncodeAttributes(attributes);
037 List<Mutation> mutations = new List<Mutation>();
038 Mutation mutation = new Mutation();
039 mutation.IsDelete = false;
040 mutation.WriteToWAL = writeToWal;
041 mutation.Column = Encode(fieldName);
042 mutation.Value = Encode(fieldValue);
043 mutations.Add(mutation);
044 client.mutateRow(tableName, row, mutations, encodedAttributes);
045 }
046
047 public override void Update(string table, string rowKey, bool writeToWal, Dictionary<string, string> fieldNameValues, Dictionary<string, string> attributes)
048 {
049 byte[] tableName = Encode(table);
050 byte[] row = Encode(rowKey);
051 Dictionary<byte[], byte[]> encodedAttributes = EncodeAttributes(attributes);
052 List<Mutation> mutations = new List<Mutation>();
053 foreach (KeyValuePair<String, String> pair in fieldNameValues)
054 {
055 Mutation mutation = new Mutation();
056 mutation.IsDelete = false;
057 mutation.WriteToWAL = writeToWal;
058 mutation.Column = Encode(pair.Key);
059 mutation.Value = Encode(pair.Value);
060 mutations.Add(mutation);
061 }
062 client.mutateRow(tableName, row, mutations, encodedAttributes);
063 }
064
065 public override void DeleteCell(string table, string rowKey, bool writeToWal,string column, Dictionary<string, string> attributes)
066 {
067 byte[] tableName = Encode(table);
068 byte[] row = Encode(rowKey);
069 Dictionary<byte[], byte[]> encodedAttributes = EncodeAttributes(attributes);
070 List<Mutation> mutations = new List<Mutation>();
071 Mutation mutation = new Mutation();
072 mutation.IsDelete = true;
073 mutation.WriteToWAL = writeToWal;
074 mutation.Column = Encode(column);
075 mutations.Add(mutation);
076 client.mutateRow(tableName, row, mutations, encodedAttributes);
077 }
078
079 public override void DeleteCells(string table, string rowKey, bool writeToWal, List<string> columns, Dictionary<string, string> attributes)
080 {
081 byte[] tableName = Encode(table);
082 byte[] row = Encode(rowKey);
083 Dictionary<byte[], byte[]> encodedAttributes = EncodeAttributes(attributes);
084 List<Mutation> mutations = new List<Mutation>();
085 foreach (string column in columns)
086 {
087 Mutation mutation = new Mutation();
088 mutation.IsDelete = true;
089 mutation.WriteToWAL = writeToWal;
090 mutation.Column = Encode(column);
091 mutations.Add(mutation);
092 }
093 client.mutateRow(tableName, row, mutations, encodedAttributes);
094 }
095
096 public override void DeleteRow(string table, string rowKey, Dictionary<string,string> attributes)
097 {
098 byte[] tableName = Encode(table);
099 byte[] row = Encode(rowKey);
100 Dictionary<byte[], byte[]> encodedAttributes = EncodeAttributes(attributes);
101 client.deleteAllRow(tableName, row, encodedAttributes);
102 }
103
104 public override int ScannerOpen(string table, string startRow, List<string> columns, Dictionary<string, string> attributes)
105 {
106 byte[] tableName = Encode(table);
107 byte[] start = Encode(startRow);
108 List<byte[]> encodedColumns = EncodeStringList(columns);
109 Dictionary<byte[], byte[]> encodedAttributes = EncodeAttributes(attributes);
110 return client.scannerOpen(tableName, start, encodedColumns, encodedAttributes);
111 }
112
113 public override int ScannerOpen(string table, string startRow, string stopRow, List<string> columns, Dictionary<string, string> attributes)
114 {
115 byte[] tableName = Encode(table);
116 byte[] start = Encode(startRow);
117 byte[] stop = Encode(stopRow);
118 List<byte[]> encodedColumns = EncodeStringList(columns);
119 Dictionary<byte[], byte[]> encodedAttributes = EncodeAttributes(attributes);
120 return client.scannerOpenWithStop(tableName, start, stop, encodedColumns, encodedAttributes);
121 }
122
123 public override int ScannerOpenWithPrefix(string table, string startAndPrefix, List<string> columns, Dictionary<string, string> attributes)
124 {
125 byte[] tableName = Encode(table);
126 byte[] prefix = Encode(startAndPrefix);
127 List<byte[]> encodedColumns = EncodeStringList(columns);
128 Dictionary<byte[], byte[]> encodedAttributes = EncodeAttributes(attributes);
129 return client.scannerOpenWithPrefix(tableName, prefix, encodedColumns, encodedAttributes);
130 }
131
132 public override int ScannerOpenTs(string table, string startRow, List<string> columns, long timestamp, Dictionary<string, string> attributes)
133 {
134 byte[] tableName = Encode(table);
135 byte[] start = Encode(startRow);
136 List<byte[]> encodedColumns = EncodeStringList(columns);
137 Dictionary<byte[], byte[]> encodedAttributes = EncodeAttributes(attributes);
138 return client.scannerOpenTs(tableName, start, encodedColumns, timestamp, encodedAttributes);
139 }
140
141 public override int ScannerOpenTs(string table, string startRow, stringstopRow, List<string> columns, long timestamp, Dictionary<string, string> attributes)
142 {
143 byte[] tableName = Encode(table);
144 byte[] start = Encode(startRow);
145 byte[] stop = Encode(stopRow);
146 List<byte[]> encodedColumns = EncodeStringList(columns);
147 Dictionary<byte[], byte[]> encodedAttributes = EncodeAttributes(attributes);
148 return client.scannerOpenWithStopTs(tableName, start, stop, encodedColumns, timestamp, encodedAttributes);
149 }
150
151 public override List<TRowResult> ScannerGetList(int id, int nbRows)
152 {
153 return client.scannerGetList(id, nbRows);
154 }
155
156 public override List<TRowResult> ScannerGet(int id)
157 {
158 return client.scannerGet(id);
159 }
160
161 public override List<TRowResult> GetRow(string table, string row, Dictionary<string, string> attributes)
162 {
163 byte[] tableName = Encode(table);
164 byte[] startRow = Encode(row);
165 Dictionary<byte[], byte[]> encodedAttributes = EncodeAttributes(attributes);
166 return client.getRow(tableName, startRow, encodedAttributes);
167 }
168
169 public override List<TRowResult> GetRows(string table, List<string> rows, Dictionary<string, string> attributes)
170 {
171 byte[] tableName = Encode(table);
172 List<byte[]> encodedRows = EncodeStringList(rows);
173 Dictionary<byte[], byte[]> encodedAttributes = EncodeAttributes(attributes);
174 return client.getRows(tableName, encodedRows, encodedAttributes);
175 }
176
177 public override List<TRowResult> GetRowsWithColumns(string table, List<string> rows, List<string> columns, Dictionary<string, string> attributes)
178 {
179 byte[] tableName = Encode(table);
180 List<byte[]> encodedRows = EncodeStringList(rows);
181 List<byte[]> encodedColumns = EncodeStringList(columns);
182 Dictionary<byte[], byte[]> encodedAttributes = EncodeAttributes(attributes);
183 return client.getRowsWithColumns(tableName, encodedRows, encodedColumns, encodedAttributes);
184 }
185
186 public override void ScannerClose(int id)
187 {
188 client.scannerClose(id);
189 }
190
191 public override void IterateResults(TRowResult result)
192 {
193 foreach (KeyValuePair<byte[], TCell> pair in result.Columns)
194 {
195 Console.WriteLine("\tCol=" + Decode(pair.Key) + ", Value=" + Decode(pair.Value.Value));
196 }
197 }
198
199 private String Decode(byte[] bs)
200 {
201 return UTF8Encoding.Default.GetString(bs);
202 }
203
204 private byte[] Encode(String str)
205 {
206 return UTF8Encoding.Default.GetBytes(str);
207 }
208
209 private Dictionary<byte[], byte[]> EncodeAttributes(Dictionary<String, String> attributes)
210 {
211 Dictionary<byte[], byte[]> encodedAttributes = new Dictionary<byte[],byte[]>();
212 foreach (KeyValuePair<String, String> pair in attributes)
213 {
214 encodedAttributes.Add(Encode(pair.Key), Encode(pair.Value));
215 }
216 return encodedAttributes;
217 }
218
219 private List<byte[]> EncodeStringList(List<String> strings)
220 {
221 List<byte[]> list = new List<byte[]>();
222 if (strings != null)
223 {
224 foreach (String str in strings)
225 {
226 list.Add(Encode(str));
227 }
228 }
229 return list;
230 }
231 }
232 }

上面代码,给出了基本的实现,接着我们给出测试用例,调用我们实现的客户端操作,与HBase表进行交互。实现的测试用例类如下所示:

001 using System;
002 using System.Collections.Generic;
003 using System.Linq;
004 using System.Text;
005 using System.Threading.Tasks;
006
007 namespace HbaseThrift.HBase.Thrift
008 {
009 class Test
010 {
011 private readonly AbstractHBaseThriftService client;
012
013 public Test(String host, int port)
014 {
015 client = new HBaseThriftClient(host, port);
016 }
017
018 public Test() : this("master", 9090)
019 {
020
021 }
022
023 static String RandomlyBirthday()
024 {
025 Random r = new Random();
026 int year = 1900 + r.Next(100);
027 int month = 1 + r.Next(12);
028 int date = 1 + r.Next(30);
029 return year + "-" + month.ToString().PadLeft(2, '0') + "-" + date.ToString().PadLeft(2, '0');
030 }
031
032 static String RandomlyGender()
033 {
034 Random r = new Random();
035 int flag = r.Next(2);
036 return flag == 0 ? "M" : "F";
037 }
038
039 static String RandomlyUserType()
040 {
041 Random r = new Random();
042 int flag = 1 + r.Next(10);
043 return flag.ToString();
044 }
045
046 public void Close()
047 {
048 client.Close();
049 }
050
051 public void CaseForUpdate() {
052 bool writeToWal = false;
053 Dictionary<String, String> attributes = new Dictionary<String, String>(0);
054 string table = SetTable();
055 // put kv pairs
056 for (int i = 0; i < 10000000; i++) {
057 string rowKey = i.ToString().PadLeft(4, '0');
058 Dictionary<String, String> fieldNameValues = new Dictionary<String, String>();
059 fieldNameValues.Add("info:birthday", RandomlyBirthday());
060 fieldNameValues.Add("info:user_type", RandomlyUserType());
061 fieldNameValues.Add("info:gender", RandomlyGender());
062 client.Update(table, rowKey, writeToWal, fieldNameValues, attributes);
063 }
064 }
065
066 public void CaseForDeleteCells() {
067 bool writeToWal = false;
068 Dictionary<String, String> attributes = new Dictionary<String, String>(0);
069 String table = SetTable();
070 // put kv pairs
071 for (long i = 5; i < 10; i++) {
072 String rowKey = i.ToString().PadLeft(4, '0');
073 List<String> columns = new List<String>(0);
074 columns.Add("info:birthday");
075 client.DeleteCells(table, rowKey, writeToWal, columns, attributes);
076 }
077 }
078
079 public void CaseForDeleteRow() {
080 Dictionary<String, String> attributes = new Dictionary<String, String>(0);
081 String table = SetTable();
082 // delete rows
083 for (long i = 5; i < 10; i++) {
084 String rowKey = i.ToString().PadLeft(4, '0');
085 client.DeleteRow(table, rowKey, attributes);
086 }
087 }
088
089 public void CaseForScan() {
090 Dictionary<String, String> attributes = new Dictionary<String, String>(0);
091 String table = SetTable();
092 String startRow = "0005";
093 String stopRow = "0015";
094 List<String> columns = new List<String>(0);
095 columns.Add("info:birthday");
096 int id = client.ScannerOpen(table, startRow, stopRow, columns, attributes);
097 int nbRows = 2;
098 List<TRowResult> results = client.ScannerGetList(id, nbRows);
099 while(results != null) {
100 foreach(TRowResult result in results) {
101 client.IterateResults(result);
102 }
103 results = client.ScannerGetList(id, nbRows);
104 }
105 client.ScannerClose(id);
106 }
107
108 public void CaseForGet() {
109 Dictionary<String, String> attributes = new Dictionary<String, String>(0);
110 String table = SetTable();
111 List<String> rows = new List<String>(0);
112 rows.Add("0009");
113 rows.Add("0098");
114 rows.Add("0999");
115 List<String> columns = new List<String>(0);
116 columns.Add("info:birthday");
117 columns.Add("info:gender");
118 List<TRowResult> results = client.GetRowsWithColumns(table, rows, columns, attributes);
119 foreach(TRowResult result in results) {
120 client.IterateResults(result);
121 }
122 }
123
124 private string SetTable()
125 {
126 string table = "test_info";
127 return table;
128 }
129
130 static void Main(string[] args)
131 {
132 Test test = new Test();
133 //test.CaseForUpdate(); // insert or update rows/cells
134 //test.CaseForDeleteCells(); // delete cells
135 //test.CaseForDeleteRow(); // delete rows
136 test.CaseForScan(); // scan rows
137 //test.CaseForGet(); // get rows
138
139 test.Close();
140 }
141
142 }
143 }

上面的测试可以实现操作Hbase表数据。另外,在生成的Thrift客户端代码中,Iface中给出了全部的服务接口,可以根据需要来选择,客户端Client实现了与Thrift交互的一些逻辑的处理,通过该类对象可以代理HBase提供的Thrift服务。

时间: 2024-10-29 20:21:18

基于C#+Thrift操作HBase实践的相关文章

python如何thrift框架操作hbase数据库及shell操作

以前都是用mongodb的,但是量大了,mongodb显得不那么靠谱,改成hbase撑起一个量级. HBase是Apache Hadoop的数据库,能够对大型数据提供随机.实时的读写访问.HBase的目标是存储并处理大型的数据.HBase是一个开源的,分布式的,多版本的,面向列的存储模型.它存储的是松散型数据. HBase提供了丰富的访问接口. HBase Shell Java clietn API Jython.Groovy DSL.Scala REST Thrift(Ruby.Python.

DockOne微信分享(九十六):爱油科技基于SpringCloud的微服务实践

本文讲的是DockOne微信分享(九十六):爱油科技基于SpringCloud的微服务实践[编者的话]本次分享主要介绍了爱油科技基于Docker和Spring Cloud将整体业务微服务化的一些实践经验,主要包括: 微服务架构的分层和框架选型 服务发现和配置管理 服务集成和服务质量保证 基于领域驱动设计 实施DevOps 从单体应用到微服务 单体应用 对于单体应用来说,优点很多,例如: 小而美,结构简单易于开发实现 部署门槛低,单个Jar包或者网站打包即可部署 可快速实现多实例部署 然而随着业务

HBase伪分布式安装(HDFS)+ZooKeeper安装+HBase数据操作+HBase架构体系

HBase1.2.2伪分布式安装(HDFS)+ZooKeeper-3.4.8安装配置+HBase表和数据操作+HBase的架构体系+单例安装,记录了在Ubuntu下对HBase1.2.2的实践操作,HBase的安装到数据库表的操作.包含内容1.HBase单例安装2.HBase伪分布式安装(基于Hadoop的HDFS)过程,3.HBase的shell编程,对HBase表的创建,删除等的命令,HBase对数据的增删查等操作.4.简单概述了Hbase的架构体系.5.zookeeper的单例安装和常用操

云上基于Kerberos的大数据安全实践

1. 摘要 本文主要介绍E-MapReduce基于Kerberos的大数据安全实践,包括边界安全/认证/授权/审计/加密,其中重点介绍了身份认证,采用了阿里云和Intel合作开发的基于Kerberos插件式可扩展认证的HAS框架,方便用户与已经存在的用户认证系统相结合,使得安全管理人员不需要在用户账号系统和Kerberos的数据库之间迁移和同步,如将阿里云的RAM/LDAP等外部的身份认证系统接入Kerberos. 2. 什么是身份认证 身份认证(Authentication)是用于识别用户身份

DockOne微信分享(一四四):BizCloud:基于Kubernetes的私有云实践

[编者的话]随着搜狗业务的快速增长,需要更有效地控制成本,提升研发效率,我们基于Docker和Kubernetes构建了一站式私有云管理平台--BizCloud,此平台涵盖服务管理.弹性伸缩.灰度发布.自动运维.持续集成等功能.本文将简要介绍BizCloud的设计思路.架构及服务发现.授权.灰度发布等核心功能的实现. BizCloud简介 本文将的是DockOne微信分享(一四四):BizCloud:基于Kubernetes的私有云实践我们基础环境非常复杂,目前有多个版本操作系统共存,应用也常常

DockOne微信分享(一三九):基于Kubernetes的应用编排实践

本文讲的是DockOne微信分享(一三九):基于Kubernetes的应用编排实践[编者的话]近年容器的使用越来越深入,越来越多的服务采用容器的方式进行部署.但随着服务数量的增加,如何管理服务之间的依赖关系,如何对多个服务之间的更新与部署进行管理,如何在新的环境中实现多个服务的快速部署.这些问题都希望通过基于Kubernetes应用编排管理来解决,从而实现对于复杂多服务系统的快速部署和高效管理. [烧脑式Kubernetes实战训练营]本次培训理论结合实践,主要包括:Kubernetes架构和资

DockOne微信分享(一三二):58 赶集基于 Docker 的自动化部署实践

本文讲的是DockOne微信分享(一三二):58 赶集基于 Docker 的自动化部署实践[编者的话]随着 58 业务的发展,机器和服务数量也日益庞大,在多环境下,服务的管理和依赖难以维护.基于 Docker 带来的技术红利,我们借助 Docker 和 Kubernetes 提供了镜像的自动打包,单一镜像在测试-沙箱-生产-稳定四个环境的流转,以及测试环境统一的 Nginx 入口.至此,开发同学可以不再为资源和环境问题困扰,提高了生产效率. [3 天烧脑式容器存储网络训练营 | 深圳站]本次培训

基于Kickstart自动化安装CentOS实践

基于Kickstart自动化安装CentOS实践 前言 因为需要在浪潮的x86服务器中集中部署CentOS搭建基于Hadoop的大数据平台,平时接触SLES(SuSE Linux Enterprise Server)较多并且已经实现基于Autoyast方式使用光盘或者PXE网络自动化安装(后续会分享具体实现方法).这次主要通过学习Kisckstart实现最简单的光盘方式自动化安装CentOS,而网上的大多数教程并不完全适用于自身的环境,本文将不再赘述Kickstart相关概念,细节可参考扩展阅读

python操作 hbase 数据的方法_python

配置 thrift python使用的包 thrift 个人使用的python 编译器是pycharm community edition. 在工程中设置中,找到project interpreter, 在相应的工程下,找到package,然后选择 "+" 添加, 搜索 hbase-thrift (Python client for HBase Thrift interface),然后安装包. 安装服务器端thrift. 参考官网,同时也可以在本机上安装以终端使用. thrift Ge