Bezpieczeństwo w PASOE cz. II

Część druga bezpieczeństwa w PASOE to raczej tylko suplement, związany z uwierzytelnieniem i autoryzacją użytkowników opartym o dane w plikach tekstowych w podkatalogu serwera aplikacji.

Po pierwsze, autoryzacja użytkowników z pliku users.properites. Każdy z nich ma przypisana rolę np.: ROLE_PSCUser, ROLE_PSCAdmin, ROLE_PSCDebug czy ROLE_None.

Skąd wiadomo, co te role oznaczają i gdzie są zdefiniowane? Żeby się dowiedzieć trzeba otworzyć plik: [working directory]\[instancja pasoe]\webapps\ROOT\WEB-INFF\oeablSecurity.csv.

Pliku oeablSecurity.csv określa kontrolę dostępu do adresów URL dla aplikacji webowych. Każdy wiersz w pliku jest uporządkowanym zestawem trzech wartości.

Odpowiadają one trzem atrybutom elementu przechwytującego URL w Spring Security, a mianowicie:
– wzorzec – wzorzec adresu URL, który może zawierać symbole wieloznaczne i wyrażenia regularne
– metoda – metoda dostępu HTTP
– dostęp – dozwolone role dostępu do zasobu.

Na poniższym obrazku widzimy kontrole dostępu dla poszczególnych warst transportowych. Najpierw APSV (metody HAD, GET, POST) i role, potem SOAP, REST, WEB, a następnie bardziej szczegółowe definicje dla wybranych URI.

Dodajmy, że ustawienia w tym pliku oraz w oeablSecurity.properties znajdują się w kilku lokalizacjach i mają charakter hierarchiczny, np. plik oeablSecurity.csv znajdziemy także w: [working directory]\[instancja pasoe]\conf\oeablSecurity.properties.csv, a oeablSecurity.properties jeszcze w kilku miejscach.

Pliki te bardziej zagnieżdżone dziedziczą ustawienia od plików znajdujących się w podkatalogach powyżej. Dzięki temu można precyzyjnie określić zabezpieczenia dla całej instancji PASOE, aplikacji ABL (agenta wielosesyjnego) czy aplikacji WEB.

Do tej pory podawane przez nas hasła były w postaci jawnej. Co jednak zrobić żeby je zaszyfrować, tak aby haker, który skopiuje pliki z dysku nie miał z nich pożytku?

Sprawa jest bardzo prosta. Po pierwsze zmieniamy nazwę procesu managera uwierzytelniającego dane z local na extlocal.

 

[working directory]\[instancja pasoe]\webapps\ROOT\WEB-INFF\oeablSecurity.properties.

Wartość parametru client.login.model=form lub basic.

Szyfrujemy hasło poleceniem: genspringpwd [hasło], np. genspringpwd password

Otrzymujemy: $2a$09$EU0wp9hga2zmfKBUg21nAeVObPBQQ3erbW53XCcJiQYr8s4QwoCki i tę wartość wstawiamy do pliku users.properites w miejsce jawnego hasła np. dla użytkownika myrestuser.

Restartujemy PASOE i logujemy się wpisując hasło niezaszyfrowane.

Sprawdzamy, że logowanie się powiodło.

Bezpieczeństwo w PASOE cz. I

Większość nowoczesnych, rozproszonych aplikacji korzysta z serwera aplikacji
dla logiki biznesowej. Korzystanie z serwera PASOE jest bardzo dobrym rozwiązaniem
ponieważ może on bezpośrednio obsługiwać wszystkie typy klientów, jest łatwo skalowalny oraz
może zapewnić bezpieczeństwo aplikacji przy użyciu Spring Security.

Spring Security to framework, który koncentruje się na zapewnianiu uwierzytelniania i autoryzacji dla aplikacji.
Spring Security można rozszerzyć w celu spełnienia niestandardowych wymagań. Poziom bezpieczeństwa zależy od nas, ponieważ to my decydujemy, którą technologię zabezpieczeń wybieramy (lokalne pliki, LDAP, OEREALM, STS i inne).

PASOE zawsze uruchamia Spring Security w sposób domyślny. Nawet próba dostępu do serwisu REST przez użytkownika anonymous wywoła proces uwierzytelniania, autoryzacji i ew. utworzenia tokena Spring Security oraz obiektu ABL CLIENT-PRINCIPAL.

Żeby to zademonstrować, stwórzmy i wystartujmy przykładowy serwer PASOE (ja nazwę go mysec). Od wersji OE12.1 każdy serwer aplikacji startuje serwis ping – jest on dostępny pod adresem URL:
http://localhost:[port]/rest/_oepingService/_oeping


Oznacza to, że PASOE wystartował i mamy dostęp do serwisu ping.

Zobaczmy jakie są domyślne ustawienia dla tego serwisu, który procuje w web aplikacji ROOT. Otwieram plik oeablSecurity.properties w lokalizacji C:\WrkOpenEdge121\mysec\webapps\ROOT\WEB-INF.

Znajdujemy wpis: client.login.model=anonymous.

Oznacza on, że każdy użytkownik (anonymous) ma dostęp do wszystkich aplikacji w ROOT.

Powyżej, widzimy wpis: http.all.authmanager=local. Oznacza on, że uwierzytelnienie jest lokalne w oparciu o użytkowników zdefiniowanych w pliku:
C:\WrkOpenEdge121\mysec\webapps\ROOT\WEB-INFF\users.properites.
Zawartość tego pliku jest następująca:

restuser=password,ROLE_PSCUser,enabled
restdebug=password,ROLE_PSCUser,ROLE_PSCAdmin,ROLE_PSCDebug,enabled
restadmin=password,ROLE_PSCUser,ROLE_PSCAdmin,enabled
restnone=password,ROLE_None,enabled

