秦悦明的运维笔记

hbase-Standalone单机模式

1. 环境

只用文件系统,不用hdfs,也就是说不需要之前安装好hadoop分布式环境。java必须安装好。

2. 配置conf/hbase-site.xml

1
2
3
4
5
6
7
8
9
10
<configuration>
<property>
<name>hbase.rootdir</name>
<value>file:///home/testuser/hbase</value>
</property>
<property>
<name>hbase.zookeeper.property.dataDir</name>
<value>/home/testuser/zookeeper</value>
</property>
</configuration>

目录不用创建,hbase会自动创建。

3. 启动hbase

1
bin/start-hbase.sh

单机模式下会起一个jvm, 名字叫HMaster,会起一个web ui,端口是16010。

4. hbase使用

用shell:

1
2
$ ./bin/hbase shell
hbase(main):001:0>

创建table:

1
2
3
4
hbase(main):002:0> create 'test', 'cf'
0 row(s) in 2.2080 seconds
=> Hbase::Table - test

list信息:

1
2
3
4
5
6
hbase(main):003:0> list 'test'
TABLE
test
1 row(s) in 0.0610 seconds
=> ["test"]

put数据:

1
2
3
4
5
6
7
8
hbase(main):008:0* put 'test', 'row1', 'cf:a', 'value1'
0 row(s) in 0.6360 seconds
hbase(main):009:0> put 'test', 'row2', 'cf:b', 'value2'
0 row(s) in 0.0540 seconds
hbase(main):010:0> put 'test', 'row3', 'cf:c', 'value3'
0 row(s) in 0.0290 seconds

scan数据:

1
2
3
4
5
6
hbase(main):012:0> scan 'test'
ROW COLUMN+CELL
row1 column=cf:a, timestamp=1482133616796, value=value1
row2 column=cf:b, timestamp=1482133663870, value=value2
row3 column=cf:c, timestamp=1482133670211, value=value3
3 row(s) in 0.0930 seconds

获取一列数据:

1
2
3
4
hbase(main):021:0> get 'test','row2'
COLUMN CELL
cf:b timestamp=1482133663870, value=value2
1 row(s) in 0.0080 seconds

disable table:

1
2
hbase(main):022:0> disable 'test'
0 row(s) in 2.2930 seconds

删除数据:

1
2
hbase(main):023:0> drop 'test'
0 row(s) in 1.2720 seconds

spring-javabean

1. 通过java代码装配bean。

比如将第三方库中的组件装配到你的应用中时,没法使用组件扫描和自动装配,这时候就需要用到显示配置了,
有两种选择:

  1. java
  2. XML

javaConfig和java代码类似,使用简单。

2. 创建配置类

关键在于添加@Configuration注解。

1
2
3
4
5
6
import org.springframework.context.annotation.Configuration;
@Configuration
public class CDPlayerConfig {
...
}

显示创建也就不需要之前的@ComponentScan注解了。

3. 声明简单的bean

编写一个方法,这个方法创建所需类型的实例,然后给这个方法添加@Bean注解。

1
2
3
4
5
6
7
8
9
@Bean
public CompactDisc compactDisc() {
return new SgtPeppers();
}
@Bean
public CompactDisc sgtPeppers(){
return new SgtPeppers();
}

4. JavaConfig注入

javaConfig最简单的方法是引用创建bean的方法。

1
2
3
4
@Bean
public CDPlayer cdPlayer() {
return new CDPlayer(sgtPeppers());
}

cdPlayer可以直接请求一个CompactDisc作为参数,调用cdPlayer()创建CDPlayer bean的时候,Spring就自动装配一个CompactDisc到配置方法之中。实现了DI。代码如下:

1
2
3
4
5
6
7
8
@Bean
public CompactDisc compactDisc() {
return new SgtPeppers();
}
@Bean
public CDPlayer cdPlayer(CompactDisc compactDisc) {
return new CDPlayer(compactDisc);
}

Spring-组件扫描

spring会自动发现应用上下文中所创建的bean。

创建一个CDPleaer类,让Spring发现它,并将CompactDisc bean注入进来。

