Оперативната база данни на Cloudera (COD) е управлявано dbPaaS решение, достъпно като опит в Cloudera Data Platform (CDP). Той предлага мултимодален клиентски достъп с NoSQL ключ-стойност, използвайки Apache HBase API и релационен SQL с JDBC (чрез Apache Phoenix). Последното прави COD достъпен за разработчици, които са свикнали да създават приложения, които използват MySQL, Postgres и др. Основните предимства на COD включват:
- Автоматично мащабиране – въз основа на използването на работното натоварване на клъстера и скоро ще има възможност за увеличаване/намаляване на клъстера
- Автоматична настройка – по-добра производителност в рамките на съществуващата инфраструктура.
- Автоматично заздравяване – разрешавайте оперативните проблеми автоматично (очаквайте скоро).
В този блог ще демонстрирам как COD може лесно да се използва като бекенд система за съхранение на данни и изображения за просто уеб приложение. За да създадем това приложение, ще използваме Phoenix, един от основните компоненти на COD, заедно с Flask. За съхраняване на изображения ще използваме възможност за HBase (задно съхранение на Apache Phoenix), наречена MOB (средни обекти). MOB ни позволява бързо да четем/записваме стойности от 100k-10MB.
*За улесняване на използване при разработка, можете също да използвате сървъра за заявки на Phoenix вместо COD. Сървърът за заявки е малка версия на phoenix, която е предназначена само за целите на разработката и данните се изтриват при всяка компилация.
Целият код е в моето репо на github.
Инструкции:
1. Влезте в конзолата за управление на Cloudera и изберете опит с оперативна база данни

2. Изберете вашата среда и наименувайте вашата DB

3. След като DB е готов, вземете URL от тънкия JDBC клиент

4. Задайте вашата парола за CDP за натоварване
5. Клонирайте проект git repo и изисквания за инсталиране:$ pip install -r requirements.txt
6. Отидете в папката на приложението и стартирайте “setup.py” – това ще създаде таблица с 3 записа на потребители и техните изображения $ python setup.py
7. Стартирайте уеб сървъра flask за стартиране на уеб приложението:$ FLASK_APP=app.py python -m flask run –port=8888 –host=127.0.0.1 –reload –with-threads –debugger
8. Отидете на https://localhost:8888/users във вашия браузър. Трябва да можете да видите как приложението работи! Просто толкова.

