HBase
 sql >> Baza danych >  >> NoSQL >> HBase

Budowanie prostej aplikacji internetowej CRUD i sklepu z obrazami przy użyciu operacyjnej bazy danych Cloudera i Flask

Cloudera Operational Database (COD) to zarządzane rozwiązanie dbPaaS dostępne jako doświadczenie w Cloudera Data Platform (CDP). Oferuje wielomodalny dostęp klienta za pomocą klucza i wartości NoSQL przy użyciu interfejsów API Apache HBase i relacyjnego SQL z JDBC (poprzez Apache Phoenix). Ten ostatni sprawia, że ​​COD jest dostępny dla programistów, którzy są przyzwyczajeni do tworzenia aplikacji korzystających z MySQL, Postgres itp. Główne zalety COD to:

  • Automatyczne skalowanie – w oparciu o wykorzystanie obciążenia klastra i wkrótce będzie mieć możliwość skalowania w górę/w dół klastra
  • Automatyczne dostrajanie – lepsza wydajność w ramach istniejącej infrastruktury.
  • Auto-naprawa – automatycznie rozwiąż problemy operacyjne (wkrótce).

W tym blogu pokażę, jak COD można łatwo wykorzystać jako system zaplecza do przechowywania danych i obrazów dla prostej aplikacji internetowej. Do budowy tej aplikacji będziemy używać Phoenix, jednego z podstawowych komponentów COD, wraz z Flask. Do przechowywania obrazów będziemy używać funkcji HBase (magazyn zaplecza Apache Phoenix) o nazwie MOB (obiekty średnie). MOB pozwala nam na szybki odczyt/zapis wartości od 100k-10MB.

*W celu ułatwienia programowania można również użyć serwera zapytań Phoenix zamiast COD. Serwer zapytań to niewielka wersja programu Phoenix, która jest przeznaczona wyłącznie do celów programistycznych, a dane są usuwane w każdej wersji.

Cały kod znajduje się w moim repozytorium github.

Instrukcje:

1. Zaloguj się do Konsoli Zarządzania Cloudera i wybierz doświadczenie operacyjnej bazy danych

2. Wybierz swoje środowisko i nazwij bazę danych

3. Po uruchomieniu bazy danych pobierz adres URL z cienkiego klienta JDBC

4. Ustaw hasło obciążenia CDP

5. Sklonuj repozytorium git projektu i wymagania instalacyjne:$ pip install -r wymagania.txt

6. Przejdź do folderu aplikacji i uruchom „setup.py” – spowoduje to utworzenie tabeli z 3 rekordami użytkowników i ich obrazami $ python setup.py

7. Uruchom serwer sieciowy flask, aby uruchomić aplikację sieciową:$ FLASK_APP=app.py python -m flask run –port=8888 –host=127.0.0.1  –reload –with-threads –debugger

8. Przejdź do http://localhost:8888/users w swojej przeglądarce. Powinieneś być w stanie zobaczyć uruchomioną aplikację! To proste.

Przeglądanie Kodeksu

1. Klasa Schema zasadniczo przechowuje szczegóły połączenia oraz tworzy i usuwa metody tabel. Jak widać, kolumna „photo” jest typem VARBINARY, co przekłada się na obiekt MOB w 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 Klasa users odpowiada za wszystkie operacje aplikacji w Phoenix. Możemy aktualizować/wstawiać (upsert w języku feniksa), usuwać, wyświetlać i obsługiwać transakcje dotyczące obrazów:

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 jest głównym routerem aplikacji. Zawiera całą obsługę danych wejściowych użytkownika i kierowanie ich do metod połączenia. Oddzieliłem obsługę obrazów dla łatwości użytkowania, dzięki czemu mogę uzyskać konkretny obraz dla użytkownika:

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)

Kolejne kroki, możesz użyć tego repozytorium github do przetestowania swojej aplikacji.

Mam nadzieję, że okaże się to przydatne, miłego kodowania!


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Silniki przetwarzania dużych zbiorów danych – którego mam używać?:Część 1

  2. Wewnątrz architektury Santander do przetwarzania danych w czasie zbliżonym do rzeczywistego

  3. Magazynowanie danych nowej generacji w Santander UK

  4. Hadoop RecordReader Wstęp, Working &Rodzaje

  5. Przegląd replikacji Apache HBase