Chcemy teraz wymusić logowanie ze strony użytkownika – ustawiamy wartość client.login.model=form.
Restartujemy PASOE i ponawiamy dostęp do URL oeping.
Bazując na danych w pliku users.properties wpisujemy: restuser i password. W efekcie dostajemy dostęp do serwisu (patrz. pierwszy rysunek).


Żeby pokazać, że dostaliśmy token od systemu, otwórzmy nową kartę w przeglądarce (ta sama sesja) i wpiszmy URL dla serwisu ping. Dostajemy od razu dostęp, bez logowania.

Jeśli podamy dane restnone i password lub jakiekolwiek inne, nie występujące w pliku, dostęp jest zabroniony.

Dodajmy teraz do pliku users.properties własnego użytkownika, o uprawnieniach takich jak restuser i zmieńmy nazwę na myrestuser.

restuser=password,ROLE_PSCUser,enabled
myrestuser=password,ROLE_PSCUser,enabled
restdebug=password,ROLE_PSCUser,ROLE_PSCAdmin,ROLE_PSCDebug,enabled
restadmin=password,ROLE_PSCUser,ROLE_PSCAdmin,enabled
restnone=password,ROLE_None,enabled

Aby zmiany zostały wczytane, restartujemy PASOE komendą:
pasman pasoestart -v -I mysec -restart

Logujemy się jako nowy użytkownik…

…który ma dostęp do serwisu rest.

O dalszych podstawach zabezpieczeń napiszę w drugiej części.

PASOE i Load Balancing

Użytkownicy klasycznego AppServera pamiętają zapewne możliwość dość łatwej implementacji load balancingu, wykorzystującego proces przekierowujący NameServer.
W nowym serwerze aplikacji PASOE nie ma NameServera, nawet proces AdminServera nie jest niezbędny, jak zatem można zrealizować usługę LB?

Aby to osiągnąć musimy wykorzystać istniejące rozwiązania innych firm. Dostępnych jest wiele produktów i ciężko jest wybrać jedną najlepszą opcję load balancingu do wszystkich zastosowań, dla każdego z klientów. Najbardziej znane to: Apache proxy LB, Tomcat LB i Amazon Elastic LB. Skupmy się na dwóch pierwszych rozwiązaniach. Oba wykorzystują popularny serwer Apache.

Apache proxy LB – popularny serwer Apache HTTP działa tutaj jako serwer proxy przekierowujący żądania HTTP do adresu URL, który jest unikalny dla każdej instancji PASOE. Ta metoda nie wymaga konfiguracji po stronie PASOE gdyż całe równoważenie obciążenia wykonywane jest przez serwer Apache.

Wadą tego typu rozwiązania jest to, że serwer Apache nie monitoruje statusu uruchomionych instancji i jeśli któraś z nich ulegnie awarii, serwer kontynuuje próbę wysyłania żądań do niedostępnej instancji i żądania zostają utracone.

Tomcat load balancing – równoważenie obciążenia realizuje tutaj wyznaczona instancja PASOE, która musi nazywać się lb (lub jklb). Jest to jej jedyne zadanie i jeśli instancja ma wdrożone jakiekolwiek aplikacje (np. ROOT) należy je usunąć (undeploy). Poniższy rysunek ilustruje przykładową konfigurację. Oprócz instancji lb można utworzyć opcjonalnie instancję do monitorowania procesu równoważenia. Musi się ona nazywać status (lub jkstatus) i także nie może mieć wdrożonych żadnych aplikacji.

Jednakże, wdrożenie load balancingu jest także możliwe gdy obie w/w instancje są skonfigurowane tylko wirtualnie, tzn. bez ich fizycznego utworzenia (bez komendy tcman create lub pasman create). Jaka jest różnica tego drugiego rozwiązania? Jest nieco łatwiejsze i bardziej nadaje się do demonstracji. Można je także wykorzystać w lokalnej instalacji. W produkcyjnym środowisku lepiej skorzystać z pierwszego sposobu i możliwości jakie dają nam fizyczne instancje PASOE, szczególnie jeśli idzie o bezpieczeństwo.

Tutaj omówię drugi, krótszy sposób. Na początek musimy mieć zainstalowany web serwer  Apache np. 2.4 (w sumie można użyć innego web serwera ale Apache jest najczęściej stosowany ze względu choćby na wspólna konfigurację Apache i Tomcata). Działanie serwera można rozszerzyć poprzez załadowanie odpowiednich modułów, i tak w pliku  conf\httpd.conf odkomentowujemy linie:

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule slotmem_shm_module modules/mod_slotmem_shm.so

To powinno wystarczyć, ale dla konkretnej wersji Apache może okazać się, że potrzebny jeszcze jakiś moduł; sprawdzajcie logi jeśli są kłopoty z uruchomieniem.

Teraz tworzymy przykładowe 2 instancje PASOE , między którymi będzie rozkładać się obciążenie. Nazwiemy je node1 i node2.

pasman create -p 8815 -P 8816 -s 8817 -j 8818 %WRKDIR%\node1
pasman create -p 8825 -P 8826 -s 8827 -j 8828 %WRKDIR%\node2

Teraz powiem kilka słów o powyższych instrukcjach. Pasman jest tą samą instrukcją co tcman, ale ma charakter jedynie globalny, tzn. nie ma tej instrukcji w podkatalogu bin dla instancji, przez co łatwiej z niej korzystać w przypadku zarządzania kilkoma instancjami. Stosuje się tutaj parametr -I, po którym podajemy nazwę instancji.

Zwróćcie uwagę, że oprócz 3 portów, podałem jeszcze czwarty oznaczony jako -j dla protokołu AJP13

Jest to binarny protokół, który umożliwia przesyłanie żądań z serwera WWW do serwera aplikacji. Jest on powszechnie stosowany w systemach ze równoważeniem obciążenia; obsługuje również monitorowanie stanu serwera.

Po utworzeniu instancji musimy aktywować protokół AJP13 w pliku conf/server.xml dla każdej instancji.

pasman feature -I node1 AJP13=on
pasman feature -I node2 AJP13=on

