如何搭建一个简单的微服务?

  我们本文,只介绍如何搭建一个微服务架构,其中微服务的理论知识见另一篇文章:

  1、创建父工程(之后所有的服务,均在父工程下创建),引入在pom文件引入依赖

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <project xmlns="http://maven.apache.org/POM/4.0.0"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 5     <modelVersion>4.0.0</modelVersion>
 6 
 7     <groupId>com.mk</groupId>
 8     <artifactId>spring_cloud</artifactId>
 9     <version>1.0-SNAPSHOT</version>
10 
11     <modules>
12         <module>User-Service</module>
13         <module>consumer-user</module>
14         <module>Euraka-service</module>
15         <module>getAwayService</module>
16         <module>myConfig</module>
17     </modules>
18     <packaging>pom</packaging>
19 
20     <properties>
21         <java.version>1.8</java.version>
22         <spring-cloud.version>Greenwich.SR1</spring-cloud.version>
23         <mapper.starter.version>2.1.5</mapper.starter.version>
24         <mysql.version>5.1.46</mysql.version>
25     </properties>
26 
27 
28     <parent>
29         <groupId>org.springframework.boot</groupId>
30         <artifactId>spring-boot-starter-parent</artifactId>
31         <version>2.1.2.RELEASE</version>
32         <relativePath/>
33 
34     </parent>
35 
36     <dependencyManagement>
37     <dependencies>
38         <!-- springCloud -->
39         <dependency>
40             <groupId>org.springframework.cloud</groupId>
41             <artifactId>spring-cloud-dependencies</artifactId>
42             <version>${spring-cloud.version}</version>
43             <type>pom</type>
44             <scope>import</scope>
45         </dependency>
46         <!-- 通用Mapper启动器 -->
47         <dependency>
48             <groupId>tk.mybatis</groupId>
49             <artifactId>mapper-spring-boot-starter</artifactId>
50             <version>${mapper.starter.version}</version>
51         </dependency>
52         <!-- mysql驱动 -->
53         <dependency>
54             <groupId>mysql</groupId>
55             <artifactId>mysql-connector-java</artifactId>
56             <version>${mysql.version}</version>
57         </dependency>
58 
59 
60     </dependencies>
61 </dependencyManagement>
62 <dependencies>
63 <dependency>
64     <groupId>org.projectlombok</groupId>
65     <artifactId>lombok</artifactId>
66 </dependency>
67 </dependencies>
68 <build>
69 <plugins>
70     <plugin>
71         <groupId>org.springframework.boot</groupId>
72         <artifactId>spring-boot-maven-plugin</artifactId>
73     </plugin>
74 </plugins>
75 </build>
76 </project>
View Code

  


 

 

  2、服务提供者:我们的服务是,根据id查询一个user,所以就会引入一些数据库相关的依赖

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <project xmlns="http://maven.apache.org/POM/4.0.0"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 5     <parent>
 6         <artifactId>spring_cloud</artifactId>
 7         <groupId>com.mk</groupId>
 8         <version>1.0-SNAPSHOT</version>
 9     </parent>
10 
11 
12     <modelVersion>4.0.0</modelVersion>
13 
14     <artifactId>User-Service</artifactId>
15 
16     <properties>
17         <maven.compiler.source>8</maven.compiler.source>
18         <maven.compiler.target>8</maven.compiler.target>
19     </properties>
20 
21     <dependencies>
22         <dependency>
23             <groupId>org.springframework.boot</groupId>
24             <artifactId>spring-boot-starter-web</artifactId>
25         </dependency>
26 
27         <dependency>
28             <groupId>org.springframework.boot</groupId>
29             <artifactId>spring-boot-starter-test</artifactId>
30         </dependency>
31 
32 
33         <!-- 通用Mapper启动器 -->
34         <dependency>
35             <groupId>tk.mybatis</groupId>
36             <artifactId>mapper-spring-boot-starter</artifactId>
37         </dependency>
38 
39 
40         <!-- mysql驱动 -->
41         <dependency>
42             <groupId>mysql</groupId>
43             <artifactId>mysql-connector-java</artifactId>
44         </dependency>
45 
46         <dependency>
47             <groupId>org.springframework.cloud</groupId>
48             <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
49         </dependency>
50 
51         <dependency>
52             <groupId>org.springframework.cloud</groupId>
53             <artifactId>spring-cloud-starter-config</artifactId>
54         </dependency>
55     </dependencies>
56 
57 
58 </project>
View Code

  2.1:实体类:其中Data注解,减少代码量

 

 

   2.2:dao层:使用tkMybatis,所以就不需要我们自己写单表的一些语句

 

   2.3:service层:

