Микросервистерди кантип колдонууну үйрөнүңүз. 1-бөлүк. Жазгы жүктөө жана Докер

Микросервистерди кантип колдонууну үйрөнүңүз. 1-бөлүк. Жазгы жүктөө жана Докер

Эй Хабр.

Бул макалада мен микросервистер менен эксперимент жүргүзүү үчүн окуу чөйрөсүн түзүүдөгү тажрыйбам жөнүндө айткым келет. Ар бир жаңы аспапты үйрөнгөндө мен аны жергиликтүү станокто гана эмес, реалдуу шарттарда да сынап көргүм келди. Ошондуктан, мен жөнөкөйлөтүлгөн микросервис тиркемесин түзүүнү чечтим, аны кийинчерээк ар кандай кызыктуу технологиялар менен "жабууга" болот. Долбоордун негизги талабы анын реалдуу системага максималдуу функционалдык жакындыгы болуп саналат.

Башында, мен долбоорду түзүүнү бир нече этапка бөлдүм:

  1. Эки кызматты түзүңүз - 'backend' (backend) жана 'gateway' (gateway), аларды докер сүрөттөрүнө топтоп, чогуу иштөө үчүн орнотуңуз

    Ачкыч сөздөр: Java 11, Spring Boot, Docker, сүрөттү оптималдаштыруу

  2. Kubernetes конфигурациясын иштеп чыгуу жана Google Kubernetes Engineде системаны жайылтуу

    Ачкыч сөздөр: Kubernetes, GKE, ресурстарды башкаруу, автоскалдаштыруу, сырлар

  3. Кластерди жакшыраак башкаруу үчүн Helm 3 менен диаграмма түзүү

    Теги: Helm 3, диаграмманы жайылтуу

  4. Кодду кластерге автоматтык түрдө жеткирүү үчүн Jenkins жана конвейерди орнотуу

    Ачкыч сөздөр: Дженкинс конфигурациясы, плагиндер, өзүнчө конфигурациялар репозиторий

Ар бир кадамга өзүнчө макала бөлүүнү пландап жатам.

Бул макалалар сериясынын негизги максаты микросервистерди кантип жазуу эмес, аларды кантип бирдиктүү системада иштетүү. Мунун баары, адатта, иштеп чыгуучунун жоопкерчилигинен тышкары болсо да, мен алар менен кеминде 20% тааныш болуу пайдалуу деп ойлойм (бул, сиз билгендей, натыйжанын 80% берет). Кээ бир шартсыз маанилүү темалар, мисалы, коопсуздук, бул долбоорго кирбей калат, анткени автор бул система жеке колдонуу үчүн гана түзүлгөнүн аз түшүнөт. Мен ар кандай пикирлерди жана конструктивдүү сынды кабыл алам.

Микросервистерди түзүү

Кызматтар Spring Boot аркылуу Java 11де жазылган. Кызматтар аралык өз ара аракеттенүү REST аркылуу уюштурулат. Долбоор тесттердин минималдуу санын камтыйт (кийин Дженкинсте сынай турган нерсе бар). Кызматтардын баштапкы коду GitHub сайтында жеткиликтүү: backend и Gateway.

Кызматтардын ар биринин абалын текшере алуу үчүн алардын көз карандылыктарына жазгы кыймылдаткыч кошулду. Ал /актуатор/ден соолуктун акыркы чекитин түзөт жана эгер кызмат трафикти кабыл алууга даяр болсо 200 статусун кайтарат, же көйгөй болсо 504. Бул учурда, бул өтө эле ойдон чыгарылган текшерүү, анткени кызматтар абдан жөнөкөй жана кандайдыр бир форс-мажордук жагдайларда, алар жарым-жартылай иштеп калганга караганда, толугу менен жеткиликсиз болуп калышы ыктымал. Бирок реалдуу системаларда, Actuator колдонуучулар аны менен күрөшө баштаганга чейин көйгөйдү аныктоого жардам берет. Мисалы, маалымат базасына кирүү көйгөйлөрү болсо, бузулган сервис инстанциясы менен суроо-талаптарды иштетүүнү токтотуп, ага автоматтык түрдө жооп бере алабыз.

