一、项目搭建
下面我们来一步步搭建spring Cloud生产环境(如果你是老手可以跳过这里)
下面我是通过截图一步步来演示的。
同时到父项目的pom.xml中导入我们的依赖,进行子项目的依赖版本控制
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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.xkkj</groupId>
<artifactId>springcloudparent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springcloudparent</name>
<description>springCloud父级项目</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.RELEASE</spring-cloud.version>
</properties>
<dependencyManagement>
<dependencies>
<!--springCloud-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
到这里我们的父项目就建好了,因为我们使用的是Spring Cloud微服务,所以框架结构为一个基座+多个子模块,该项目就是用来管理子项目依赖,和提供一个统一的工作区间。
1、创建Eureka注册中心
如果你看过我的上篇帖子或者了解过Spring Cloud相关组件,你应该知道,Eureka是服务的管理者(服务注册和发现)。,而我们的微服务就是把一整个后台应用拆分成小的功能模块, 那么这些模块之间就是通过将服务注册到Eureka,通过注册中心来相互通信的?
那么我们现在就来创建Eureka注册中心项目
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">
<parent>
<artifactId>springcloudparent</artifactId>
<groupId>com.xkkj</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>SpringCloud-EureKa</artifactId>
<dependencies>
<!--eureka服务端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
</project>
启动类:
@SpringBootApplication
@EnableEurekaServer
public class EureKaApplication {
public static void main(String[] args) {
SpringApplication.run(EureKaApplication.class,args);
}
}
配置application.yml, 其实application.properties和application.yml这两个配置文件都可以配置工程, 只不过相比之下yml更直观一些,不过请注意缩进, 因为yml使用缩进来区分不同字段的
yml配置文件:
server:
# 配置服务端口
port: 8081
eureka:
client:
service-url:
# 配置eureka服务器地址
defaultZone: http://127.0.0.1:8081/eureka
#是否需要将自己注册到注册中心(注册中心集群需要设置为true)
register-with-eureka: false
#是否需要搜索服务信息 因为自己是注册中心所以为false
fetch-registry: false
注意:这里如果yml文件运行时候报错,请先将中文注释删除,或者修改编码格式。
下面我们去自己的启动类,启动项目,启动后,我们可以看到日志输出
那么我们现在通过浏览器访问注册中心客户端:http://localhost:8081
我们可以正确访问,就说明我们的注册中心配置好了,是不是很简单呢。
二、创建微服务
刚刚我们创建了注册中心,现在我们就来创建两个服务,待会我们来实现他们自己的调用关系。
下面我们分别导入maven坐标和创建启动类和配置文件
pom.xml,两个项目都导入下方这个坐标
<dependencies>
<!--eureka客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
分别创建启动类
启动类A
@SpringBootApplication
@EnableEurekaClient
public class ServiceAApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceAApplication.class,args);
}
}
启动类B
@SpringBootApplication
@EnableEurekaClient
public class ServiceBApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceBApplication.class,args);
}
}
yml配置A
server:
# 服务端口号
port: 8888
spring:
application:
# 服务名称 - 服务之间使用名称进行通讯
name: service-a
eureka:
client:
service-url:
# 填写注册中心服务器地址
defaultZone: http://localhost:8081/eureka
# 是否需要将自己注册到注册中心
register-with-eureka: true
# 是否需要搜索服务信息
fetch-registry: true
instance:
# 使用ip地址注册到注册中心
prefer-ip-address: true
# 注册中心列表中显示的状态参数
instance-id: ${spring.cloud.client.ip-address}:${server.port}
yml配置B
server:
# 服务端口号
port: 9999
spring:
application:
# 服务名称-服务之间使用名称进行通讯
name: service-b
eureka:
client:
service-url:
# 填写注册中心服务器地址
defaultZone: http://localhost:8081/eureka
# 是否需要将自己注册到注册中心
register-with-eureka: true
# 是否需要搜索服务信息
fetch-registry: true
instance:
# 使用ip地址注册到注册中心
prefer-ip-address: true
# 注册中心列表中显示的状态参数
instance-id: ${spring.cloud.client.ip-address}:${server.port}
接下来,我们运行两个服务看看效果
启动后,我们可以去注册中心看看,你会发现我们的服务已经注册到了注册中心
那么接下来我们就通过部分代码来让大家看看效果首先我们到Service-A中编写一个接口,创建controller
HelloWorldController.java
@RestController
@RequestMapping("hello")
public class HelloWorldController {
@GetMapping
public String hello(){
return "欢迎来到Spring Cloud微服务的世界!";
}
}
接下来我们重启Service-A项目
访问:http://localhost:8888/hello
访问成功,但是现在这种访问方式只是我们平时单模块开发时,项目的服务方式,这里都没有使用到注册中心,所以我们现在使用Service-B访问Service-A的接口,该如何实现呢。下面我们一起来看看
要想Service-B调用Service-A,就需要用到eurka(注册中心)和feign客户端了,所以我们现在需要先导入feign的maven坐标。
B中导入坐标:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
编写client接口,用于访问Service-A服务
HelloworldClient.java
@FeignClient("Service-A")
public interface HelloworldClient {
@GetMapping("hello")
public String hello();
}
编写controller,注入上方的HelloworldClient
package com.xkkj.serviceb.controller;
import com.xkkj.serviceb.client.HelloworldClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @description: HelloWorldController
* @author: xuhao
* @time: 2019/12/12 17:10
*/
@RestController
public class HelloWorldController {
@Autowired
private HelloworldClient helloworldClient;
@GetMapping("hello")
public String hello(){
return helloworldClient.hello();
}
}
最后我们在启动类上加上注解:@EnableFeignClients,就可以实现服务间的调用
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class ServiceBApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceBApplication.class,args);
}
}
最后我们运行看看效果:http://localhost:9999/hello
显然调用成功了,但是还有一个情况我们没有考虑,服务间的请求是有默认时间限制的,如果超过时间就会报错,feign默认的响应时间是1000mm,所以我们在配置文件中配置feign的超时时间即可
在service-b的yml中配置:
ribbon:
#建立连接超时时间
ReadTimeout: 5000
#读取资源超时间
ConnectTimeout: 5000
这样就可以有效避免因为响应慢而导致报错的这种情况。
这里的ribbon相信大家如果有一定了解,应该都知道它可以实现负载均衡
那么我们现在来看看,它是实现的效果。
首先我们将Service-A的controller方法,输出一条相信到控制台,我们就可以清晰看到那个服务执行了。
/**
* @description: HelloWorldController
* @author: xuhao
* @time: 2019/12/12 16:43
*/
@RestController
@RequestMapping("hello")
public class HelloWorldController {
@GetMapping
public String hello(){
System.out.println("欢迎来到Spring Cloud微服务的世界!");
return "欢迎来到Spring Cloud微服务的世界!";
}
}
负载均衡肯定是同一个请求,但是被分到了不同的服务端口或者服务
那么我们现在将Service-A服务改变端口,启动两次模拟负载均衡的环境
我们现在重启项目,启动后查看注册中心:
现在我们重新运行:http://localhost:9999/hello
并且清空控制台,运行后你会发现,刚刚那就输出语句分别打印在项目的8888端口和8889端口,然后他们之间来回切换,这就是我们所谓的本地负载均衡。