Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Кирилл Толкачёв, Александр Тарасов — микроСЕРВИСЫ огонь, вода, медные трубы

Moscow JUG
November 26, 2015

Кирилл Толкачёв, Александр Тарасов — микроСЕРВИСЫ огонь, вода, медные трубы

Микросервисы, кто-то только слышал о них, кто-то пытался делать, кто-то уже использует в продакшене. Идеи, заложенные в концепцию микросервисов, не новы и основные постулаты уже звучали раньше. Так почему же в последнее время мы всё чаще слышим о микросервисах? Что такое микросервисы для нас и чем они отличаются от старого доброго подхода SOA? Как теперь разрабатывать enterprise-приложения с микросервисным подходом на нашем любимом языке программирования Java?

На эти и некоторые другие вопросы постараемся ответить во время встречи. Наши гости, Кирилл Толкачёв и Александр Тарасов, в режиме live coding попытаются создать небольшой стартап, попутно использовав новомодные подходы и инструменты.

На пути к релизу стартапа будут затронуты основные проблемы выбранных подходов в целом и технологий в частности:
- Микросервис — что это, для чего и как с этим дальше жить. Где теория брат? ;)
- На чём писать API: REST или RPC, и почему Thrift имеет право на жизнь в эпоху тотального распространения JSON-а. Упрощай и превозмогай с помощью Spring boot starter;
- Какой стек выбрать для разработки, что выбрали мы и почему. Небольшое сравнение легковесных и не очень java фреймворков а так же сопутствующих инструментов;
- Способы упаковки, дистрибуции и разворачивания микросервисов, как Spring Boot и Docker помогают нам в решении этих непростых для разработчика проблемах;
- Как микросервисам найти друг друга, как готовить Spring Cloud и как обойти существующие проблемы и ограничения. Не доверяйте технологиям, доверяйте только себе;
- API Gateway. Предохраняй и сохраняй свои микросервисы.

Также речь пойдет о других распространенных проблемах распределенных систем и их решениях.

Moscow JUG

November 26, 2015
Tweet

More Decks by Moscow JUG

Other Decks in Programming

