Rozwiązania serverless

Charles_Ray
  • Rejestracja:około 17 lat
  • Ostatnio:około 5 godzin
  • Postów:1873
0

Cześć, jestem ciekawy jakie macie doświadczenia z serverlessemt :) a konkretnie:

  1. Jakiego rozwiązania używacie, np. AWS Lambda, GCP cloud run, …
  2. Jaki scenariusz obsługujecie tym rozwiązaniem?
  3. Słowo komentarza - co jest fajne, co nie działa? Czego brakuje? Jaki próg wejścia? Jak z kosztami i wydajnością? Warto/nie warto?

”Engineering is easy. People are hard.” Bill Coughran
edytowany 1x, ostatnio: Charles_Ray
Patryk Maleszko
czyżbyś szykował skok na kasę i targetujesz szkolenie, kurs, webinar, książkę, kanał na YT?
Charles_Ray
Tak, pomyślałem, że rzucę pracę w korporacji i zacznę produkować kursy na YT ;) tak na poważnie, to sam wchodzę w świat serverless i chciałem poznać doświadczenia użytkowników tych rozwiązań
Aventus
  • Rejestracja:prawie 9 lat
  • Ostatnio:ponad 2 lata
  • Lokalizacja:UK
  • Postów:2235
2

U mnie korzystamy z (oraz jesteśmy na etapie migracji na) Azure Functions. Wcześniej wszystko było hostowane jako Web Jobs (długo działający proces, taki odpowiednik Windows Service albo Daemon).

Mówiąc szczerze to mam mieszane uczucia. O ile bez wątpienia znacznie to ułatwia skalowalność, o tyle nie jest to takie kolorowe jak się może wydawać jeśli ma się złożony system biznesowy, chce się mieć czysty kod i architekturę oraz ułatwiać życie programistom. Bo gdyby chcieć mieć "czysty" serverless to trzeba by tworzyć funkcje dla każdej logiki wykonywanej asynchronicznie (w naszym przypadku to event handlery, bo mamy kod reaktywny reagujący na eventy zachodzące w systemie). A to już oznacza że programista pracujący nad jakąś biznesową funkcjonalnością musi również zająć się tym całym podpinaniem tego pod nową funkcję. Taka funkcja musi zostać postawiona w Azure (to oczywiście może zostać zautomatyzowanego za pomocą IaC) ale nadal potrzebne jest jakieś podpinanie tego.

Co za tym idzie zastosowaliśmy rozwiązanie pośrednie- funkcja reaguje na eventy (każde), i wywołuje odpowiednią infrastrukturę w naszym kodzie która zajmuje się routingiem odebranego eventu do konkretnego handlera (logiki biznesowej).

Plus jest taki że w kodzie nadal mamy zachowany podział na odpowiednie warstwy (architektura onion) ale przychodzi to kosztem tego że tracimy część tego "prawdziwego" serverless bo jest więcej kodu który się wykonuje w ramach jednej funkcji. Zimny start oczywiście jest również odrobinę dłuższy (ale to różnica marginalna).

Wydaje mi się że funkcje najlepiej nadaje się do lekkiego, szybkiego kodu z pogranicza systemu- taki który niekoniecznie musi być "czysty" w kontekście architektury systemu.


Na każdy złożony problem istnieje rozwiązanie które jest proste, szybkie i błędne.
Charles_Ray
Dzięki za komentarz! Żebym lepiej zrozumiał - ta „frontalna” funkcja wtedy subskrybuje wiele topicow i odpala dalej różne funkcje? To nie jest problem, ze tworząc nowa funkcje zawsze tam tez trzeba dodać „routing” (więcej kodowania i zużycia zasobów)? ;)
Charles_Ray
  • Rejestracja:około 17 lat
  • Ostatnio:około 5 godzin
  • Postów:1873
0

Dzięki za komentarz! Żebym lepiej zrozumiał:

  1. Ta „frontalna” funkcja wtedy subskrybuje wiele topicow i odpala dalej różne funkcje? To nie jest problem, ze tworząc nowa funkcje zawsze tam tez trzeba dodać „routing” (więcej kodowania i zużycia zasobów)? ;)
  2. Dlaczego nie da się ładnie pisać takiej funkcji, chyba tez można wydzielić domenę od infry stosując normalne podejście jak w heksie?