Арткы кызмат

Backend кызматы жөн гана эсептеп, кабыл алынган сурамдардын санын кайтарып берет.

Контроллердин коду:

@RestController
public class RequestsCounterController {

    private final AtomicLong counter = new AtomicLong();

    @GetMapping("/requests")
    public Long getRequestsCount() {
        return counter.incrementAndGet();
    }
}

Контроллер тести:

@WebMvcTest(RequestsCounterController.class)
public class RequestsCounterControllerTests {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void firstRequest_one() throws Exception {
        mockMvc.perform(get("/requests"))
            .andExpect(status().isOk())
            .andExpect(MockMvcResultMatchers.content().string("1"));
    }
}

Кызмат шлюзи

Шлюз суроо-талапты төмөнкү маалымат менен толуктап, сервердик кызматка жөнөтөт:

  • шлюз id. Бул сервердин жообу менен шлюздун бир инстанциясын башкасынан айырмалоо үчүн зарыл.
  • Өтө маанилүү сырсөздүн ролун ойной турган кээ бир "сыр" (маанилүү кукилердин шифрлөө ачкычынын саны)

application.properties ичиндеги конфигурация:

backend.url=http://localhost:8081
instance.id=${random.int}
secret="default-secret"

Арткы адаптер:

@Service
public class BackendAdapter {

    private static final String REQUESTS_ENDPOINT = "/requests";

    private final RestTemplate restTemplate;

    @Value("${backend.url}")
    private String backendUrl;

    public BackendAdapter(RestTemplateBuilder builder) {
        restTemplate = builder.build();
    }

    public String getRequests() {
        ResponseEntity<String> response = restTemplate.getForEntity(
backendUrl + REQUESTS_ENDPOINT, String.class);
        return response.getBody();
    }
}

Контроллер:

@RestController
@RequiredArgsConstructor
public class EndpointController {

    private final BackendAdapter backendAdapter;

    @Value("${instance.id}")
    private int instanceId;

    @Value("${secret}")
    private String secret;

    @GetMapping("/")
    public String getRequestsCount() {
        return String.format("Number of requests %s (gateway %d, secret %s)", backendAdapter.getRequests(), instanceId, secret);
    }
}

Ишке киргизүү:

Биз backend баштайбыз:

./mvnw package -DskipTests
java -Dserver.port=8081 -jar target/microservices-backend-1.0.0.jar

Шлюзду баштоо:

./mvnw package -DskipTests
java -jar target/microservices-gateway-1.0.0.jar

текшерүү:

$ curl http://localhost:8080/
Number of requests 1 (gateway 38560358, secret "default-secret")