Krótka uwaga – zdecydowanie nie zalecam dokonywania zmian w pliku server.xml ręcznie, gdyż łatwo przy tym o błędny wpis i kłopot z prawidłowym uruchomieniem instancji PASOE.

Teraz trzeba skonfigurować obie instancje tak, aby obsługiwały naszą aplikację: ustawić połączenie z bazą, sprawdzić czy są włączone protokoły APSV / REST / WEB / SOAP,
warto wdrożyć (jeśli nie są) manager.war i oemanager.war oraz na koniec jakąś aplikację do testowania. Tych czynności nie będę tutaj opisywał bo była już wcześniej o nich mowa.

Uruchamiamy instancji node1 komendę tcman workers (lub pasman workers -I node1). W podkatalogu utworzy się plik w podkatalogu node1\temp\workers.properties z wygenerowanymi ustawieniami dla load balancingu. Ustawienia te należy traktować raczej jako wzorzec ponieważ wymagają pewnej edycji.

Do tego pliku za chwilę wrócimy; teraz w pliku Apache conf\httpd.conf na samym końcu dodajemy ustawienia:

#workers.properties load balancing config
LoadModule jk_module modules/mod_jk.so
JkWorkersFile C:/Apache24/lbfiles/conf/workers.properties
JkShmFile C:/Apache24/lbfiles/logs/mod_jk.shm
JkLogFile C:/Apache24/lbfiles/logs/mod_jk.log
JkLogLevel info
JkLogStampFormat "[%a %b %d %H:%M:%S %Y]"
JkMount /* jklb
JkMount /status jkstatus 

Jest tutaj ładowany jeszcze jeden moduł mod_jk.so, jeśli nie ma go w instalacji trzeba pobrać go z sieci i dodać katalogu modules. Wygodnie jest umieścić dane związane z LB w osobnym katalogu, tutaj jest to katalog lbfiles.

W tym katalogu musimy umieścić plik workers.properties odpowiednio skorygowany. Załączam plik z ustawieniami dla niniejszego przykładu.

# List of worker server instances
worker.list=jklb,jkstatus
#
# Global properties
#
# worker.maintain=60
# Common worker properties referenced by individual workers
worker.common.type=ajp13
worker.common.host=PCPTU3
worker.common.socket_timeout=10
worker.common.connect_timeout=10000
worker.common.socket_keepalive=true
worker.common.ping_mode=I
worker.common.ping_timeout=10000
worker.common.retry_interval=100
worker.common.recovery_options=7
# worker.common.connection_ping_interval=10000
# worker.common.fail_on_status=0
# worker.common.max_packet_size=8192
# worker.common.recover_time=60

 

# properties for alias node1 with jvmRoute node1
worker.node1.port=8818
worker.node1.reference=worker.common
worker.node1.lbfactor=1

# properties for alias node2 with jvmRoute node2
worker.node2.port=8828
worker.node2.reference=worker.common
worker.node2.lbfactor=1

# Load balancer directives
worker.jklb.type=lb
#worker.jklb.port=8012
worker.jklb.balance_workers=node1,node2
worker.jklb.method=Request

# Status worker directives
worker.jkstatus.type=status
worker.jkstatus.read_only=False

Omówię niektóre ustawienia: worker.list=jklb,jkstatus – to lista instancji wirtualnych do LB i do monitorowania. Sa również ustawienia dla maszyn z obiema instancjami node1 i node2 (tutaj wszystko znajduje się na jednej maszynie).

worker.jklb.balance_workers=node1,node2 – to lista instancji obsługujących żądania klienckie. Na uwagę zasługują ustawienia: worker.node1.lbfactor=1 oraz worker.node2.lbfactor=1. Określają one udział instancji w procesie obsługi żądań. W tym przypadku podział jest 50%/50%. Jeśli np. node1 ma obsługiwać 2 razy więcej żądań to współczynnik trzeba ustawić 2 razy większy niż node2.

Startujemy obie instancje. Jaki będzie port w adresie URL jeśli mamy kilka instancji PASOE, obsługujących tą samą aplikację? Port w adresie będzie wskazywać na Apache serwer (domyślnie 80), reszta pozostaje bez zmian. Odświeżamy kilka razu adres URL, generując żądania do obsługi.

Jeśli chcemy podejrzeć status LB to podajemy w adresie URL: nazwa_hosta_lb/status, czyli tutaj: localhost/status.

Widać m.in, że obie instancje są aktywne, node2 ma mniej obsłużonych żądań i 2 błędy, co jest związane z moim czasowym wyłączeniem tej instancji (dla testu). Większość oznaczeń jest opisana po najechaniu na nie kursorem. To na razie tyle, jeśli chodzi o Load Balancing.

OpenEdge Explorer

OpenEdge Explorer nie jest tematem nowym. To okrojona wersja systemu OpenEdge Management (dawniej Fathom Management) który pojawił się w wersji Progress V9.

Wszystkie wymienione powyżej produkty mają głównie za zadanie monitorowanie parametrów systemów operacyjnych i komponentów Openedge (bazy danych, serwery aplikacji itd). Dotyczy to zarówno lokalnego komputera jak i maszyn zdalnych, a wszystko to z jednej konsoli w przeglądarce internetowej. Oprócz monitorowania można także zarządzać komponentami OE: konfigurować, uruchamiać, zatrzymywać itp. W opcji Database Administration znajdują się ponadto dodatkowe możliwości związane z obsługą funkcji baz danych. Tyle w dużym skrócie.

OE Explorer (OEE) jest, jak wspomniałem, uboższą wersją OE Management (OEM). Nie ma np. możliwości zapisu parametrów do specjalnej bazy (trending data), definiowania alertów, wyświetlania graficznych widoków, ale ma te zaletę, że jest darmowy (instaluje się automatycznie z większością licencji od wersji OE 10.2B).

Jak uruchamiamy OEE: możemy kliknąć w ikonkę OE Explorer, ale najlepiej w przeglądarce wpisać URL: localhost:9090.

Aby system wystartował musi być uruchomiony AdminServer. Sprawdzamy jego status komendą w oknie Proenv: proadsv -query i jeśli proces nie pracuje uruchamiamy go komendą: proadsv -start.

Teraz sprawdzamy czy uruchomiony jest OEE: fathom -query i w razie konieczności uruchamiamy go: fathom -start.

Teraz już powinniśmy mieć system uruchomiony. Na starcie jesteśmy proszeni o zmianę hasła. Gdybyśmy mieli pełny produkt OEM to trzeba byłoby jeszcze zdefiniować mail server (powiadomienia o przekroczeniu zdefiniowaniu wartości), bazę do przechowywania trending data itd. W OEE po zmianie hasła mamy od razu widok podobny jak na poniższym rysunku.

Aby monitorować bazę danych definiujemy nowy element Resources -> OpenEdge -> Database. Database Migration Utility służy do skonfigurowania istniejącej już bazy przy czym serwer musi być uruchomiony z podaniem numeru lub nazwy portu.

Klikając na Database Administration możemy zarządzać funkcjami np. opisanymi wcześniej Table Partitioning czy Change Data Capture, Multi-tenancy itp. Funkcje te włączamy w bazie jak na rysunku poniżej. Tych funkcjonalności nie znajdziemy w graficznym narzędziu Data Administration.

Listę włączonych funkcji widać na rysunku po prawej stronie poniżej.

Można tutaj także edytować dane zabezpieczeń (Data Security), przeglądać schemat danych, …

… zrzucać i ładować dane tabel.

W zasobach bazy danych większość widoków jest nieaktywnych dla OEE, ale w widoku Performance Summary mamy ciekawe zestawienie aktualnych parametrów:

Od razu widać, że podobne informacje możemy uzyskać poprzez narzędzie PROMON, ale o ile promon zbiera dane tylko dla bazy lokalnej, to w OEE mamy dostęp dla baz zdalnych. W ten sposób z jednej konsoli można monitorować bazy danych i inne procesy np. serwery aplikacji, data serwery itd.

A propos serwerów aplikacji: poniżej zamieszczam widok dla PASOE, aplikacja ROOT. Dla zainteresowanych tym serwerem, w OEE i OEM 12 nie ma wsparcia dla web serwisów SOAP.

Podsumowując to krótkie zestawienie, OpenEdge Explorer jest użytecznym narzędziem dla administratorów baz, niezbędnym przy konfigurowaniu nowych funkcji jak partycjonowanie tabel czy multi-tenancy oraz do monitorowania zasobów zdalnych.

Partycje Tabel OpenEdge cz. III

Zanim przejdę do kolejnej części związanej z partycjami tabel, winien jestem odpowiedzi na pytanie związane z definiowaniem zasad partycjonowanie.
Otóż kilku z Was chciało wiedzieć czy jest planowana możliwość definiowania podziału danych w tabeli w oparciu nie o wartość pola, lecz o funkcję (np. YEAR(TODAY)-1).
Miałem okazję niedawno rozmawiać z Richem Banvill’em – odpowiedzialnym za rozwój bazy OpenEdge. Taka możliwość nie jest w planach, ani w wersji OE12 ani w dalszej przyszłości.
Rich wspomniał, że problem ten można rozwiązać np. poprzez zdefiniowanie zadań w cronie.

Wróćmy jednak do tematu. W poprzedniej części zakończyliśmy podział tabeli w oparciu o wartości pola Country (lokalny idex). Wspomniałem, że partycjonowanie jest transparentne dla aplikacji, jednakże mogą zdarzyć się sytuacje gdy zapytanie zwraca nie te same rekordy co przed partycjonowaniem. Jednym z przykładów jest stosowanie w kodzie wyszukiwania po adresach RECID/ROWID. Ponieważ partycjonowanie przenosi rekordy, ich fizyczne adresy ulegają zmianom. W przypadku stosowania tego rozwiązania trzeba wprowadzić odpowiednie poprawki w kodzie aplikacji.

Innym, częstszym przykładem jest stosowanie w zapytaniu filtra na dane pole (WHERE). Ponieważ w partycjonowanej tabeli dodany jest zazwyczaj nowy, lokalny index, wyszukiwanie może być realizowane w oparciu o niego. Aby mieć pewność, że index nie został zmieniony i aby zachować ten sam porządek rekordów trzeba ew. dopisać frazę USE-INDEX.

Teraz trzeba wspomnieć o ważnej funkcji technologi partycjonowania tzw. pruning (okrajanie partycji).

Proces pruningu analizuje automatycznie zapytanie i (o ile to możliwe) nie bierze pod uwagę rekordów w partycjach, które nie spełniają warunków zapytania. Na rysunku widać przykład podziału rekordów na kwartały wg pola OrderDate. Jeśli w zapytaniu warunki będą dotyczyły rekordów tylko z kwartału drugiego, to tylko ta jedna partycja będzie w użyciu. Technologia ta może znacząco wpłynąć na poprawę wydajności.

Następnym zagadnieniem jest stosowanie frazy TABLE-SCAN. Powoduje ona pobranie rekordów bez dostępu do indexów i wyświetlenie ich w porządku, w jakim znajdują się w blokach bazy. Porządek rekordów zmieni się więc po partycjonowaniu, ze względu na przeniesienie ich do innych bloków. Przed pobieraniem wykonywana jest operacja pruning. Zobaczmy poniższy przykład:

FOR EACH order WHERE country = “USA” AND
  OrderDate >= 10-01-2014 AND
  OrderDate <= 12-31-2014 TABLE-SCAN:
DISPLAY OrderNum...

Jak widać, partycjonowanie tabel może wpłynąć na porządek przetwarzanych rekordów. Zobaczmy teraz jak wygląda sytuacja z tworzenie nowych rekordów i ich edytowaniem.

Należy pamiętać, że rekordy muszą mieć określone wartości dla pól, wg których odbywa się partycjonowanie. Dlatego warto stosować instrukcję ASSIGN grupującą ustawienia wartości dla rekordu, zaraz po instrukcji CREATE. Instrukcja ASSIGN wymusza fizyczne utworzenie rekordu w bazie, a więc zadziałanie mechanizmu portycjonowania. Poniższy przykład wywoła błąd (partycjonowanie po polu Country).

CREATE order.
ASSIGN ordernum = NEXT-VALUE(next-ord-num). /* ERROR! */
ASSIGN country = “USA”. 