Transcript

  1. DISCLAIMER Наше мнение может не совпадать с официальной позицией банка,

    начальника, коллег или других специалистов. Мы не претендуем на роль последней инстанции в вопросах использования той или иной технологии. Все представленные решения вы можете использовать на свой страх и риск. За все ваши действия ответственность несёте только вы сами. 5
  2. 8

  3. 9

  4. 11

  5. SOA Principles • standardized service contract • loose coupling •

    encapsulation • reusability • autonomy • statelessness • discoverability 12
  6. 13

  7. UDDI • Никто не говорит и никто не знает ;)

    • Но все же. Кто знает что это и зачем это? • А кто внедрял ? :) 14
  8. Как это выглядит? “Сейчас” 18 @UDDIService( businessKey="uddi:myBusinessKey", serviceKey="uddi:myServiceKey", description =

    "Hello World test service") @UDDIServiceBinding( bindingKey="uddi:myServiceBindingKey", description="WSDL endpoint for the hello${department} Service. This service is used for testing the jUDDI annotation functionality", accessPointType="wsdlDeployment", accessPoint="http://localhost:8080/juddiv3-samples/services/helloworld?wsdl")
  9. <S:Envelope> <S:Header> ... <Security S:actor="null" S:mustUnderstand="..."> ... </Security> ... </S:Header>

    ... </S:Envelope> …а реализация врозь Не все реализации клиентов могут так сделать :( 21
  10. 22

  11. А что с людьми? • Что волновало людей тогда? •

    Их волновало то, как не использовать технологию • Сейчас эта книга до сих пор продается. 20$ Ничто не не вечно :) 2004 год 24
  12. 29

  13. In short, the microservice architectural style is an approach to

    developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. These services are built around business capabilities and independently deployable by fully automated deployment machinery. There is a bare minimum of centralized management of these services, which may be written in different programming languages and use different data storage technologies. -- James Lewis and Martin Fowler Что такое микросервисы? 30
  14. Размер имеет значение? • Method/Function = Microservice? • 10-300 LOC

    = Microservice? • 1 week = Microservice? • 1 developer = Microservice? 32
  15. Размер не имеет значения* • Single Responsibility • One capability

    • Bounded context “In your organization, you should be thinking not in terms of data that is shared, but about the capabilities those contexts provide the rest of the domain.” – Sam Newman, Building Microservices *до разумных пределов конечно 33
  16. Пример Микросервис платежей - принимает платеж и проводит его -

    но платежей много типов - а если внешние системы? - а если каждый тип разный для разных групп пользователей? 35
  17. Trade-off - name: copy nginx config sudo: yes template: src:

    "nginx.conf" dest: "{{nginx_config_dir}}/project1.conf" tags: copy_nginx_config - name: copy nginx config sudo: yes template: src: "nginx.conf" dest: "{{nginx_config_dir}}/project2.conf" tags: copy_nginx_config server { server_name {{ hostname }}.superproject; } server { server_name {{ hostname }}.superproject; } 39
  18. Trade-off - N языков программирования - M в среднем фреймворков

    на язык - L типов источников данных complexity = N * M * L 45
  19. Пример - три языка программирования - два в среднем фреймворка

    на язык - семь типов источников данных - legacy WS - mongo db - реляционная БД (oracle) - хранимые процедуры - JDBC templates/ORM - elasticsearch - neo4j/orient db - мишкина база complexity = 3 * 2 * 7 = 42 (!) 46
  20. Ключевые характеристики • Domain-Driven Design • Single responsibility • Independent

    DURS ◦ deploy, update, replace, scale • Lightweight contract and communication • Segregation ◦ people ◦ technologies 48
  21. min (N * M * L) -> max (L) 51

    Закон трёх букв
  22. А что есть в мире Java? • Java EE •

    Spring Boot/Spring Cloud • Ratpack • Dropwizard • Vert.x • Restlet • Spark 52
  23. Почему Spring Boot/Spring Cloud? • Развитая экосистема • Неограниченные возможности

    кастомизации и интеграции новых фреймворков • Не только REST/HTTP • Великолепные возможности мониторинга 54
  24. 61

  25. 62

  26. Netflix Eureka 64 • Как работает heartbeat? • Как работает

    healthcheck? eureka.instance.leaseRenewalIntervalInSeconds: 3 eureka.instance.leaseExpirationDurationInSeconds: 3
  27. 69

  28. 71

  29. Какие есть варианты? • Nginx/Haproxy + consul template • Haproxy

    + bamboo (need marathon) • Netflix Zuul (Java way!!!) • Custom Servlet <- все с этого начинают! 72
  30. Nginx + consul_template {{range services}} upstream {{.Name}} { least_conn; {{range

    service .Name}} server {{.Address}}:{{.Port}} max_fails=3 fail_timeout=60 weight=1; {{else}}server localhost:60000;{{end}} } {{end}} server { server_name localhost; {{range services}} location /{{.Name}}/ { proxy_pass http://{{.Name}}/; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } {{end}} } 73
  31. Nginx + consul_template upstream hippoapi { least_conn; server server1:8080 max_fails=3

    fail_timeout=60 weight=1; server server1:8081 max_fails=3 fail_timeout=60 weight=1; server server1:8082 max_fails=3 fail_timeout=60 weight=1; } server { server_name localhost; location /hippoapi/ { proxy_pass http://hippoapi/; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } 74
  32. Bamboo + haproxy + marathon { "Marathon": { "Endpoint": "{{bamboo_marathon_endpoint}}",

    "UseEventStream": true }, "Bamboo": { "Endpoint": "{{bamboo_endpoint}}", "Zookeeper": { "Host": "{{bamboo_zk_hosts}}", "Path": "/marathon-haproxy/state", "ReportingDelay": 5 }}, "HAProxy": { "TemplatePath": "config/haproxy_template.cfg", "OutputPath": "/etc/haproxy/haproxy.cfg", "ReloadCommand": "haproxy -f /etc/haproxy/haproxy.cfg -p /var/run/haproxy.pid -D -sf $(cat /var/run/haproxy.pid)" }, "StatsD": { "Enabled": false, "Host": "localhost:8125", "Prefix": "{{bamboo_statsd_prefix}}" } } Работает при наличии mesos+marathon :) 75
  33. Netflix Zuul 77 POST /myservice?param1=1&param2=2&param3=3 BODY { “order_id”: 1234 }

    Что тут может быть не так? if(request.getMethod().equalsIgnoreCase("POST") && request.getQueryString() !=null) { StringTokenizer st = new StringTokenizer(this.request.getQueryString(), "&"); while (st.hasMoreTokens()) { String s = st.nextToken(); int i = s.indexOf("="); if (i > 0 && s.length() > i + 1) { String name = s.substring(0, i); builder.remove(name); } } } POST /myservice?param1=1&param2=2&param3=3 Окау, добавим свой Zull pre filter
  34. 82

  35. +-------------------------------------------+ | Server | | (single-threaded, event-driven etc) | +-------------------------------------------+

    | Processor | | (compiler generated) | +-------------------------------------------+ | Protocol | | (JSON, compact, binary etc) | +-------------------------------------------+ | Transport | | (raw TCP, HTTP etc) | +-------------------------------------------+ • Просто* • Гибко* • Безопасно* *по нашему скромному мнению 83 Apache Thrift
  36. namespace java info.developerblog.services struct TUser { #это наш любимый пользователь

    1: required i64 userId #а это его идентификатор } struct TFbiResponse { #результат вызова сервиса 1: required string lastFink #дата последнего стука ( да, это строка :) ) } service TFbiService { #а это наш сервис TFbiResponse fink( #метод “постучи в ФБР” 1: required TUser user, 2: required i32 hippoCount, 3: required i32 fee ) } 84
  37. Thrift API Gateway service InternalTestService { SomeReturnData getSomeData( 1: UserData

    userData, 2: RequestData requestData ) throws (1: SomeException e); } 91
  38. Thrift API Gateway service InternalTestService { SomeReturnData getSomeData( 1: UserData

    userData, 2: RequestData requestData ) throws (1: SomeException e); } service ExternalTestService { SomeReturnData getSomeData( 1: AuthToken authData, 2: RequestData requestData ) throws (1: SomeException e, 99: UnauthorizedException ue); } 92
  39. int startPosition = findStartPosition(protocol); TBase userData = exchanger.process( extractAuthToken(protocol,exchanger.createEmptyAuthToken()) );

    int endPosition = findEndPosition(protocol); return mergeArrays( getSkippedPart(protocol, startPosition), serializeUserData(protocolFactory, userData), getAfterTokenPart(protocol, endPosition, thriftBody.length) ); 93
  40. 94

  41. Springway @SpringBootApplication @EnableThriftGateway public class Application { public static void

    main(String[] args) { SpringApplication.run(Application.class, args); } } 95
  42. 104

  43. И чё? • В Spring-е нет: ◦ @ThriftHandler ◦ @ThriftClient

    ◦ @EnableThriftGateway • Consul Cloud -> 1.0.0.M3
  44. 110

  45. Эра PAAS • Mesos + Marathon framework • Kubernetes •

    Cloud foundry • Other.. ◦ Heroku ◦ Tutum ◦ Mesosphere DCOS ◦ ... 115
  46. HTTP/2 • HTTP/2 Client (Java SE) ◦ http://openjdk.java.net/jeps/110 • Servlet

    4.0 (HTTP/2) ◦ https://www.jcp.org/en/jsr/detail?id=369 117
  47. Hello grpc world! service Greeter { rpc SayHello (HelloRequest) returns

    (HelloReply) {} } message HelloRequest { string name = 1; } message HelloReply { string message = 1; } public static interface Greeter { public void sayHello(HelloRequest request, StreamObserver<HelloReply> responseObserver); } 119
  48. Docker Network http://developerblog.info/2015/11/16/splendors-and-miseries-of-docker-network/ • синтаксический сахар ◦ docker network create

    --driver bridge mynet • пока проблемы с multi-host сетями ◦ несколько сетевых интерфейсов ◦ рудиментарный DNS ◦ плагины не работают/не на 100% 121
  49. Docker Network + Spring Consul Cloud https://github.com/spring-cloud/spring-cloud-consul/issues/115 public static InetAddress

    getFirstNonLoopbackAddress() { /// for (Enumeration<NetworkInterface> enumNic = NetworkInterface.getNetworkInterfaces(); enumNic.hasMoreElements(); ) { /// } /// } eth0 - overlay eth1 - bridge 122
  50. Java SE 9 • Jigsaw ◦ http://openjdk.java.net/jeps/200 • Java Reactive

    JEP 266 (не в 9ке видимо) ◦ http://openjdk.java.net/jeps/266 124
  51. Eureka 2.0 • server group • guaranted instance id uniqueness

    • fast and simple replication • write cluster/read cluster 125
  52. 127

  53. 128

  54. Saga guarantee • T1 -> T2 -> T3 -> …

    -> Tn • T1 -> T2 -> … Tn -> Cn … -> C2 -> C1 129
  55. 130

  56. 131

  57. 132

  58. Выводы. Микросервисы... 134 1. должны работать как единая система для

    предоставления законченной функциональности 2. дают вам опции, как тестировать и где тестировать ваш код 3. дают возможность закладывать нужные оси вариативности в вашу архитектуру (да да, подготавливаемся вставлять костыли на любых уровнях!) 4. предполагают, что вы готовы вникать в вещи, не связанные непосредственно с кодом продукта (а это 80% времени) 5. принесут вам радость, только если налажен CD, иначе только боль
  59. 135

  60. Code. Better. Together. Spring Thrift Client (Proof of Concept) https://github.com/aatarasoff/spring-thrift-starter

    Thrift API Gateway (Proof of Concept) https://github.com/aatarasoff/thrift-api-gateway-core https://github.com/aatarasoff/spring-thrift-api-gateway Примеры сегодняшнего дня https://github.com/lavcraft/jug-samples 137
  61. Высокие теории Sam Newman “Building Microservices” Martin Fowler “Microservice TradeOff”

    “Microservices” “The Twelwe-Factor App” http://12factor.net Hystrix: managing failures in distributed systems - Tomasz Nurkiewicz https: //www.youtube.com/watch?v=JadVts_prtA 138