Баары иштейт. Кунт коюп окурман, шлюзду айланып өтүп, артка түз кирүүгө эч нерсе тоскоол эмес экенин белгилейт (http://localhost:8081/requests). Муну оңдоо үчүн кызматтар бир тармакка бириктирилип, сырттан шлюз гана "чыгарылышы" керек.
Ошондой эле, эки кызмат тең бир файл тутумун бөлүшөт, агымдарды чыгарат жана бир учурда бири-бирине тоскоолдук кыла башташы мүмкүн. Биздин микросервистерди обочолонтуу жакшы болмок. Буга тиркемелерди ар кандай машиналарга жайылтуу (көп акча, кыйын), виртуалдык машиналарды колдонуу (ресурсту көп талап кылган, узак ишке киргизүү) же контейнерлештирүү аркылуу жетишүүгө болот. Күтүлгөндөй эле, биз үчүнчү жолду тандап жана ютуб контейнерлөө үчүн курал катары.

ютуб

Кыскача айтканда, докер обочолонгон контейнерлерди жаратат, ар бир колдонмодо бирден. Докерди колдонуу үчүн Dockerfile жазуу керек - тиркемени куруу жана иштетүү боюнча нускама. Андан кийин, сиз сүрөттү куруп, аны сүрөт реестрине жүктөй аласыз (№. Dockerhub) жана микросервисиңизди каалаган докерлештирилген чөйрөдө бир буйрук менен жайгаштырыңыз.

докер файлы

Сүрөттүн эң маанилүү өзгөчөлүктөрүнүн бири – бул анын өлчөмү. Ыкчам сүрөт алыскы репозиторийден тезирээк жүктөлүп, азыраак орун ээлейт жана кызматыңыз тезирээк башталат. Кандай гана сүрөт болбосун, негизги сүрөттүн негизинде курулат жана эң минималисттик вариантты тандоо сунушталат. Жакшы вариант Alpine, минималдуу топтомдор менен толук Linux дистрибьютору.

Биринчиден, келгиле, "маңдайга" Dockerfile жазууга аракет кылалы (мен дароо айтам, бул жаман жол, муну кылбаңыз):

FROM adoptopenjdk/openjdk11:jdk-11.0.5_10-alpine
ADD . /src
WORKDIR /src
RUN ./mvnw package -DskipTests
EXPOSE 8080
ENTRYPOINT ["java","-jar","target/microservices-gateway-1.0.0.jar"]

Бул жерде биз долбоорбузду куруу үчүн мурунтан орнотулган JDK менен Альп тоосуна негизделген базалык сүрөттү колдонуп жатабыз. ADD буйругу менен биз сүрөткө учурдагы src каталогун кошуп, аны иштеп жаткан деп белгилейбиз (WORKDIR) жана курууну баштайбыз. EXPOSE 8080 буйругу докерге контейнердеги тиркеме өзүнүн 8080 портун колдоно тургандыгын билдирет (бул колдонмону сырттан жеткиликтүү кылбайт, бирок колдонмого, мисалы, ошол эле докер тармагындагы башка контейнерден кирүүгө мүмкүндүк берет. ).

Кызматтарды сүрөттөргө топтоо үчүн ар бир долбоордун тамырынан буйруктарды иштетишиңиз керек:

docker image build . -t msvc-backend:1.0.0

Натыйжада 456 МБ сүрөт (анын ичинен JDK базалык сүрөтү 340 Мб ды ээлеген). Ал эми биздин долбоордо сабактар ​​бармак менен санаса болот экенине карабастан. Биздин сүрөттүн өлчөмүн азайтуу үчүн:

  • Биз көп баскычтуу чогултууну колдонобуз. Биринчи кадамда биз долбоорду курабыз, экинчи кадамда JRE орнотобуз, үчүнчү кадамда анын баарын жаңы таза Альп сүрөтүнө көчүрөбүз. Жалпысынан акыркы сүрөттө керектүү компоненттер гана болот.
  • Келгиле, javaдын модулизациясын колдонолу. Java 9 менен баштап, сиз керектүү модулдардан JRE түзүү үчүн jlink куралын колдоно аласыз

Кызыккандар үчүн бул жерде сүрөттү кыскартуу ыкмалары жөнүндө жакшы макала бар. https://habr.com/ru/company/ruvds/blog/485650/.

Акыркы докер файлы:

FROM adoptopenjdk/openjdk11:jdk-11.0.5_10-alpine as builder
ADD . /src
WORKDIR /src
RUN ./mvnw package -DskipTests

FROM alpine:3.10.3 as packager
RUN apk --no-cache add openjdk11-jdk openjdk11-jmods
ENV JAVA_MINIMAL="/opt/java-minimal"
RUN /usr/lib/jvm/java-11-openjdk/bin/jlink 
    --verbose 
    --add-modules 
        java.base,java.sql,java.naming,java.desktop,java.management,java.security.jgss,java.instrument 
    --compress 2 --strip-debug --no-header-files --no-man-pages 
    --release-info="add:IMPLEMENTOR=radistao:IMPLEMENTOR_VERSION=radistao_JRE" 
    --output "$JAVA_MINIMAL"

FROM alpine:3.10.3
LABEL maintainer="Anton Shelenkov [email protected]"
ENV JAVA_HOME=/opt/java-minimal
ENV PATH="$PATH:$JAVA_HOME/bin"
COPY --from=packager "$JAVA_HOME" "$JAVA_HOME"
COPY --from=builder /src/target/microservices-backend-*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]