Przykład ten łatwo poprawić do postaci:

CREATE order.
ASSIGN ordernum = NEXT-VALUE(next-ord-num)
       country = “USA”.

Edycja pola rekordu, wg którego realizowany jest podział tabeli niesie ze sobą przeniesienie całego rekordu do innego obszaru, a więc skasowanie rekordu, utworzenie go w nowym obszarze, aktualizacja indexów. Zbyt częste takie operacje mogą nieść ze sobą obniżenie wydajności. Może to być wynikiem niewłaściwie wybranego klucza partycji, co warto przedyskutować i ew. wybrać inny klucz.

 

 

Partycje Tabel OpenEdge cz. II

W poprzedniej części zapoznaliśmy się nieco z częścią teoretyczną, dotyczącą partycjonowania tabel OpenEdge. Teraz czas zrobić coś w praktyce.

Tworzymy nową bazę np. mytp, kopię bazy sports2000 :

prodb mytp sports2000

Do partycjonowania tabel dane muszą znajdować się w obszarach Typ II. Demonstracyjna baza sports2000 posiada tylko obszary Typ I. Dodajemy zatem obszary, do których przeniesiemy tabele Customer (Cust_Data2) i Order (Order2), a także  obszary, w których będą przechowywane dane po procesie partycjonowania.