”Engineering is easy. People are hard.” Bill Coughran
Aventus
Odpiszę późnie jak będę miał więcej czasu, postaram się to lepiej wyjaśnić.
Aventus
  • Rejestracja:prawie 9 lat
  • Ostatnio:ponad 2 lata
  • Lokalizacja:UK
  • Postów:2235
1

Ta „frontalna” funkcja wtedy subskrybuje wiele topicow i odpala dalej różne funkcje? To nie jest problem, ze tworząc nowa funkcje zawsze tam tez trzeba dodać „routing” (więcej kodowania i zużycia zasobów)? ;)

Nie, niejasno opisałem o co konkretnie chodzi. Pisząc "routing" miałem na myśli routing na poziomie aplikacji, nie "fizycznej" infrastruktury.

Pozwól że po staram się pokrótce opisać jak to u nas wygląda z poziomu architektury ale i pewnej filozofii pisania oprogramowania. Mamy system oparty o mikroserwisy i event-driven, a więc komunikacja pomiędzy serwisami odbywa się właśnie na takiej zasadzie że jeden serwis publikuje event, i inne serwisy mogą nasłuchiwać tego eventu i odpowiednio na niego reagować. Na popzimie infrastruktury używamy Azure ServiceBus, wszystko leci do jednego topica. Każdy serwis ma swój proces nasłuchujący na tym topicu, i to subskrypcja danego serwisu definiuje jakie eventy się dostają do niego. Z perspektywy "filozofii" pisania nowych funkcjonalności, to wszystko to jest transparentne dla programistów. Jeśli programista pisze kod który musi nasłuchiwać danego eventu i go obsłużyć, to musi zrobić jedynie dwie rzeczy:

  1. Zaimplementować interfejs IEventHandler<T> gdzie T jest konkretnym,silnie typowanym event domenowym. Taki event handler to po prostu jednostka logiki biznesowej, może dodatkowo przyjmować inne serwisy domenowe przez DI. Event handlery należą do warstwy domeny (bo mają logikę biznesową i operują na eventach domenowych), z punktu widzenia onion architecture są więc w corze systemu.

  2. Nowy event musi zostać zarejestrowany, tak aby proces odbierający ten event z ServiceBusa wiedział gdzie go przekierować w kodzie aplikacji. Programista robi to w kodzie boostrapującym aplikację, wykorzystując do tego naszą warstwę infrastruktury (chodzi o infrastrukturę w kodzie, nie fizyczną). Mamy własną paczkę Messaging która dostarcza takie funkcjonalności, więc wygląda to mniej więcej tak jak poniżej (nie dokładnie tak, ale to tylko przykład):

Kopiuj
// Rejestracja DI
services.AddServiceBusEventListeners(config =>
  config.UseConnectionString("")
    .UseSubscriptionName("")
    .Handle<MyEvent, MyEventHandler>() // To jest ten "routing"- mówimy do jakiego handlera skierować dany event
);

To jedyne co programista musi zrobić. Idea jest taka aby programista mógł skupić się na tym co naprawdę ma znaczenie- na logice biznesowej- i miał jak najmniej dodatkowej pracy. Całą resztą zajmuje się kod w naszej bibliotece od messagingu.

Za kulisami to wygląda tak że DI rejestruje kilka dodatkowych serwisów. Wtedy aplikacja hostująca ma podpięty moduł odpowiadający za odbiór eventów przychodzących z ServiceBus- to po prostu klasa która oznaczona jest atrybutem zawierającym trigger z ServiceBus. Moduł ten przyjmuje przez konstruktor procesor eventów- ten procesor właśnie odpowiada za zdeserializowanie surowych wiadomości z ServiceBus (obiekty typu Message) na konkretny, silnie typowany event, oraz przekazanie go do jednego lub więcej event handlerów zarejestrowanych wcześniej (wymieniony wcześniej routing). I to są te dwa kluczowe elementy stwarzające pewien problem- moduł odbierający surowe wiadomości, i cała podpięta logika obsługująca je odpowiednio.

Bo gdybyśmy chcieli to robić "czysto" w rozumieniu serverless, to każdy event handler musiałby mieć oddzielny, jawny "moduł" odbierający dany event, na danym topicu- czyli funkcję. Rzecz w tym że ze względu na to iż mamy architekturę event-driven, tych handlerów mamy całkiem sporo. Gdyby dla każdego programista musiał tworzyć oddzielne funkcje, to kolidowało by to z naszą filozofią ułatwiania programistom życia, oraz skupianiu się na warstwie domeny. Dodatkowo, u nas wszystkie eventy idą po jednym topicu, co tym bardziej kolidowałoby z koniecznością wydzielania tego dla każdego rodzaju eventu. Musielibyśmy "wycinać" te zależności które dla konkretnego event handlera są niepotrzebne, zamiast po prostu rejestrować wszystko co potrzebne do wykonania przez logikę biznesową jako całość.

