SpringCloud系列二:硬编码实现简单的服务提供者与服务消费者

从本文开始,以一个电影售票系统为例讲解Spring Cloud

1. 版本

  jdk:1.8

  SpringBoot:2.0.0.RELEASE

  SpringCloud:Finchley.M8

2. 系统信息

  使用Spring Data JPA作为持久层框架,使用H2作为数据库

3. 编写服务提供者

  开发:

  > 创建一个Spring Boot项目。pom.xml内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.itmuch.cloud</groupId>
    <artifactId>microservice-simple-provider-user</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

  其中,spring-boot-starter-web提供了SpringMVC支持;spring-boot-starter-data-jpa提供了Spring Data JPA的支持。

  > 准备好建表语句,在项目的resources目录下创建sql文件夹,在sql文件夹下建立schema.sql,并添加如下内容:

DROP TABLE user if EXISTS;
CREATE TABLE user (
  id bigint generated BY DEFAULT AS IDENTITY,
  username VARCHAR(40),
  name VARCHAR(20),
  age INT(3),
  balance DECIMAL(10, 2),
  PRIMARY KEY (id)
);

  > 准备几条数据,在sql文件夹下创建data.sql,并添加如下内容:

INSERT INTO user (id, username, name, age, balance)
  VALUES (1, 'account1', '张三', 20, 100.00);
INSERT INTO user (id, username, name, age, balance)
  VALUES (2, 'account2', '李四', 28, 180.00);
INSERT INTO user (id, username, name, age, balance)
  VALUES (3, 'account3', '王五', 32, 280.00);

  > 创建用户实体类

package com.itmuch.cloud.microservicesimpleprovideruser.pojo;

import javax.persistence.*;
import java.math.BigDecimal;

@Entity
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @Column
    private String username;
    @Column
    private String name;
    @Column
    private Integer age;
    @Column
    private BigDecimal balance;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public BigDecimal getBalance() {
        return balance;
    }

    public void setBalance(BigDecimal balance) {
        this.balance = balance;
    }
}

  > 创建DAO

package com.itmuch.cloud.microservicesimpleprovideruser.dao;

import com.itmuch.cloud.microservicesimpleprovideruser.pojo.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}

  > 创建Controller

package com.itmuch.cloud.microservicesimpleprovideruser.controller;

import com.itmuch.cloud.microservicesimpleprovideruser.dao.UserRepository;
import com.itmuch.cloud.microservicesimpleprovideruser.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @Autowired
    private UserRepository userRepository;

    @GetMapping("/{id}")
    public User findById(@PathVariable Long id) {
        User findOne = userRepository.findById(id).get();
        return findOne;
    }

}

  > 编写配置文件。将application.properties重命名为application.yml。

server:
  port: 8000
spring:
  jpa:
    generate-ddl: false
    show-sql: true
    hibernate:
      ddl-auto: none
  datasource:                           # 指定数据源
    platform: h2                        # 指定数据源类型
    url: jdbc:h2:mem:cloud              # 指定h2数据库的连接地址
    driver-class-name: org.h2.Driver   # 指定h2数据库的驱动
    username: root                      # 指定h2数据库的登录用户
    password: 20121221                  # 指定h2数据库的登录密码
    schema: classpath:/sql/schema.sql   # 指定h2数据库的建表脚本
    data: classpath:/sql/data.sql       # 指定h2数据库的数据脚本
  h2:
    console:
      path: /h2-console
      enabled: true
logging:
  level:
    org.hibernate: info
    org.hibernate.type.descriptor.sql.BasicBinder: TRACE
    org.hibernate.type.descriptor.sql.BasicExtractor: TRACE
info:
  app:
    name: microservice-simple-provider-user
    encoding: UTF-8
    java:
      source: 1.8
      target: 1.8

  测试:

  在开发中整合了actuator模块,Spring Boot Actuator提供了很多监控端点。

  具体可查看:http://www.cnblogs.com/jinjiyese153/p/8607895.html

  > Spring Boot Actuator测试

  启动Spring Boot项目,访问:http://localhost:8000/actuator/health,若如下图,则正常

  (默认只展示状态,详细信息不展示。若想查看详细信息,可点击上方URL查看

  > 项目测试

  启动Spring Boot项目,访问:http://localhost:8000/1,若如下图,则正常

 4. 编写服务消费者

  开发:

  > 创建一个Spring Boot项目。pom.xml内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.itmuch.cloud</groupId>
    <artifactId>microservice-simple-consumer-movie</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

  > 创建一个用户实体类

package com.itmuch.cloud.microservicesimpleconsumermovie.pojo;

import java.math.BigDecimal;

public class User {

    private Long id;
    private String username;
    private String name;
    private Integer age;
    private BigDecimal balance;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public BigDecimal getBalance() {
        return balance;
    }

    public void setBalance(BigDecimal balance) {
        this.balance = balance;
    }
}

  > 修改启动类

package com.itmuch.cloud.microservicesimpleconsumermovie;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
public class MicroserviceSimpleConsumerMovieApplication {

    public static void main(String[] args) {
        SpringApplication.run(MicroserviceSimpleConsumerMovieApplication.class, args);
    }

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

  > 创建Controller,在其中使用RestTemplate请求用户微服务的API。

package com.itmuch.cloud.microservicesimpleconsumermovie.controller;

import com.itmuch.cloud.microservicesimpleconsumermovie.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class MovieController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/user/{id}")
    public User findById(@PathVariable Long id) {
        return this.restTemplate.getForObject("http://localhost:8000/" + id, User.class);
    }

}

  > 编写配置文件。将application.properties重命名为application.yml。

server:
  port: 8010
info:
  app:
    name: microservice-simple-consumer-movie
    encoding: UTF-8
    java:
      source: 1.8
      target: 1.8

  测试:

  在开发中同样整合了actuator模块

  具体可查看:http://www.cnblogs.com/jinjiyese153/p/8607895.html

  > Spring Boot Actuator测试

  启动Spring Boot项目,访问:http://localhost:8010/actuator/health,若如下图,则正常

  > 项目测试

  启动Spring Boot项目,访问:http://localhost:8010/user/1,若如下图,则正常

5. 总结

  在传统的应用程序中,一般都是这样做的。然而,这种方式存在问题。

  1. 适用场景有限:如果服务提供者的网络地址(IP和端口)发生了变化,将会影响服务消费者。

  2. 无法动弹伸缩:在生成环境中,每个微服务一般都会部署多个实例,从而实现容灾和负载均衡。在微服务架构的系统中,还需要系统具备自动伸缩的能力,例如动态增加节点等。硬编码无法适应这种需求。

  将会在下一篇博客中,解决这些问题。敬请期待~~~

6. 参考
  周立 --- 《Spring Cloud与Docker微服务架构与实战》

 

posted @ 2018-03-20 15:19  禁忌夜色153  阅读(1603)  评论(0编辑  收藏  举报