Najpierw tworzymy plik add_tp.st

d "Cust_Data2":20,64;8 . f 1280
d "Cust_Data2":20,64;8 .
#
d "Cust_Index2":25,32;8 . f 1280
d "Cust_Index2":25,32;8 .
#
d "Order2":30,64;8 . f 1280
d "Order2":30,64;8 .
#
d "CustomerData":300,64;8 ./customer f 1280
d "CustomerData":300,64;8 ./customer
d "CustomerIndex":301,32;8 ./customer f 320
d "CustomerIndex":301,32;8 ./customer
#
d "OrderData":400,64;8 ./order f 1280
d "OrderData":400,64;8 ./order 
d "OrderIndex":401,32;8 ./order f 320
d "OrderIndex":401,32;8 ./order
#

W katalogu z bazą tworzymy podkatalogi customer i order.
Teraz uruchamiamy polecenie:

prostrct add mytp add_tp.st

Przenosimy tabele Customer i Order do nowych obszarów Typ II:

proutil mytp -C tablemove customer Cust_Data2

proutil mytp -C tablemove order  Order2

Niestety, musimy także przenieść wszystkie indexy do obszarów Typ II (nie będę tego tutaj pokazywać, ale to też proste zadanie). Bazę demo można przygotować na różne sposoby, np. kasując niepotrzebne obiekty lub dump i load do nowej struktury.

Podobnie jak w przypadku CDC, dodamy konfigurację serwera bazy w OE Management (lub OE Explorer).  Po zalogowaniu się wybieramy Resources -> Database. Pojawia się widok Database Migration Utility, w którym podajemy parametry utworzonej bazy mytp wraz z numerem portu, np. 1009. Zaznaczamy Autostart database broker.

Na górnej listwie OE Management (OE Exlporer) klikamy Database Administration i na nazwę bazy: mytp. Pojawia się poniższy ekran.

W sekcji Database Features klikamy Table Partitioning Enable

… i jeszcze w Enable table partitioning. Funkcja jest już włączona w bazie.

W słowniku baz danych dodajemy dla tablicy Order index: OrderDateLocal, obszar: OrderIndex, pole: OrderDate. Analogicznie dla tablicy Customer index: CustomerCountryLocal, obszar: CustomerIndex, pole: Country.

Wracamy do OE Explorera. W sekcji Storage Management klikamy Create partition policy.

Pojawia się poniższy ekran, w którym definiujemy ustawienia dla naszej pierwszej partycji dla tablicy Order. Klikamy Create partition policy. Tworzymy partycję dla tablicy Customer.

Wypełniamy dane jak powyżej (w lookupach wyświetlają się tylko tablice w obszarach Typ II), zaznaczamy: Immediate – set new partitions to allocate space. Klikamy Next.

Będzie to partycja typu List, więc NIE zaznaczamy opcji Has range. Klikamy Add fields from index, wybieramy nowo utworzony index CustomerCountryLocal. Partycja podzieli dane wg pola Country.

Klikamy Next oraz Load Details. Otrzymujemy info, że znaleziono 9 podobszarów dla naszej partycji (jest to związane z wartościami pola Country). Klikamy Next.

Widzimy szczegóły Table Partition Policy. Klikamy Finish.

Zostaje utworzona nowa zasada o nazwie Customer. Dane w tablicy nie są jednak jeszcze podzielone.

Przygotowujemy dane do migracji. Klikamy w Edit Details wchodząc ponownie w szczegóły zasady partycjonowania. Klikamy podwójnie w każdy szczegół np. Austria i zaznaczamy Split-target. Tylko te zaznaczone elementy zostaną podzielone. Oznaczam Split-target wszystkie 9 elementów (czyli dla wszystkich krajów).


Wybieram Commit. Wszystko jest już przygotowane aby przenieść dane z partycji złożonej (Composite) do partycji podzielonych (Split-target).

W oknie komend proenv wpisujemy polecenie:

proutil mytp -C partitionmanage split table customer composite initial useindex

CustomerCountryLocal recs 100

Dane zostały podzielone przy użyciu zdefiniowanego indexu lokalnego. Ilość rekordów w transakcji: 100.