2.4:controller层:

 

 

2.5:启动类:

 

 

2.6:yml配置文件(配有注释)

 

 

 

  3.1:服务消费者因为客户端,不需要操作数据库,所以只需要实体类和控制层就行。

  3.2:pom依赖文件:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <project xmlns="http://maven.apache.org/POM/4.0.0"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 5     <parent>
 6         <artifactId>spring_cloud</artifactId>
 7         <groupId>com.mk</groupId>
 8         <version>1.0-SNAPSHOT</version>
 9     </parent>
10     <modelVersion>4.0.0</modelVersion>
11 
12     <artifactId>consumer-user</artifactId>
13 
14     <properties>
15         <maven.compiler.source>8</maven.compiler.source>
16         <maven.compiler.target>8</maven.compiler.target>
17     </properties>
18 
19 
20     <dependencies>
21         <dependency>
22             <groupId>org.springframework.boot</groupId>
23             <artifactId>spring-boot-starter-web</artifactId>
24         </dependency>
25 
26 
27         <!--euraka客户端-->
28         <dependency>
29             <groupId>org.springframework.cloud</groupId>
30             <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
31         </dependency>
32 
33         <!--熔断器-->
34         <dependency>
35             <groupId>org.springframework.cloud</groupId>
36             <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
37         </dependency>
38 
39         <!--feign代理-->
40         <dependency>
41             <groupId>org.springframework.cloud</groupId>
42             <artifactId>spring-cloud-starter-openfeign</artifactId>
43         </dependency>
44     </dependencies>
45 
46 </project>
View Code

  3.3:实体类:因为是客户端,所以就不需要那些jpa注解

 1 package com.mk.consumer.pojo;
 2 
 3 import lombok.Data;
 4 
 5 @Data
 6 public class User {
 7   private Long id;
 8   private String userName;
 9   private String password;
10   private String name;
11   private long age;
12   private long sex;
13   private java.sql.Date birthday;
14   private java.sql.Date created;
15   private java.sql.Date updated;
16   private String note;
17 
18 }
View Code

  3.4:controller层:(这里我们采用截图,因为后面会对这里进行改造)

 

   3.5:配置文件:

 

 

  3.6:启动类:

 1 package com.mk.consumer;
 2 
 3 import org.springframework.boot.SpringApplication;
 4 import org.springframework.boot.autoconfigure.SpringBootApplication;
 5 import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
 6 import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
 7 import org.springframework.cloud.client.loadbalancer.LoadBalanced;
 8 import org.springframework.cloud.openfeign.EnableFeignClients;
 9 import org.springframework.context.annotation.Bean;
10 import org.springframework.web.client.RestTemplate;
11 
12 @SpringBootApplication
13 @EnableDiscoveryClient
14 @EnableCircuitBreaker   //开启熔断器
15 @EnableFeignClients //开启feign组件功能
16 public class Application {
17     public static void main(String[] args) {
18         SpringApplication.run(Application.class, args);
19     }
20 
21 
22     /*spring提供的模板,对http进行封装*/
23     @Bean
24     @LoadBalanced       //负载均衡
25     public RestTemplate restTemplate(){
26         return new RestTemplate();
27     }
28 }
View Code

  

 


 

 

  4.1Eureka注册中心;既然后我们客户端和服务端都有了,那么我们还需要搭建自己的Eureka注册中心,来发现服务,引入依赖

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <project xmlns="http://maven.apache.org/POM/4.0.0"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 5     <parent>
 6         <artifactId>spring_cloud</artifactId>
 7         <groupId>com.mk</groupId>
 8         <version>1.0-SNAPSHOT</version>
 9     </parent>
