Book-Microservices-v2 / update-2.4.0

Update package: Spring Boot 2.4.0, Spring Cloud 2020.0, JDK 15, and more
13 stars 6 forks source link

Bug when we scale up the app with Docker #3

Open mi2shiii opened 3 years ago

mi2shiii commented 3 years ago

In page 402, we can scale up the app using the blow command:

docker-compose up --scale multiplication=2 --scale gamification=2

This is my result of calling leaderboard api ( http :8000/leaders) before and after scaling up the project:

Before:

Mahdis-MacBook-Pro:LearningMicroServices-v2-update-2.4.0-master mahdishabani$ http :8000/leaders HTTP/1.1 200 OK Content-Type: application/json Date: Sun, 04 Apr 2021 08:35:48 GMT Vary: Origin Vary: Access-Control-Request-Method Vary: Access-Control-Request-Headers transfer-encoding: chunked

[ { "badges": [ "First time" ], "totalScore": 10, "userId": 1 } ]

And After scaling up , each time I got different response:

First call:

Mahdis-MacBook-Pro:LearningMicroServices-v2-update-2.4.0-master mahdishabani$ http :8000/leaders HTTP/1.1 200 OK Content-Type: application/json Date: Sun, 04 Apr 2021 09:09:47 GMT Vary: Origin Vary: Access-Control-Request-Method Vary: Access-Control-Request-Headers transfer-encoding: chunked

[]

Second Call:

Mahdis-MacBook-Pro:LearningMicroServices-v2-update-2.4.0-master mahdishabani$ http :8000/leaders HTTP/1.1 200 OK Content-Type: application/json Date: Sun, 04 Apr 2021 09:14:29 GMT Vary: Origin Vary: Access-Control-Request-Method Vary: Access-Control-Request-Headers transfer-encoding: chunked

[ { "badges": [ "First time" ], "totalScore": 10, "userId": 1 } ]

Third call:

Mahdis-MacBook-Pro:LearningMicroServices-v2-update-2.4.0-master mahdishabani$ http :8000/leaders HTTP/1.1 200 OK Content-Type: application/json Date: Sun, 04 Apr 2021 09:14:29 GMT Vary: Origin Vary: Access-Control-Request-Method Vary: Access-Control-Request-Headers transfer-encoding: chunked

[ { "badges": [ "First time" ], "totalScore": 10, "userId": 1 } ]

Screenshot 2021-04-04 at 13 45 50 Screenshot 2021-04-04 at 13 45 45 Screenshot 2021-04-04 at 13 45 36

You can see each time I refresh the page, I got a different result.

This problem just happens when I scaled up the project. Before scaling up, everything was stable and consistent.

mechero commented 3 years ago

You are right, it's a known issue. Unfortunately, this is something I noticed after the book was released, so it's missing an explanation.

In Chapter 7's "Scaling Up Microservices" section (page 274 in the printed version), I describe how multiple instances can share the same database and therefore the same state, keeping the microservices stateless. In Listing 7-20, the reader learns how to enable the Server Mode in H2.

However, H2's Server Mode as it's used in the book doesn't work with Docker. Each container has its own independent storage, so they can't see each other's H2 instance. They create independent databases. That's why you see that one call gets the statistics and the next one doesn't. The load balancer is directing the call each time to a different microservice instance, which uses an isolated database.

You can configure Docker (via docker compose) and set up a shared volume for all instances. This way, the second instance will have access to the file created by the first one, and the server mode will work correctly. Give it a try, or let me know if you prefer that I give you the solution.

Thanks for reporting it!

mi2shiii commented 3 years ago

Thanks for the explanation. It would be great if you could give me the solution. I was also thinking to use another db like postgre or mongo instead of H2.

mi2shiii commented 3 years ago

Any update @mechero?

mechero commented 3 years ago

I was hoping that someone else would post the solution but didn't happen so far 😅

I'll post a solution this or next week.

mi2shiii commented 3 years ago

Great. Waiting for it.

mechero commented 3 years ago

This is the updated version of docker-compose-public.yml that fixes the problem. As you can see, it modifies the database location via SPRING_DATASOURCE_URL environment property. Besides, it declares a volume pointing to that same location, the /tmp folder.

version: "3"

services:
  frontend:
    image: learnmicro/challenges-frontend:0.0.1
    ports:
      - '3000:80'
  multiplication:
    image: learnmicro/multiplication:0.0.1
    environment:
      - SPRING_PROFILES_ACTIVE=docker
      - SPRING_CLOUD_CONSUL_HOST=consul
      - SPRING_DATASOURCE_URL=jdbc:h2:file:/tmp/multiplication;DB_CLOSE_ON_EXIT=FALSE;AUTO_SERVER=TRUE;
    depends_on:
      - rabbitmq-dev
      - consul-importer
    networks:
      - microservices
    volumes:
      - temp:/tmp/
  gamification:
    image: learnmicro/gamification:0.0.1
    environment:
      - SPRING_PROFILES_ACTIVE=docker
      - SPRING_CLOUD_CONSUL_HOST=consul
      - SPRING_DATASOURCE_URL=jdbc:h2:file:/tmp/multiplication;DB_CLOSE_ON_EXIT=FALSE;AUTO_SERVER=TRUE;
    depends_on:
      - rabbitmq-dev
      - consul-importer
    networks:
      - microservices
    volumes:
      - temp:/tmp/      
  gateway:
    image: learnmicro/gateway:0.0.1
    ports:
      - '8000:8000'
    environment:
      - SPRING_PROFILES_ACTIVE=docker
      - SPRING_CLOUD_CONSUL_HOST=consul
    depends_on:
      - rabbitmq-dev
      - consul-importer
    networks:
      - microservices
  logs:
    image: learnmicro/logs:0.0.1
    environment:
      - SPRING_PROFILES_ACTIVE=docker
      - SPRING_CLOUD_CONSUL_HOST=consul
    depends_on:
      - rabbitmq-dev
      - consul-importer
    networks:
      - microservices
  consul-importer:
    image: learnmicro/consul-importer:0.0.1
    depends_on:
      - consul-dev
    networks:
      - microservices
  consul-dev:
    image: consul:1.7.2
    container_name: consul
    ports:
      - '8500:8500'
      - '8600:8600/udp'
    command: 'agent -dev -node=learnmicro -client=0.0.0.0 -log-level=INFO'
    networks:
      - microservices
  rabbitmq-dev:
    image: rabbitmq:3-management
    container_name: rabbitmq
    ports:
      - '5672:5672'
      - '15672:15672'
    networks:
      - microservices

networks:
  microservices:
    driver: bridge
volumes:
  temp:

I'll update the book's web page to log this error, which is actually coming from Chapter 7.

Thanks once more for reporting it and for your patience!