Możemy sprawdzić gdzie znajdują się teraz dane z tablicy Customer uruchamiając dobrze znane polecenie: proutil mytp -C tabanalys

Analiza dla obszaru CustomerData pokazuje podział tablicy na 9 partycji.

To na razie tyle w niniejszym odcinku, ale to nie koniec tematu partycjonowania.

Partycje Tabel OpenEdge cz. I

W ostatnim czasie kilka osób prosiło mnie o wyjaśnienie na czym polega partycjonowanie tabel w bazach OpenEdge. Ten temat czasem powraca w rozmowach z Wami, więc postanowiłem go nieco przybliżyć.

Partycjonowanie tabel (Table Partitioning) to oddzielny produkt dla baz Enterprise, umożliwiający dzielenie dużych tabel na mniejsze części pod względem logicznym zwane partycjami.

Partycje są zaimplementowane na poziomie bazy danych i przezroczyste dla aplikacji. Korzystanie z partycjonowanych tabel może wymagać niewielkich zmian w kodzie aplikacji lub nie wymagać ich wcale.

Uwaga: obiekty podzielone na partycje muszą znajdować się w storage area Typ II.

Partycjonowanie posiada kilka istotnych cech. Partycje w tabeli są niezależne, więc można realizować do nich jednoczesny dostęp, poprawiając wydajność zapytań. Jeśli jedna partycja w tabeli nie jest dostępna, pozostałe partycje są nadal dostępne dla aplikacji.


Każdy rekord tabeli podzielonej na partycje ma te same kolumny.
Każdy rekord może znajdować się tylko w jednej partycji.
Każda partycja może znajdować się we własnym obszarze przechowywania (storage area),
Każda partycja może być niezależnie modyfikowana i zarządzana bez wpływu na inne partycje tej samej tabeli.


Ponadto:
indeksy związane z tabelami podzielonymi na partycje można również podzielić na partycje (tzw. lokalne indeksy).
Podobnie jak partycje tabel, każdy lokalny indeks może znajdować się we własnym obszarze przechowywania i być niezależnie zarządzany. Oprócz indeksów lokalnych mogą istnieć także indeksy globalne dla wszystkich danych w tabeli, bez względu na wydzielone partycje.

Kiedy warto stosować tę technologię?

Np. dla tabel zawierających dane historyczne, które muszą być
archiwizowane. Ciekawą cechą partycji jest to, że jeśli jakaś partycja zawiera dane, które nie mogą być modyfikowane, może być ustawiona tylko do odczytu. W ten sposób w tabeli można modyfikować tylko dane aktualne, a nie zarchiwizowane.

Inne przykładowe przyczyny:

Tabele zawierające dane, które muszą być rozłożone na różnych urządzeniach pamięci masowej.
Duże tabele, które muszą podlegać okresowym operacjom na rekordach i indeksach.
Tabele zawierają kolumny, wg których można logicznie pogrupować dane.
Tabele zawierające dane z częstymi zapytaniami z frazą TABLE-SCAN, a nie WHOLE-INDEX.
Tabele, które będą rosły do bardzo dużych rozmiarów.

Partycjonowanie wykorzystuje jedną kolumnę (tzw. partition key) do jednoznacznej identyfikacji każdej partycji. Podział może być według zakresu (np. zakres dat) lub według listy (lista odrębnych wartości kolumn, np. kraje, województwa, itp.). Kolumna partition key nie może mieć wartości nieokreślonych (“?”).

Należy dodać, że dane w partycji można podzielić na dalsze partycje (możliwe jest 15 poziomów podziału). Np. dzielimy zamówienia (tablica order) według zakresu dat, a następnie każdą partycję dzielimy dodatkowo na subpartycje wg kraju.

 

Sposób w jaki tabele są podzielone jest opisane w tzw. zasadach partycjonowania (partition policy), znajdujących się w meta-schemacie bazy.

W następnym odcinku pokażę jak w praktyczny sposób stworzyć partycje i przenieść do nich dane.

Change Data Capture cz. II

Kontynuujemy temat związany z praktycznym wykorzystaniem technologii Change Data Capture opisanej w poprzednim artykule.

Mamy zatem bazę danych myCDC z włączoną funkcją CDC i zdefiniowanymi obszarami dla danych i indexów CDC.

Wejdżmy jeszcze raz w OE Explorerze w opcję Database Administration.

W sekcji Storage Management znajdziemy opcje, w których możemy zmodyfikować listę tabel lub stworzyć/zmodyfikować zasady CDC (CDC policy).
W sekcji Data Administration znajdują się opcje dla zrzucenia lub załadowania zdefiniowanych zasad CDC.

Podczas tworzenia zasad CDC należy określić poziom (Level), który określa ilość zapisywanych danych. Ilustruje to poniższa tabela.

Poziom Opis Fieldmap Czy można zmienić poziom?
 0  Przechowywanie danych tylko w Tracking Table  Brak  Nie
 1   Przechowywanie danych tylko w Tracking Table. Zawiera Fieldmap  Odzwierciedla zmienione pola tylko dla aktualizacji  Tak
 2  Zapis aktualnych wartości (after) dla wszystkich operacji CUD (Create, Update, Delete)   Odzwierciedla zmienione pola tylko dla aktualizacji  Tak
 3   Zapis aktualnych wartości (after) oraz poprzednich (before) dla wszystkich operacji CUD
  Odzwierciedla zmienione pola tylko dla aktualizacji  Tak

Pole Fieldmap jest wykorzystywane wtedy gdy interesuje nas, które pola zastały zmienione, ale nie interesują nas same wartości.

Utwórzmy teraz zasadę CDC poziom 2.

Na stronie Data Administration, w sekcji Storage Management, wybieramy Create Change Data Capture policy.

Wprowadzamy dane: Policy name: CustomerPolicy, Table: PUB.Customer, Level: Medium(2). Wartość State zostawiamy jako Inactive. Zasadę uaktywnimy później.