Co za tym idzie w naszym przypadku funkcje (w Azure) wyglądają tak że mamy tak naprawdę jedną funkcję dla jednego mikroserwisu, przyjmuje ona wiadomość z ServiceBus, a następnie przekazuje ją do naszego procesora który zajmuje się całym routingiem na poziomie aplikacji (w procesie) tak jak opisałem to wyżej. Taka funkcja nie jest więc tak "lekka" jak powinna, ale z drugiej strony nadal mamy łatwość skalowania zapewnioną przez Azure Functions.

Mam nadzieję że to co napisałem ma chociaż trochę sensu, zdając sobie sprawę że po części opisywałem to dosyć abstrakcyjnie :P


Na każdy złożony problem istnieje rozwiązanie które jest proste, szybkie i błędne.
Charles_Ray
Ok, to teraz rozumiem, że możecie delegować obsługę eventu do dowolnej funkcji. Ciekawe, że każdy serwis subskrybuje się na ten sam topic - w przypadku retry jeden serwis nie blokuje innych? Nie jest tych zdarzeń „za dużo”? Spotkałem się z rozwiązaniem, ze jest wiele topiców i każdy wybiera co go interesuje - mniej czytania.
Aventus
@Charles_Ray: nie blokuje, dla czego miało by tak być? Nie pomyliłeś czasem topica z kolejką? Topic ma bardzo dużą przepustowość i ze swojej natury obsługuje wiele roenoleglych klientów, stąd też my wysyłamy wszystkie eventy do jednego. Co do "mniej czytania" to od tego mamy właśnie subskrypcje na topicu- każda subskrypcja ma filtr który filtruje po metadanych wiadomości, ponieważ każda wiadomość w meta ma między innymi typ eventu. Tak więc przy rejestrowaniu eventów dla danego serwisu jak w przykładzie który podałem wyżej, dodajemy je automatycznie do filtra danej...
Aventus
...subskrypcji. Wtedy pomimo ze w topicu lądują wszystkie eventy w systemie, to subskrypcja odbiera te na które pozwala, więc w aplikacji lądują tylko te eventy którymi dany serwis jest zainteresowany.
Aventus
Jeden topic w Azure SB może obsłużyć kilka tysięcy wiadomości na sekundę (nie pamiętam dokładnie ile). Na dzień dzisiejszy nie mamy takiej skali, ale nie zaprzeczam że kiedy zaczniemy się do tego zbliżać to zapewne będziemy musieli jakoś to rozbić na więcej topiców. Obecnie jeszcze jedna duża zaletą jednego topica że mamy jedną subskrypcję która zrzuca wszystkie eventy do event logu w Cosmos DB, mamy więc świetną historię w jednym miejscu która można łatwo sprawdzić kiedy coś nie działa jak należy.
Charles_Ray
Ok, teraz już rozumiem. Brakowało mi tego komponentu subskrypcji, w którym jest rzeczony filtr, dzięki :)
Aventus
  • Rejestracja:prawie 9 lat
  • Ostatnio:ponad 2 lata
  • Lokalizacja:UK
  • Postów:2235
1

Dodam jeszcze specjalnie w oddzielnym poście że nie do końca zrozumiałem oryginalne pytanie, i myślałem że chodzi tylko o szeroko rozumiane funkcje (lambda itp). To na ten temat się wypowiadałem.

Jeśli chodzi o serverless ogólnie to korzystamy u mnie w pracy również z bazy danych (Cosmos DB), w/w service busa (Azure ServiceBus) oraz hostowania aplikacji webowych (Azure App Service). Chociaż nie jestem pewny czy to ostatnie zalicz się jako szeroko rozumiane serverless.


Na każdy złożony problem istnieje rozwiązanie które jest proste, szybkie i błędne.
Shalom
  • Rejestracja:około 21 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
2
  1. Raz widziałem AWS Lambde na prodzie
  2. Sprawdzało sie całkiem ok, jako handler pewnych czasowych zdarzeń - zamiast stawiać serwis który przez 99% nic nie robi, masz lambdę która jest triggerowana co jakiś czas. W tym przypadku logika była też dość prosta.