SgtPeppers.java
主要是用@Component注解,表明该类会作为一个组件类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package soundsystem;
import org.springframework.stereotype.Component;
@Component
public class SgtPeppers implements CompactDisc {
private String title = "Sgt. Pepper's Lonely Hearts Club Band";
private String artist = "The Beatles";
public void play() {
System.out.println("Playing " + title + " by " + artist);
}
}

不过组件扫描默认是不启用的,得配置一下Spring,让他去寻找带有@Component的组件,如下:
CDPlayerConfig.java

1
2
3
4
5
6
7
8
package soundsystem;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
public class CDPlayerConfig {
}

然后通过CDPlayerTest.java类来测试。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package soundsystem;
import static org.junit.Assert.*;
import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.StandardOutputStreamLog;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=CDPlayerConfig.class)
public class CDPlayerTest {
@Autowired
private CompactDisc cd;
@Test
public void cdShouldNotBeNull() {
assertNotNull(cd);
}
}
1
2
3
4
5
6
7
8
9
10
11
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:compileTestJava
:processTestResources UP-TO-DATE
:testClasses
:test
BUILD SUCCESSFUL
Total time: 16.894 secs

gradle测试通过,说明SgtPeppers被很好的创建出来了,不为空。

flask-bootstrap和表单

1.bootstrap安装

1
pip install flask-bootstrap

2.初始化bootstrap

1
2
3
from flask_bootstrap import Bootstrap
...
bootstrap = Bootstrap(app)

3.制作自己的基模板

初始化bootstarp以后就可以继承bootstrap文件的基模板了

1
2
3
{% extends "bootstrap/base.html" %}
{% block title %}Flasky{% endblock %}
...

4.Form表单

主要用Flask-WTF包

1
pip install flask-wtf

Flask-WTF是wtforms的一个扩展,两个包都要引入。

5.设置SCRF保护

1
2
app = Flask(__name__)
app.config['SECRET_KEY'] = 'hard to guess string'

6.Form类

跟django的套路差不多,都要继承一个Form父类,

1
2
3
4
5
6
from flask_wtf import Form
from wtforms import StringField, SubmitField
from wtforms.validators import Required
class NameForm(Form):
name = StringField('What is your name?', validators=[Required()])
submit = SubmitField('Submit')

7.模板

可以直接写html

1
2
3
4
5
<form method="POST">
{{ form.hidden_tag() }}
{{ form.name.label }} {{ form.name() }}
{{ form.submit() }}
</form>

或者直接用Flask-bootstrap的辅助函数一次生产这个form

1
2
{% import "bootstrap/wtf.html" as wtf %}
{{ wtf.quick_form(form) }}

8.处理表单

1
2
3
4
5
6
7
8
@app.route('/', methods=['GET', 'POST'])
def index():
name = None
form = NameForm()
if form.validate_on_submit():
name = form.name.data
form.name.data = ''
return render_template('index.html', form=form, name=name)

methods里面加入POST请求。如果没有指定,只能路由GET请求。
如果提交的数据通过验证,则validate_on_submit返回True,把name字段清空,并且把数据传到模板里面去。

flask模板

1.简单实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from flask import Flask, render_template
from flask_script import Manager
app = Flask(__name__)
mamanger = Manager(app)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/user/<name>')
def user(name):
return render_template('user.html', name=name)
if __name__ == '__main__':
mamanger.run()

最简单的模板,render_template,跟django里面用法差不多。

模板支持if,for等语句。
更能支持宏macro等强大用法。
还可以支持继承.

2.模板继承

这里重点说说继承,extends

base.html

1
2
3
4
5
6
7
8
9
10
11
<html>
<head>
{% block head %}
<title>{% block title %} {% endblock %} - My application </title>
{% endblock %}
</head>
<body>
{% block body %}
{% endblock %}
</body>
</html>

user.html

1
2
3
4
5
6
7
8
9
10
{% extends "base.html" %}
{% block title %} index {% endblock %}
{% block head %}
{{ super() }}
<style>
</style>
{% endblock %}
{% block body %}
<h1>hello, {{ name }}!</h1>
{% endblock %}

block标签定义的元素可在衍生模板中修改。user.html里面重新定义了title,head,body。定义head的时候用到了base.html里面的内容,需要调用super()即可,跟面向对象语法里面的一模一样。
完整例子可以参看github https://github.com/gqdw/study-flk 里面的test-templates。