W polach Data area i Index area podajemy nazwy zdefiniowanych w bazie obszarów, jak na powyższym rysunku.

Jeśli nie podamy wartości Change table, to przyjmie ono domyślna nazwę, tutaj: CDC_Customer. Wartośc pola Change table owner przyjmie wartość pub.

Jeśli chcemy wybrać pola, których wartości mają być przechwytywane, zaznaczamy Identifying fields.

Z listy poniższych pól wybieramy: City, Country, CustNum, Name (zaznaczamy checkbox w pierwszej kolumnie). Dla pola CustNum w kolumnie Enable identifying field wybieramy YES, a wartość pola Field order ustawiamy 1. Dla tego pola zostanie utworzony index w tabeli Change Table.

Przyciskiem SUBMIT (na górze strony) tworzymy zasadę CDC.

Powinniśmy teraz widzieć poniższy ekran.

Wybieramy w górnym menu: Database Administration i Go to Database Administration.

Widzimy zdefiniowaną zasadę CDC dla tabeli Customer. W kolumnie Policy state widać No Current Policy ponieważ nie uaktywniliśmy jeszcze tej zasady. Klikamy na nazwę CustomerPolicy w polu Pending policy.

Zaznaczamy Active i przycisk SUBMIT.

Zasada CustomerPolicy jest już aktywna. Zasadę mogliśmy uaktywnić oczywiście wcześniej, podczas definiowania.

Pora napisać jakiś program. Otwieramy klienta podłączonego do bazy myCDC (np. komenda prowin myCDC) i uruchamiamy “skomplikowany” program składający się z instrukcji CREATE customer.

Następnie uruchamiamy program Customer_CTT.p oparty na schemacie z tablicy Change Tracking Table.

// Customer_CTT.p

 FOR EACH _file, each _cdc-change-tracking WHERE _file._file-number = 
          _cdc-change-tracking._source-table-number AND _file._file-name="customer":
  CASE _operation:

    WHEN 1 THEN
      DISPLAY "Create"  _operation  _file._FILE-NAME.
    WHEN 2 THEN  
      DISPLAY "Delete"  _operation  _file._FILE-NAME.
    WHEN 3 THEN  
      DISPLAY "Before Update"  _operation  _file._FILE-NAME.
    WHEN 4 THEN  
      DISPLAY "After Update" _operation  _file._FILE-NAME.
  END CASE.
END.

Widzimy informację, że została wykonana operacja 1 (Create) i utworzony został jeden rekord Customer.

W drugim przykładzie Customer_CT.p korzystamy z danych zapisanych do Change table CDC_Customer.

// Customer_CT.p

FOR EACH cdc_customer :
  DISPLAY _operation country city custNum name.
end.

W Change table zapisywane są jedynie pola wybrane podczas tworzenia zasady (wartości pól CustNum i Country ustawiane są przez tryger Create).

Wprowadźmy następną zmianę w danych.np. pole name dla pierwszego Customera = “Lift Tours Corp.”.

Customer_CTT.p

Mamy tu już dwie operacje na tablicy Customer: Create i After Update.

Customer_CT.p

Widzimy nową wartość pola Name oraz wartość CustNum (jest to Identifying field). Wartości pozostałych pól nie zmieniły się i są wyświetlone jako ?.

Powyższe przykładowe proste programy ilustrują sposób odczytu zmodyfikowanych danych dla zasady na poziomie 2. Poziom można ustawić w zależności od potrzeb. Tak uzyskane dane moga słuzyć różnym celom. Może to być element systemu ETL (o czym wspomniałem w pierwszej części) czy np. naszego własnego systemu do replikacji wybranych informacji.

Change Data Capture cz. I

Progress OpenEdge Change Data Capture (CDC) jest mechanizmem śledzącym, który umożliwia aplikacjom zaimplementowanie procesu, który automatycznie rejestruje zmiany w tabelach użytkowników w bazie danych OpenEdge.

Obsługuje on również automatyczne kopiowanie podzbiorów danych, które uległy zmianie do specjalnych tablic zmian (Change Tables). Zebrane przez CDC dane mogą być wykorzystane przez narzędzia wspomagające procesy ETL (Extract, Transform, Load).

Jednym z przykładówich ich wykorzystania jest identyfikacja trendów na podstawie danych w hurtowni danych, która została zapełniona informacjami z CDC change tables przy użyciu procesu ETL.

Change Data Capture to nowy produkt w OE 11.7. Można go kupić oddzielnie lub razem z licencją OE Advance Enterprise RDBMS. Funkcje wspierające CDC można znaleźć w OpenEdge SQL, OpenEdge ABL, OpenEdge Management, OpenEdge Explorer i w innych obszarach.

Dane dostarczane przez proces przechwytywania znajdują się w źródłowej bazie danych i są przechowywane w formie relacyjnej.

OpenEdge CDC jest elastyczny, ponieważ:

  • Przechwycone dane są przechowywane w tej samej bazie danych
  • Przechwycone dane są utrzymywane w formie relacyjnej
  • Przechwycone dane są dostępne poprzez składnie SQL i ABL.

OpenEdge CDC jest skalowalny, ponieważ można zdefiniować zasady (policy) CDC takie, że:

  • Ilość przechwyconych danych może być różna dla różnych tabel. Można nie przechwytywać żadnych danych, wybrane dane lub cały rekord
  • Można indeksować dane w celu łatwiejszego wyszukiwania informacji
  • Ilość przechwyconych danych jest kontrolowana za pomocą zasad zdefiniowanych na poziomie tabeli i pola.

Niektóre zalety OpenEdge Change Data Capture to:

  • Identyfikacja i śledzenie wszystkich zmian danych w bazie OpenEdge
  • Gwarancja dokładności śledzenia wszystkich zmian danych bez względu na miejsce ich występowania
  • Zwiększenie efektywności i dostępności zmian dla ETL w celu synchronizacji określonych zmian z
    innymi źródłami danych, repozytoriami danych lub hurtowniami danych
  • Jedno miejsce konfiguracji niezależnie od ABL lub SQL
  • Możliwość aktywacji bez jakichkolwiek zmian w kodzie aplikacji, wystarczy tylko skonfigurować i uruchomić
  • Możliwość zarządzania całkowicie online – bez żadnych przestojów.