"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
ledi12
  • Rejestracja:ponad 5 lat
  • Ostatnio:19 dni
  • Lokalizacja:Wrocław
1

W przypadku Azure stawianie rozwiązań serverless czyli app functions jest banalnie proste, szczególnie jeśli chodzi o event handling np. trigger w przypadku pojawienia się nowego obiektu na blobie itp. Nie trzeba nawet pisać kodu tylko można użyć tzw. bindingu czyli konfiguracja konkretnego jsona. Rozwiązanie oprócz łatwości w utrzymaniu / szybkości implementacji, jest również tanie. M$ billuje per wywołanie funkcji z czego pierwszy 1mln masz za darmo.


Robię http response status cody w martwych ciągach
HA
  • Rejestracja:około 6 lat
  • Ostatnio:około godziny
  • Postów:1006
0

Mam ogólnie kiepskie doświadczenia z serverless - w mojej działce (duże ecommerce głównie w PHP) nadal królują monolity typu Magento i wiele większych SH postanowiło przejść na szeroko rozumiany cloud bo "marketingowo to się sprzedaje" + klienci często przychodzą i mówią, że chcą być "nowocześni". I tak byłem już w kilku projektach, które były stawiane w chmurze z użyciem wielu różnych usług typu redis, db, grupy atoskalowalne itd.

Streściłbym to tak, że przenoszenie na siłę monolitów na serverless to jest działanie na szkodę klienta. Oczywiście czasami było to uzasadnione, ale w znacznie częściej rezultaty były opłakane.

Oczywiście widzę dobre zastosowania dla serverless - czy to świadome korzystanie z wybranych usług, czy też np. architektura budowana z myślą o serverless, ale to co widzę na rynku to ślepy pęd w tym kierunku ze wszystkim co się da.

Zobacz pozostałe 11 komentarzy
Aventus
@some_ONE: ok to faktycznie chyba się mylę.
SO
A co do Cosmosa to może jednak nieironicznie się tak nazywa? ;) Mamy już przykład Cosmosa i Aurory, które w specjalnych planach, gdzie nie masz z góry zaalokowanych zasobów i nie masz stałej opłaty nazywają się serverless, w przeciwieństwie do planów z zaalakowanymi z góry zasobami. Definicja jak z większością modnych rzeczy może być niejasna, ale jak uznamy, że taki chmurowy Redis to serverless to równie dobrze można wtedy postawić znak równości pomiędzy serverless a cloud computing.
Aventus
Masz rację. Chociaż to też ciekawa zagwozdka bo powiedzmy że cały Twoj system to funkcje (nawet do odbierania requestow HTTP poprzez HTTP trigger). Masz to postawione w Azure Functions, i dla lepszej wydajności używasz cache właśnie w postaci Azure Redis Cache. I co, nagle zgodnie z "dogmatem" nie możesz mówić że masz system serverless? Wydaje się to trochę bez sensu.
SO
Może trzeba rozdzielić część compute od storage? Bo tak na prawdę to się chyba nazywa serverless computing. @hadwao podawał przykłady S3, SES, SQS (czy tam jakiś Azure Storage, Event Grid, Storage Queue). Tych usług bym nie zaliczał do compute, więc i pojęcie serverless albo nie-serverless chyba nie ma do nich zastosowania.
HA
Kurcze ciągle mam mieszane uczucia co do tego pojęcia, ale dzięki za ciekawą dyskusję. Wcześniej uważałem, że każda usługa zarządzana może być nazwana serverless, ale teraz to już sam nie wiem co myśleć ;-)
piotrpo
  • Rejestracja:ponad 7 lat
  • Ostatnio:2 minuty
  • Postów:3277
0