10     <modelVersion>4.0.0</modelVersion>
11 
12     <artifactId>Euraka-service</artifactId>
13 
14     <properties>
15         <maven.compiler.source>8</maven.compiler.source>
16         <maven.compiler.target>8</maven.compiler.target>
17     </properties>
18 
19     <dependencies>
20         <dependency>
21             <groupId>org.springframework.cloud</groupId>
22             <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
23         </dependency>
24     </dependencies>
25 
26 
27 
28 </project>
View Code

  4.2:配置文件:(配有注解)

 1 #端口号
 2 server:
 3   port: 10010
 4 
 5 #服务名,因为Eureka本身也是一个服务
 6 spring:
 7   application:
 8     name: eureka
 9 
10 #服务注册中心的位置
11 eureka:
12   client:
13     service-url:
14       defaultZone: http://127.0.0.1:10010/eureka
15   instance:
16 
17 #      不注册自己
18     register-with-eureka: false
19 #    不拉取服务
20     fetch-registry: false
View Code

  4.3:启动类:

 1 package com.mk.eureka;
 2 
 3 import org.springframework.boot.SpringApplication;
 4 import org.springframework.boot.autoconfigure.SpringBootApplication;
 5 import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
 6 
 7 @SpringBootApplication
 8 @EnableEurekaServer
 9 public class Application {
10     public static void main(String[] args) {
11         SpringApplication.run(Application.class, args);
12     }
13 }
View Code

 

以上我们的客户端,服务端,注册中心都配置完毕,那么我们启动服务看看。

访问Eureka注册中心:注意端口号

 

 

访问我们的服务:(传入id为2),可以看到,返回一个json数据

 

 

以上就是,我们传入正确的id,假如,我们传入的id,在数据库中,不存在怎么办呢。经实践发现,服务就会一直等待,那么我们后续的其他的请求就会阻塞,这样我们后续用户的请求也会阻塞。

  5.Spring Cloud为我们提供了Hystrix组件:特地处理我们服务时间超时,然后我们可以回显给用户一些有好的提示。

  5.1:添加hystrix依赖

 

 

   5.2:在启动类上添加开启@EnableCircuitBreaker的注解

 

 

   5.3.编写我们的降级逻辑,也就是给用户的提示

 

 

 

  5.4.测试降级逻辑,为了确保一定能够满足服务降级的条件(1.该服务的线程池满,2.服务超时(Hystrix的默认超时时长为1)),我们就不启动服务端,那么客户端的请求一定超时,就会触发服务降级。下面是测试结果

 

 

 

 

 从上面可以看出,我们的服务,虽然没有得到应该的结果,但是我们的线程得到释放,并不会影响其他的服务。这就是我们服务降级的一个流程。

 

  那么上面服务降级的方式,我们每增加一个方法是不是,就需要我们在该方法上进行注入呢,还有另外一种,更加简便的方式,就注解在类上,就不用每一个方法都去注入了

 

 

 

 

 

 

 以上我们就搭建了一个简易的微服务,但是还存在一些问题。比如我的3.4步骤中,可以看到我们的url被写死,那么我们后期的需求改变或者说是拓展其他的功能,那么显然是不方便的。

 


 

 

  我们SpringCloud给我们提供了一个叫做feign的组件,是一种声明式、模板化的HTTP客户端。在Spring Cloud中使用Feign, 我们可以做到使用HTTP请求远程服务时能与调用本地方法一样的编码体验,开发者完全感知不到这是远程方法,更感知不到这是个HTTP请求。下面,我们就对客户端进行优化。

 

  6.Feign声明式服务,

  6.1.pom文件依赖,添加如下

 

 

 

  6.2我们添加日志配置类,方便我们对请求的参数,请求体进行查看。

package com.mk.consumer.logger;


import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FeignLogger {
    
    @Bean
    public Logger.Level feignLoggerLevel(){
        //日志级别是记录所有(包括请求的行,请求体,)
        return Logger.Level.FULL;
    }
}
View Code

 

  6.3.下面我们添加我们的客户端控制层的接口,

 

   6.4.我们改造后的控制层,就变得优雅了许多,仿佛就是在调用我们的本地方法。

 

 

  6.5.测试结果

 