Włączenie mechanizmu CDC powoduje dodanie dwóch tabel do metaschematu bazy: _Cdc-Table-Policy oraz _Cdc-Field-Policy. Tabele te zawierają informacje o zasadach CDC dla tabel i powiązanych z nimi pól.

Oprócz tego dodawane są tabele: Change Tracking Table (_Cdc-Change-Tracking) i oddzielne tabele CDC dla każdej tabeli źródłowej, dla której chcemy przechwytywać zmiany danych (wspomniane wcześniej Change Tables).

Tabela _Cdc-Change-Tracking przechowuje zapis wszystkich działań związanych ze zmianami danych we wszystkich tablicach źródłowych, zgodnie z zasadami CDC. Przechwytywanie jest wykonywane poprzez specjalne trygery CDC, wbudowane w silnik bazy. Zawiera także informacje niezbędne do zabezpieczenia sekwencji transakcyjnej. Następnie dane te są zapisywane przez trygery do tabel Change Tables, o ile poziom zasad jest większy niż zero (w tym przypadku wszystkie dane znajdują się tylko w Change Tracking Table).

Przed włączeniem mechanizmu CDC należy przydzielić miejsce dla nowych tabel i indeksów. Ważnym zadaniem administratora jest monitorowanie przyrostu tych danych oraz zarządzanie nimi.

OK, po tym przydługawym wprowadzeniu zabierzmy się do pracy i stwórzmy bazę przygotowaną do CDC. Pamiętajmy, że aby CDC można było włączyć, baza musi zawierać obszary typu II.

Najpierw tworzymy nową bazę np. myCDC, kopię bazy sports2000 poleceniem:

prodb myCDC sports2000

Do bazy dodajemy obszary, w których będą przechowywane dane przechwycone przez CDC. Najpierw tworzymy plik add_CDC.st

#
d "CDC_Track_Data":20,64;512 .
#
d "CDC_Track_Index":21,1;64 .
#
d "CDC_Customer_Data":25,64;512 .
#
d "CDC_Customer_Index":26,1;64 .
#
d "CDC_Misc_Data":27,64;512 .
#
d "CDC_Misc_Index":28,1;64 .
#

Teraz uruchamiamy polecenie:

prostrct add myCDC add_CDC.st

którego efekt widać na poniższym obrazku.

Teraz skorzystamy z narzędzia webowego OE Explorer lub OE Management. Po zalogowaniu się wybieramy Resources -> Database. Pojawia się widok Database Migration Utility, w którym podajemy parametry utworzonej bazy myCDC wraz z numerem portu, np. 1005. Zaznaczamy Autostart database broker.

Po naciśnięciu SUBMIT powinien pojawić się poniższy widok.

Teraz w menu głównym klikamy Database Administration i Go to Database Administration.

Na liście baz danych klikamy naszą bazę myCDC.

Pojawia się ekran z kilkoma widokami. Po prawej stronie znajduje się widok Database Features, na której odnajdziemy wyłączona funkcję Change Data Capture.

Klikamy Enable.

Teraz musimy podać w jakich obszarach będą zapisywane dane i indeksy. Klikamy ikonki z lupą i wybieramy odpowiednie obszary.

Teraz klikamy Enable change data capture.

Powinien pojawić się poniższy komunikat.

Włączenie CDC możemy wykonać także bezpośrednio z linii komend np:

proutil myCDC -C enablecdc area Track_CDC_Data indexarea CDC_Track_Index

Na razie wystarczy. W następnym odcinku zdefiniujemy zasady CDC i napiszemy kilka prostych programów ilustrujących wykorzystanie informacji z change tables.

Instalacja OpenEdge w nowej wersji

Większość z Was wie, że model licencjonowania PSDN (Progress Software Developer Network) został zastąpiony przez Progress OpenEdge Developers Kit.

Zmiana wiąże się z rozszerzeniem dostępu do produktów Telerik, Corticon oraz wybranych usług. Model OEDK zawiera 5 licencji: Classroom (darmowa), Basic, Corporate, Premier, Innovator. Np. od licencji Corporate dostępne są wszystkie nowe szkolenia online. Porównanie 5 licencji możecie znaleźć tutaj.

Instalacja OpenEdge została uproszczona za pomocą tzw. plików instalacyjnych. Nie trzeba już wpisywać numerów licencji i kodów – wystarczy tylko wybrać z listy instalowane produkty.
I teraz wielu z Was zapewne zaprotestuje: przecież już od OE 10.1C można było instalować bez “wklepywania” tych kodów! Rzeczywiście od tamtej wersji można było zapisać plik licencyjny w formacie html i podczas instalacji wczytać License Addendum File. Jednakże była także opcja instalacji przez ręczne wpisywanie S/N oraz kodów wybranych produktów. Myślę, że wiele osób w ogóle nie stosowało opcji z Licenses Addendum File. Obecnie generowanie plików instalacyjnych (aktywacyjnych) jest obowiązkowe.

Po kolei: po zalogowaniu się do swojego konta ESD wybieramy opcję Manage OEDK Activation Files. Tu trzeba nadmienić, że Activation Files to to samo co Installation Files. Informacja, jaką dostajemy automatycznie emailem odnosi się do Installation Files, co może być w pierwszej chwili mylące.

Po wybraniu powyższych informacji i nadaniu nazwy Reference zaznaczamy które produkty będziemy instalować. Takich plików aktywacyjnych można wygenerować kilka dla różnych produktów, co jest bardzo użyteczne.

Zawartość utworzonych plików można przeglądać.

Podczas instalacji wystarczy wczytać konkretny plik i lista produktów pojawia się automatycznie.

1 2