step05 day01 learning notes springcloud practice

Posted by lexx on Fri, 10 Sep 2021 20:43:12 +0200

1. Introduction to springcloud

1.1 INTRODUCTION

spring cloud is a collection of frameworks. Taking advantage of the development convenience of spring boot, it cleverly simplifies the development of distributed system infrastructure, such as service discovery and registration, configuration center, message bus, load balancing, circuit breaker, data monitoring, etc., which can be started and deployed with one click with the development style of spring boot. spring cloud does not repeatedly manufacture wheels. It just combines the relatively mature and practical service frameworks developed by various companies, repackages them through the spring boot style, shields the complex configuration and implementation principles, and finally leaves a set of distributed system development kit that is easy to understand, deploy and maintain for developers.

Spring cloud is a blessing for small and medium-sized Internet companies, because such companies often do not have the strength or sufficient capital investment to develop their own distributed system infrastructure. Using spring cloud one-stop solution can not only calmly deal with business development, but also greatly reduce development costs. At the same time, with the popularity of microservice architecture and docker container concept in recent years, spring cloud will also have a place in the future more and more "cloud" software development style. In particular, it provides standardized and one-stop technical solutions in the current variety of distributed solutions, which may be as meaningful as the birth of servlet specification in that year, Effectively promote the progress of the technical level of the server software system.

1.2 technical composition

Insert picture description here
explain:
eureka microservice governance, service registration and discovery
ribbon load balancing, request retry
hystrix circuit breaker, service degradation, fusing
feign ribbon + hystrix integration and declarative client
hystrix dashboard and turbine hystrix data monitoring
zuul API gateway provides a unified entrance to microservices and unified permission verification
config configuration center
Bus message bus, configuration refresh
sleuth+zipkin link tracking

2. Microservice architecture

2.1 Spring Cloud vs. Dubbo

! [insert picture description here]( https://img-blog.csdnimg.cn/a5950a6672a445c4ab73c7683285c566.png?x-oss-process=image/watermark,t
ype_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAbHlkb244ODg=,size_20,color_FFFFFF,t_70,g_se,x_16)

2.2 service microservice invocation process

3. Project code

3.1 service creation process

1. Create project
2. Configuration dependency

Make a series of corresponding configurations in the pom.xml file
Parent project dependency (Description: automatically generated after the project is created)

3. Configure writing source files

4. Write goods and services

ItemServiceImpl

ItemController

Access test

3.2 common items

1.pom.xml

<dependencies>
        <dependency>
            <groupId>com.fasterxml.jackson.module</groupId>
            <artifactId>jackson-module-parameter-names</artifactId>
            <version>2.9.8</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.datatype</groupId>
            <artifactId>jackson-datatype-jdk8</artifactId>
            <version>2.9.8</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.datatype</groupId>
            <artifactId>jackson-datatype-jsr310</artifactId>
            <version>2.9.8</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.datatype</groupId>
            <artifactId>jackson-datatype-guava</artifactId>
            <version>2.9.8</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.6</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.26</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.9</version>
        </dependency>
    </dependencies>

explain:

2. Project structure (same as above)

3.util layer
cookieutil

public class CookieUtil {
    /**
     * @param response
     * @param name
     * @param value
     * @param maxAge
     */
    public static void setCookie(HttpServletResponse response,
                                 String name, String value, String domain, String path, int maxAge) {
        Cookie cookie = new Cookie(name, value);
        if (domain != null) {
            cookie.setDomain(domain);
        }
        cookie.setPath(path);
        cookie.setMaxAge(maxAge);
        response.addCookie(cookie);
    }

    public static void setCookie(HttpServletResponse response, String name, String value, int maxAge) {
        setCookie(response, name, value, null, "/", maxAge);
    }

    public static void setCookie(HttpServletResponse response, String name, String value) {
        setCookie(response, name, value, null, "/", 3600);
    }

    public static void setCookie(HttpServletResponse response, String name) {
        setCookie(response, name, "", null, "/", 3600);
    }

    /**
     * @param request
     * @param name
     * @return
     */
    public static String getCookie(HttpServletRequest request, String name) {
        String value = null;
        Cookie[] cookies = request.getCookies();
        if (null != cookies) {
            for (Cookie cookie : cookies) {
                if (cookie.getName().equals(name)) {
                    value = cookie.getValue();
                }
            }
        }
        return value;
    }