Azurowe bardzo fajne jako wyzwalacze robiące "coś" po tym jak się pojawi nowa wiadomość na service bus, blob w magazynie itd. Jeżeli chodzi o stawianie w ten sposób czegoś dużego, to wciąż mam trochę obaw na poziomie zarządzania tym kodem. Boję się, że ostatecznie pojawi się w cholerę drobnych kawałków logiki, które musza trafić w bardzo określone miejsce infrastruktury, w dodatku o ile wiem, dość specyficzne dla każdej platformy. Czyli tracimy na "cloud agnostic" i trzeba mieć naprawdę przemyślany i przestrzegany software development plan, żeby być w stanie sensownie to wydawać, przenosić przez kolejne środowiska testowe, a w razie czego być w stanie w skończonym czasie odtworzyć całe środowisko zbudowane na tych drobiazgach. Ostatecznie z tych powodów nie wykorzystałem jeszcze w projekcie. W przypadku Azure minusem była siermiężna obsługa Javy, bo w razie czego start takiej funkcji był na tyle długi, że zabijało to cały zysk z "płacisz za wykorzystanie", ale zaglądałem do tego już dość dawno, coś się pewnie zmieniło.

Aventus
  • Rejestracja:prawie 9 lat
  • Ostatnio:ponad 2 lata
  • Lokalizacja:UK
  • Postów:2235
1

@piotrpo:

Jeżeli chodzi o stawianie w ten sposób czegoś dużego, to wciąż mam trochę obaw na poziomie zarządzania tym kodem. Boję się, że ostatecznie pojawi się w cholerę drobnych kawałków logiki, które musza trafić w bardzo określone miejsce infrastruktury, w dodatku o ile wiem, dość specyficzne dla każdej platformy.

Dokładnie, był to jeden z powodów dla którego nie zrobiliśmy "pełnego" serverless tak jak opisałem to wyżej. U nas była zgoda co do tego że domena i cała filozofia z tym związana (łatwość dodawania nowej funkcjonalności biznesowej przez programistów itp) to sprawa nadrzędna, i cała warstwa biznesowa musi zostać agnostyczna co do metody hostingu tego. Niedawno było to WebJobs w Azure, teraz jest Functions, a kiedyś może być całkowicie inna platforma cloud- lub nie cloud. Zastosowaliśmy więc rozwiązanie pośrednie, ale dzięki temu zmiana sposobu hostowania tego to kwestia podpięcia wszystkiego na poziomie infrastruktury, bez zmian do kodu biznesowego.


Na każdy złożony problem istnieje rozwiązanie które jest proste, szybkie i błędne.
nowy_kret_2
  • Rejestracja:prawie 4 lata
  • Ostatnio:około 21 godzin
  • Postów:305
1

Pracuje z serverless, obecnie 3ci projekt, jednak sa to systemy generalnie nieskomplikowane, kilka kolejek, api. Problemem z serverless jest fakt ze ludzie go nie znaja i nie potrafia uzywac, a duzo info w necie to jakies paplaniny o tym ze to tak na prawde nie serverless tylko sa dokery odpalane, ciezko znalezc odpowiedzi na rzeczy, ktore sa problematyczne.
Iaac, ktory uzywamy to serverless framework, raz byl to terraform i musze powiedziec ze sls framework mi bardziej podchodzi, chociaz tf jest bardziej uniwersalny (koniec koncow z sls'ie mozna uzywac cloud formation wiec tez duzo rzeczy da sie ogarnac).

Problem jest na poziomie testowania zeby miec dobry i szybki feedback loop - ale na to tez sa rozwiaznia. Obecnie dla mnie pisanie czegos w SLS nie rozni sie od stawiania tomcata, tyle ze scope zastosowan jest inny. Fakt faktem, ze wiele rozwiazan ala crudowych moglyby spokojnie byc opedzlowane sls'em i prawdopodobnie bylaby to tansza opcja.

edytowany 2x, ostatnio: nowy_kret_2
somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:dzień
  • Lokalizacja:Wrocław
0

U mnie kiedyś TL chciał użyć AWS lambda do formatowania komunikatów do loggera. To się liczy?

PO
Może szukał nowej pracy i akurat w wymaganiach pojawiał się AWS lambda
somekind
Może być coś na rzeczy, bo parę tygodni po tej akcji go przenieśli. ;)
nowy_kret_2
  • Rejestracja:prawie 4 lata
  • Ostatnio:około 21 godzin
  • Postów:305
0

https://www.datadoghq.com/state-of-serverless/ wskazuja na rosnaca popularnosc, czy to prawda tylko stworca wie, jednak pojawiaja sie ogloszenia gdzie stricte szukaja serverless ludzi, wiec cos na rzeczy jest.

No i nie zapominajcie ze serverless jest eco friendly wiec new world order idzie po was i wasze zakurzone, ciezkie, opasłe, wiecznie głodne i konsumujace serwery!!!!

edytowany 1x, ostatnio: nowy_kret_2
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)