Преминаване през Кодекса
1. Класът Schema, по принцип съдържа подробностите за връзката и методите за създаване и пускане на таблица. Както можете да видите, колоната „снимка“ е тип VARBINARY, който се превежда в MOB обект в HBase:
import phoenixdb
import phoenixdb.cursor
class Schema:
def __init__(self):
opts = {}
opts['authentication'] = 'BASIC'
opts['avatica_user'] = '<cod workload username>'
opts['avatica_password'] = '<cod workload pw>'
database_url = "<cod thin jdbc url>"
self.TABLENAME = "users"
self.conn = phoenixdb.connect(database_url, autocommit=True,**opts)
self.curs = self.conn.cursor()
def create_users_table(self):
query = """
CREATE TABLE IF NOT EXISTS """+self.TABLENAME+""" (
username VARCHAR NOT NULL,
firstname VARCHAR,
lastname VARCHAR,
telephone VARCHAR,
message VARCHAR,
email VARCHAR,
photo VARBINARY,
photo_name VARCHAR,
photo_type VARCHAR,
photo_chars VARCHAR
CONSTRAINT my_pk PRIMARY KEY (username))
"""
self.curs.execute(query)
def drop_users_table(self):
query = "DROP TABLE "+self.TABLENAME
self.curs.execute(query) 2 Потребителският клас е отговорен за всички операции на приложението с Phoenix. Можем да актуализираме/вмъкваме (upsert на език Phoenix), изтриваме, изброяваме и обработваме транзакции с изображения:
import phoenixdb
from schema import Schema
import json
class UsersModel:
TABLENAME = "users"
def __init__(self):
db = Schema()
self.conn=db.conn
self.curs=db.curs
def upsert(self, params):
sql = "upsert into " + self.TABLENAME + \
" (username ,message,telephone,firstname,lastname,email) \
values (?,?,?,?,?,?)"
data = (params.get('username'),params.get('message'),\
params.get('telephone'),params.get('firstname'),\
params.get('lastname'),params.get('email'))
results = self.curs.execute(sql,data)
return results
def upsert_photo(self, params):
if params.get('photo') is None:
photo = bytes('','utf-8')
else:
photo = params.get('photo')
sql = "upsert into " + self.TABLENAME + \
" (username, photo,photo_name) values (?,?,?)"
data = (params.get('username'),photo, params.get('photo_name'))
results = self.curs.execute(sql,data)
return results
def delete(self, username):
query = f"DELETE from {self.TABLENAME} " \
f"WHERE username = {username}"
self.curs.execute(query)
def list_items(self, where_clause="",format="json"):
query = f"SELECT username ,email,message,telephone,firstname,\
lastname,photo_name " \
f"from {self.TABLENAME} WHERE " + where_clause
self.curs.execute(query)
if format=="json":
r = [dict((self.curs.description[i][0].lower(), value) \
for i, value in enumerate(row)) for row in \
self.curs.fetchall()]
self.conn.close()
data={'data': r }
return json.dumps(data)
result_set=self.curs.fetchall()
result = [{column: row[i]
for i, column in enumerate(result_set[0].keys())}
for row in result_set]
return result
def get_image(self, username):
query = f"SELECT photo,photo_name " \
f"from {self.TABLENAME} WHERE username='"+username+"'"
self.curs.execute(query)
row = self.curs.fetchone()
return row 3. App.py е основният рутер за приложението. Той съдържа цялата обработка с потребителски входове и насочването им към методите за свързване. Отделих обработката на изображения за по-лесно използване и по този начин мога да получа конкретно изображение за потребител:
from flask import Flask, request, send_file ,jsonify,render_template
import phoenixdb
import io
from users import UsersModel
from schema import Schema
import json
app = Flask(__name__)
@app.after_request
def add_headers(response):
response.headers['Access-Control-Allow-Origin'] = '*'
response.headers['Access-Control-Allow-Headers'] = \
"Content-Type, Access-Control-Allow-Headers, Authorization, \
X-Requested-With"
response.headers['Access-Control-Allow-Methods']= "POST, GET, PUT, \
DELETE, OPTIONS"
response.headers['Allow']= "POST, GET, PUT, OPTIONS"
return response
@app.route("/")
def hello():
return "Hello World!"
@app.route("/users")
def return_form():
return render_template("users.html")
@app.route("/handle_data",methods=['POST'])
def handle_data():
if request.method == 'POST':
username = request.form['username']
firstname = request.form['firstname']
lastname = request.form['lastname']
email = request.form['email']
telephone = request.form['telephone']
message = request.form['message']
photo = request.files['photo']
photo_bytes = photo.read()
model=Schema()
usersmodel=UsersModel()
data = {'username':f"{username}",'firstname':f"{firstname}",\
'lastname':f"{lastname}",'telephone':f"{telephone}",\
'message':f"{message}"}
photo_data = {'username':f"{username}",\
'photo':photo_bytes,\
'photo_name':f"{photo.filename}"}
usersmodel.upsert(data)
usersmodel.upsert_photo(photo_data)
return render_template('users.html')
else:
return render_template('users.html')
@app.route("/get_users",methods=['GET'])
def get_users():
if request.method == 'GET':
usersmodel=UsersModel()
users = usersmodel.list_items("1=1")
return users
@app.route("/get_image",methods=['GET'])
def get_image():
if request.method == 'GET':
username = request.args.get('username')
usersmodel=UsersModel()
imagedb = usersmodel.get_image(username)
return send_file(io.BytesIO(imagedb[0]),mimetype='image/png', \
attachment_filename=imagedb[1])
if __name__ == "__main__":
Schema()
app.run(debug=True, port=8888) Следващите стъпки, можете да използвате това github репо, за да тествате приложението си.
Надявам се да го намерите полезен, Приятно кодиране!!