    /**
     * @param response
     * @param name
     * @return
     */
    public static void removeCookie(HttpServletResponse response, String name, String domain, String path) {
        setCookie(response, name, "", domain, path, 0);
    

jsonresult

@Getter
@Setter
public class JsonResult<T> {
    /** success */
    public static final int SUCCESS = 200;

    /** not logged on */
    public static final int NOT_LOGIN = 400;

    /** exception occurred */
    public static final int EXCEPTION = 401;

    /** System error */
    public static final int SYS_ERROR = 402;

    /** Parameter error */
    public static final int PARAMS_ERROR = 403;

    /** Unsupported or obsolete */
    public static final int NOT_SUPPORTED = 410;

    /** AuthCode error */
    public static final int INVALID_AUTHCODE = 444;

    /** Too frequent calls */
    public static final int TOO_FREQUENT = 445;

    /** unknown error */
    public static final int UNKNOWN_ERROR = 499;

    private int code;
    private String msg;
    private T data;



    public static JsonResult build() {
        return new JsonResult();
    }
    public static JsonResult build(int code) {
        return new JsonResult().code(code);
    }
    public static JsonResult build(int code, String msg) {
        return new JsonResult<String>().code(code).msg(msg);
    }
    public static <T> JsonResult<T> build(int code, T data) {
        return new JsonResult<T>().code(code).data(data);
    }
    public static <T> JsonResult<T> build(int code, String msg, T data) {
        return new JsonResult<T>().code(code).msg(msg).data(data);
    }

    public JsonResult<T> code(int code) {
        this.code = code;
        return this;
    }
    public JsonResult<T> msg(String msg) {
        this.msg = msg;
        return this;
    }
    public JsonResult<T> data(T data) {
        this.data = data;
        return this;
    }


    public static JsonResult ok() {
        return build(SUCCESS);
    }
    public static JsonResult ok(String msg) {
        return build(SUCCESS, msg);
    }
    public static <T> JsonResult<T> ok(T data) {
        return build(SUCCESS, data);
    }
    public static JsonResult err() {
        return build(EXCEPTION);
    }
    public static JsonResult err(String msg) {
        return build(EXCEPTION, msg);
    }

    @Override
    public String toString() {
        return JsonUtil.to(this);
    }
}

4. Test

3.3 item service

1.pom.xml

<dependency>
            <groupId>com.lydon</groupId>
            <artifactId>sp01-commons1</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

2. Project structure

ItemserviceImpl

@Slf4j
@Service
public class ItemServiceImpl implements ItemService {
    @Override
    public List<Item> getItems(String orderId) {
        log.info("Get goods,orderId="+orderId);
        List<Item> items=new ArrayList<>();
        items.add(new Item(1,"Commodity 1",1));
        items.add(new Item(2,"Commodity 2",5));
        items.add(new Item(3,"Commodity 3",2));
        items.add(new Item(4,"Commodity 4",3));
        items.add(new Item(5,"Commodity 5",4));
        return items;
    }
    @Override
    public void decreaseNumbers(List<Item> items) {
        for (Item item : items){
            log.info("reduce stock:"+item);
        }
    }
}

ItemController

@RestController
@Slf4j
public class ItemController {
    @Autowired
    private ItemService itemService;
    @GetMapping("/{orderId}")
    public JsonResult<List<Item>> getItems(
            @PathVariable String orderId) throws InterruptedException {
        List<Item> items=itemService.getItems(orderId);
        //Random blocking
        if(Math.random()<0.9){
            //Random extension duration, 0 ~ 5 seconds
            int t=new Random().nextInt(5000);
            log.info("delay"+t);
            Thread.sleep(t);
        }
        return JsonResult.ok().data(items);
    }
    //Testing post requests with postman
    @PostMapping("/decreaseNumber")
    public JsonResult<?>decreaseNumber(
            @RequestBody List<Item> items){
        itemService.decreaseNumbers(items);
        return JsonResult.ok().msg("Self increasing");
    }

3.application.yml

spring:
  application:
    name: item-service #Registry name

#item    8001
#user    8181
#order   8201

server:
  port: 8001

eureka:
  client:
    service-url:
      defaultZone: http://eureka1:2001/eureka

4. Test

3.4 user service

1.pom.xml

<dependency>
            <groupId>com.lydon</groupId>
            <artifactId>sp01-commons1</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

2. Project structure

ItemserviceImpl

@Service
@Slf4j
public class UserServiceImpl implements UserService {
    @Value("${sp.user-service.users}")
    private String userJson;

    @Override
    public User getUser(Integer userId) {
        //userJson-->List<User>
        List<User> list = JsonUtil.from(
                userJson, new TypeReference<List<User>>() {});
        for (User u:list){
           if(u.getId().equals(userId)){
               return  u;
           }
       }
        return new User (userId,"user name="+userId,"password="+userId);
    }

    @Override
    public void addScore(Integer userId, Integer score) {
        log.info("Increase user points","userId="+userId,"score="+score);
    }
}

ItemController

@RestController
@Slf4j
public class UserController {
    @Autowired
    private UserService userService;

    @GetMapping("/{userId}")
    public JsonResult<User> getUser(@PathVariable Integer userId) {
        User user = userService.getUser(userId);
        return JsonResult.ok().data(user);
    }

    //   /8/score?score=1000
    @GetMapping("/{userId}/score")
    public JsonResult<?> addScore(@PathVariable Integer userId,
                                  Integer score) {
        userService.addScore(userId, score);
        return JsonResult.ok().msg("Points increased successfully!");
    }
    @GetMapping("/favicon.ico")
    public void ico(){}
}

3.application.yml

sp:
  user-service:
    users: "[{\"id\":7, \"username\":\"abc\",\"password\":\"123\"},
    {\"id\":8, \"username\":\"def\",\"password\":\"456\"},
    {\"id\":9, \"username\":\"ghi\",\"password\":\"789\"}]"

spring:
  application:
    name: user-service

server:
  port: 8101

eureka:
  client:
    service-url:
      defaultZone: http://eureka1:2001/eureka

4. Test

3.5 order service

1.pom.xml

 <dependency>
            <groupId>com.lydon</groupId>
            <artifactId>sp01-commons1</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
            <version>1.4.2.RELEASE</version>
        </dependency>

2. Project structure

ItemserviceImpl

@Slf4j
@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    private ItemClient itemClient;
    @Autowired
    private UserClient userClient;

    @Override
    public Order getOrder(String orderId) {
        log.info("Get order,orderId="+orderId);
        // Remotely call the product to get the product list
        JsonResult<List<Item>> items = itemClient.getItems(orderId);
        //TODO: call item service to get product information
        //Remotely call the product to obtain the user list
        JsonResult<User> user = userClient.getUser(8);//In a real project, you want to get the login user information
        Order order = new Order();
        order.setId(String.valueOf(user.getData()));
        order.setItems(items.getData());
        return order;
    }
    @Override
    public void addOrder(Order order) {
        //log.info("save order:" + order);
        log.info("Add order: "+order);
        //TODO: call item service to reduce commodity inventory
        //TODO: call user service to increase user points

        //TODO: call commodities remotely to reduce inventory
        itemClient.decreaseNumber(order.getItems());
        //TODO: call users remotely to increase points
        userClient.addScore(order.getUser().getId(),1000);
       }
}

ItemController

@Slf4j
@RestController
public class OrderController {
    @Autowired
    private OrderService orderService;

    @GetMapping("/{orderId}")
    public JsonResult<Order> getOrder(@PathVariable String orderId) {
        log.info("get order, id="+orderId);
        // TODO: call commodities remotely to obtain commodity list
        // TODO: call the user remotely to obtain user data
        Order order = orderService.getOrder(orderId);
        return JsonResult.ok(order);
    }

    @GetMapping("/add")
    public JsonResult addOrder() {
        //Simulate data submitted by post
        Order order = new Order();
        order.setId("saf1234");
        order.setUser(new User(8,null,null));
        order.setItems(Arrays.asList(new Item[] {
                new Item(1,"aaa",2),
                new Item(2,"bbb",1),
                new Item(3,"ccc",3),
                new Item(4,"ddd",1),
                new Item(5,"eee",5),
        }));
        orderService.addOrder(order);
        return JsonResult.ok().msg("Order added successfully~~");
    }
    @GetMapping("/favicon.ico")
    public void ico(){
    }
}

3.application.yml

spring:
  application:
    name: order-service

server:
  port: 8201

#Client application request address: / eureka sub path
#View erueka console address with browser:/
#defaultZone: if you use cloud services, you can purchase servers in non-stop locations,
#Your own server must be defaultZone

eureka:
  client:
    service-url:
      defaultZone: http://eureka1:2001/eureka,http://eureka2:2002/eureka

4. Test

3.6 service access test summary

1. item-service

Query the goods according to orderid: http://localhost:3001/item-service/
Reduce commodity inventory: http://localhost:8001/decreaseNumber

2.user-service

Query user information according to userid: http://localhost:8101/7

Add points for users according to userid: http://localhost:8101/7/score?score=100

3.order-service

According to orderid, get the order: http://localhost:8201/123abc
Save the order and observe the console log output: http://localhost:8201/

4. Summary

This chapter briefly studies the implementation of some basic services of microservices, and briefly introduces the use of eureka. Through eureka, network companies can easily obtain or manage various services. Its role is similar to that of nacos, but its use has a greater amount of concurrency. The specific implementation will be introduced later.

Topics: Java Spring Boot RESTful