从结果可以看出,我们同样可以得到结果,这就是feign组件的作用,方便我们服务的调用,得到与调用本地方法一致的编码体验。

  6.6.feign对hystrix的支持,feign中有对hystrix的支持,我们只需要定义一个类,实现我们6.3中的客户端接口,然后再客户端中通过注解,添加即可。下面是降级逻辑

 

 

 

 

 6.7.下面我们看一下测试结果,触发条件和之前的hystrix一样

 

 


 

7. 以上就是,feign的使用。其实feign就是简化我们内部的,服务与服务之间的调用,那么我们服务暴露给对外的api接口,应该怎样解决呢?同样Spring Cloud提供了Gateway网关组件。

 

 

我们外部的请求,首先就会通过网关的过滤,鉴权,然后才能请求我们内部的服务。下面我们就来配置我们的网关。

7.1,新建一个model,引入依赖

 

 7.2.编写启动类

 7.3,编写配置文件,Gateway,重点就是配置文件

 

 

 

7.4下面我们,启动服务,看看效果

 

 

 


 

  8.上面就是Gateway的简单应用,当然,网关还有一些添加前缀,去除前缀,过滤器的一些使用,大家可以自己去探索。大家肯定会发现,我们整个微服务搭建下来,配置文件超级多,而且以后开发,

所有的配置文件肯定也不是在一台电脑上,所以有的配置文件,就访问不了,没事,SpringCloud也为我们提供了SpringCloud config分布式配置中心。

 

 

 

  8.1.既然要有git仓库,那就自己准备一个,我就不粘贴步骤了,唯一需要注意的是这个配置文件的命名方式,就比如我的配置文件的名字是:“userService-dev.yml”,userService就代表服务名,-这是分隔符,dev就代表是开发环境。

然后就是将我们的userService的配置文案上传到gitee的新建文件,(只截取了一部分)

 

 

8.2新建一个model,引入依赖

 

 

8.3编写启动类

 

 8.4编写配置文件

 

8.5下面我们就通过本地访问git上的配置文件

 

 

这就是我们之前准备的在仓库中的配置文件,这样我们就可以通过配置中心进行访问。

 

  8.6.既然可以通过配置中心访问,下面我们就对我们的服务端的配置文件(就是之前的UserService)进行修改,注意配置文件名改为bootstrap.yml,因为bootstrap.yml文件是Spring Boot的默认配置文件,而且其加载的时间相比于application.yml更早。 application.yml和bootstrap.yml虽然都是Spring Boot的默认配置文件,但是定位却不相同。bootstrap.yml 可以理解成系统级别的一些参数配置,这些参数一般是不会变动的

 

 

 

  8.7.我们重启UserService服务。发现UserService仍然存在,说明能够读取到配置中心的文件。

 

 

 


   9.既然,我们在git配置了配置文件,那么如果,我们在git上进行了修改,那么本地的配置文件会不会自己刷新呢,显然是不会的。我们的Spring cloud也为我们提供了叫做:Spring cloud bus服务总线,专门用于同步git上配置文件的改变。下面我们进行测试。

   9.1. 在8.2中增加如下依赖,

 

   9.3:在8.3增加如下配置

 

   9.4.在往服务提供者中增加如下依赖:

 

 

 

  9.5.修改2.4的controller为:

 

 

   9.6.测试,先正常访问

 

   9.7.控制台输出的是:

 

 

   9.8.我们修改name为mk

 

 

  

  9.9.利用我们postman工具,发送我们在8.3中暴露的api,(注意我们需要提前安装\otp_win64_23.0.exe和rabbitmq-server-3.8.5.exe),因为rabbitmq使用otp语言实现

 

 

   9.10.我们再次访问9.6的url,查看控制台的输出变为我们刚刚更新的mk

 

 

 

 

就实现了我们配置中心改变,同步到本地的功能。


 

 

下面就是SpringCloud的完整体系架构图

 

 

整个微服务搭建完毕,各个组件的功能总结见另外一篇文章:https://www.cnblogs.com/kunmin/p/15108090.html

 

posted @ 2021-08-06 15:19  kunmin  阅读(2225)  评论(0编辑  收藏  举报