Биз сүрөттү кайра жаратабыз, натыйжада ал 6 эсе салмагын жоготуп, 77 Мб түзөт. Жаман эмес. Андан кийин, даяр сүрөттөрдү сүрөттөр реестрине жүктөсө болот, андыктан сүрөттөрүңүздү Интернеттен жүктөө үчүн жеткиликтүү болот.

Докерде чогуу иштеген кызматтар

Баштоо үчүн, биздин кызматтар бир тармакта болушу керек. Докерде тармактардын бир нече түрү бар жана биз алардын эң примитивдүүсүн колдонобуз - бир эле хостто иштеген контейнерлерди тармакка салууга мүмкүндүк берген көпүрө. Төмөнкү буйрук менен тармак түзүңүз:

docker network create msvc-network

Андан кийин, microservices-backend:1.0.0 сүрөтү менен 'backend' деп аталган резервдик контейнерди баштаңыз:

docker run -dit --name backend --network msvc-net microservices-backend:1.0.0

Белгилей кетсек, көпүрө тармагы контейнерлер үчүн өз аталыштары боюнча кызмат көрсөтүүлөрдү ачууну камсыз кылат. Башкача айтканда, сервердик кызмат докер тармагынын ичинде жеткиликтүү болот http://backend:8080.

Шлюзду баштоо:

docker run -dit -p 80:8080 --env secret=my-real-secret --env BACKEND_URL=http://backend:8080/ --name gateway --network msvc-net microservices-gateway:1.0.0

Бул буйрукта биз хостубуздун 80-портун контейнердин 8080 портуна жөнөтүп жатканыбызды көрсөтөбүз. Биз env параметрлерин жаз менен автоматтык түрдө окула турган чөйрө өзгөрмөлөрүн коюу жана application.properties касиеттерин жокко чыгаруу үчүн колдонобуз.

Баштагандан кийин чалабыз http://localhost/ жана баары мурункудай эле иштеп жатканын текшериңиз.

жыйынтыктоо

Натыйжада, биз эки жөнөкөй микросервисти түзүп, аларды докер контейнерлерине топтоп, бир эле машинада чогуу ишке киргиздик. Натыйжада система, бирок, бир катар кемчиликтери бар:

  • Катуу толеранттуулук начар - бардыгы биз үчүн бир серверде иштейт
  • Начар масштабдалуу - жүк көбөйгөндө, кошумча тейлөө инстанцияларын автоматтык түрдө жайгаштыруу жана алардын ортосундагы жүктү тең салмактоо жакшы болмок
  • Ишке киргизүүнүн татаалдыгы - биз жок дегенде 3 буйрукту жана белгилүү бир параметрлерди киргизүүбүз керек болчу (бул 2 кызмат үчүн гана)

Жогорудагы көйгөйлөрдү чечүү үчүн Docker Swarm, Nomad, Kubernetes же OpenShift сыяктуу бир катар чечимдер бар. Эгер бүт система Java тилинде жазылган болсо, сиз Spring Cloud (жакшы макала).

В кийинки бөлүгү Мен Kubernetesти кантип орнотконум жана долбоорду Google Kubernetes Engine'ге орнотконум жөнүндө сүйлөшөм.

Source: www.habr.com

Комментарий кошуу