Spring Cloud微服务搭建
目录
四、创建ribbon-rest项目-服务消费者(rest方式负载均衡调用)
五、创建feign-hystrix项目-服务消费者(声明式HTTP调用、服务降级处理)
一、创建springcloud项目
打开idea创建maven多模块项目:springcloud,作为一个父工程,然后修改pom文件,引入Spring Cloud相关依赖,如下:
<?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.demo</groupId>
<artifactId>springcloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>springcloud</name>
<description>Demo project for Spring Cloud</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/>
</parent>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.cloud.version>Finchley.RELEASE</spring.cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<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>
<modules>
</modules>
</project>
二、创建eureka-server项目-高可用服务注册中心
在springcloud下创建子模块:eureka-server,pom文件引入以下依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
新建配置文件:application.yml,添加eureka服务端相关配置,如下:
spring:
application:
name: eureka-server
eureka:
instance:
prefer-ip-address: true
server:
enable-self-preservation: false
---
spring:
profiles: eureka-server-1
server:
port: 8081
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8082/eureka/
---
spring:
profiles: eureka-server-2
server:
port: 8082
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8081/eureka/
这里配置了两个profile:eureka-server-1、eureka-server-2,并且让两个Eureka Server相互注册,实现高可用。
然后,编写启动类,在启动类上添加@EnableEurekaServer,声明这是一个Eureka Server:
/**
* eureka 服务注册中心
*/
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
启动后访问:http://localhost:8081,可以看到如下界面:
三、创建eureka-client项目-服务提供者
在springcloud下创建子模块:eureka-client,pom文件引入以下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
新建配置文件:application.yml,添加eureka客户端相关配置,如下:
spring:
application:
name: eureka-client
---
spring:
profiles: eureka-client-1
server:
port: 8084
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8081/eureka/
---
spring:
profiles: eureka-client-2
server:
port: 8085
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8082/eureka/
这里同样配置了两个profile:eureka-client-1、eureka-client-2,并且分别注册到两个Eureka Server。
编写启动类,添加@EnableDiscoveryClient注解,声明这是一个服务提供者,如下:
/**
* eureka 服务提供者
*/
@SpringBootApplication
@EnableDiscoveryClient
@RestController
public class EurekaClientApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientApplication.class, args);
}
@Value("${server.port}")
private int port;
@RequestMapping("hello")
public String hello(String name) {
return port + ":hello world, " + name;
}
}
然后分别启动eureka-client-1、eureka-client-2,再次访问:http://localhost:8081,如下:
可以看到Eureka Client服务已经注册到Eureka Server集群上了,访问:http://localhost:8084/hello,正常返回如下:
8084:hello world, null
四、创建ribbon-rest项目-服务消费者(rest方式负载均衡调用)
在springcloud下创建子模块:ribbon-rest,pom文件引入以下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</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-netflix-ribbon</artifactId>
</dependency>
新建配置文件:application.yml,添加eureka客户端相关配置,如下:
server:
port: 8088
spring:
application:
name: ribbon-rest
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8081/eureka/
接着编写启动类,配置RestTemplate Bean,添加@LoadBalanced注解,开启负载均衡调用,如下:
/**
* robbin + rest 方式调用服务
* robbin 实现负载均衡调用服务,默认轮询
*/
@SpringBootApplication
@EnableDiscoveryClient
@RestController
public class RobbinRestApplication {
public static void main(String[] args) {
SpringApplication.run(RobbinRestApplication.class, args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
@Autowired
private RestTemplate restTemplate;
@RequestMapping("hello")
public String hello(String name) {
return restTemplate.getForObject("http://EUREKA-CLIENT/hello?name=" + name, String.class);
}
}
然后启动ribbon-rest,访问:http://localhost:8081,如下:
可以看到ribbon-rest服务已经注册到Eureka Server集群上了,访问:http://localhost:8088/hello,会交替返回如下内容:
8084:hello world, null
8085:hello world, null
说明消费者以轮询的在方式访问不同的服务提供者实例。
五、创建feign-hystrix项目-服务消费者(声明式HTTP调用、服务降级处理)
在springcloud下创建子模块:feign-hystrix,pom文件引入以下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</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-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
新建配置文件:application.yml,添加eureka客户端相关配置以及hystrix熔断配置,如下:
server:
port: 8087
spring:
application:
name: feign-hystrix
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8081/eureka/
feign:
hystrix:
enabled: true
这里以feign方式调用服务,需要写一个接口:IHelloService,添加@FeignClient,表明这是一个feign客户端,同时通过注解的fallback属性指定服务降级的实现类:HelloServiceFallback,在这个类中进行服务的容错处理。
@FeignClient(value = "EUREKA-CLIENT", fallback = HelloServiceFallback.class)
public interface IHelloService {
@RequestMapping("/hello")
public String hello(@RequestParam(value = "name") String name);
}
@Component
public class HelloServiceFallback implements IHelloService {
@Override
public String hello(String name) {
// TODO Auto-generated method stub
return name + " sorry, something wrong";
}
}
接着编写启动类,添加@EnableFeignClients注解,开启声明式http调用。注入IHelloService,调用服务,如下:
/**
* feign 方式调用服务
* feign 声明式http客户端,集成robbin,实现负载均衡
* 整合hystrix,实现熔断,服务降级
* hystrix 当服务不可用达到阀值时,直接执行fallback方法返回,不用等到超时
*/
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@RestController
public class FeignHystrixApplication {
public static void main(String[] args) {
SpringApplication.run(FeignHystrixApplication.class, args);
}
@Autowired
private IHelloService iHelloService;
@RequestMapping("/hello")
public String hello(String name) {
return iHelloService.hello(name);
}
}
然后启动feign-hystrix,访问:http://localhost:8081,如下:
可以看到feign-hystrix服务已经注册到Eureka Server集群上了,访问:http://localhost:8087/hello,同样会交替返回如下内容:
8084:hello world, null
8085:hello world, null
然后停止eureka-client-1、eureka-client-2,再次访问:http://localhost:8087/hello,会返回如下内容:
null sorry, something wrong
说明由于服务提供者不可用,feign进行了服务降级处理。
六、创建zuul项目-网关(过滤请求、路由)
在springcloud下创建子模块:zuul,pom文件引入以下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</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-netflix-zuul</artifactId>
</dependency>
新建配置文件:application.yml,添加eureka客户端相关配置以及zuul路由配置,如下:
server:
port: 8089
spring:
application:
name: eureka-client-zuul
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8081/eureka/
zuul:
routes:
ribbon:
path: /ribbon/**
serviceId: RIBBON-REST
feign:
path: /feign/**
serviceId: FEIGN-HYSTRIX
根据routes配置,zuul会将请求路径匹配/ribbon/**的请求转发给RIBBON-REST服务的实例。
同时,编写过滤器:TokenFilter,实现统一的请求过滤:
@Component
public class TokenFilter extends ZuulFilter {
/**
* 过滤器具体实现
*/
@Override
public Object run() throws ZuulException {
// TODO Auto-generated method stub
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
Object accessToken = request.getParameter("token");
if (accessToken == null) {
ctx.setSendZuulResponse(false);
try {
ctx.getResponse().getWriter().write("sorry, you do not have a token");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
return null;
}
/**
* 返回是否需要过滤(执行run函数),true表示要,false表示不要
*/
@Override
public boolean shouldFilter() {
// TODO Auto-generated method stub
return true;
}
/**
* 返回过滤器执行的顺序,越小越先执行,0最高
*/
@Override
public int filterOrder() {
// TODO Auto-generated method stub
return 0;
}
/**
* 返回生命周期不同的过滤器类型
* pre:路由之前
* routing:路由之时
* post: 路由之后
* error:发送错误调用
*/
@Override
public String filterType() {
// TODO Auto-generated method stub
return "pre";
}
}
接着编写启动类,添加@EnableZuulProxy注解,开启服务网关,如下:
/**
* zuul 网关组件,实现路由转发、过滤功能
*/
@SpringBootApplication
@EnableDiscoveryClient
@EnableZuulProxy
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}
然后启动zuul,访问:http://localhost:8081,如下:
可以看到zuul服务已经注册到Eureka Server集群上了,访问:http://localhost:8089/feign/hello,因为过滤器会拦截没有token的请求,所以此时会返回如下内容:
sorry, you do not have a token
然后加上token,再次访问:http://localhost:8089/feign/hello?token=token,会返回如下内容:
null sorry, something wrong
这是因为前面停止eureka-client-1、eureka-client-2,feign进行了降级处理,说明zuul已经根据路由配置把请求转发给了FEIGN-HYSTRIX服务实例。
七、创建zipkin-server项目-服务调用链路追踪
在springcloud下创建子模块:zipkin-server,pom文件引入以下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-ui</artifactId>
<version>2.11.5</version>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-server</artifactId>
<version>2.11.5</version>
</dependency>
新建配置文件:application.yml,配置如下:
server:
port: 8094
spring:
application:
name: zipkin-server
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8081/eureka/
management:
metrics:
web:
server:
auto-time-requests: false
接着编写启动类,添加@EnableZipkinServer注解,开启Zipkin Server,如下:
/**
* 链路追踪
*/
@SpringBootApplication
@EnableDiscoveryClient
@EnableZipkinServer
public class ZipkinServerApplication {
public static void main( String[] args )
{
SpringApplication.run(ZipkinServerApplication.class, args);
}
}
然后启动zipkin-server,访问:http://localhost:8081,如下:
可以看到zipkin-server服务已经注册到Eureka Server集群上了,访问:http://localhost:8094/zipkin/,会出现如下界面:
然后修改eureka-client、ribbon-rest、feign-hystrix、zuul的pom文件,引入zipkin客户端依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
修改application.yml,添加zipkin配置如下:
spring:
zipkin:
base-url: http://zipkin-server/
sleuth:
sampler:
probability: 1
重新启动,访问:http://localhost:8089/feign/hello?token=token,接着再次访问:http://localhost:8094/zipkin/,就可以看到服务之间调用的信息了,如下:
八、创建config-server项目-配置中心
在springcloud下创建子模块:config-server,pom文件引入以下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
新建配置文件:application.yml,配置如下:
spring:
profiles:
active: native
application:
name: config-server
server:
port: 8090
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8081/eureka/
接着编写启动类,添加@EnableConfigServer注解,开启Config Server,如下:
/**
* 配置中心
*/
@SpringBootApplication
@EnableDiscoveryClient
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
然后启动config-server,访问:http://localhost:8081,如下:
可以看到config-server服务已经注册到Eureka Server集群上了。
然后修改eureka-client、ribbon-rest、feign-hystrix、zuul、zipkin-server的pom文件,引入config client客户端依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
以eureka-client为例,复制application.yml到config-server项目的resources下并重命名为eureka-client.yml,接着注释掉application.yml所有配置,如下:
#spring:
# zipkin:
# base-url: http://zipkin-server/
# sleuth:
# sampler:
# probability: 1
# application:
# name: eureka-client
#---
#spring:
# profiles: eureka-client-1
#server:
# port: 8084
#eureka:
# client:
# serviceUrl:
# defaultZone: http://localhost:8081/eureka/
#---
#spring:
# profiles: eureka-client-2
#server:
# port: 8085
#eureka:
# client:
# serviceUrl:
# defaultZone: http://localhost:8082/eureka/
然后eureka-client新建bootstrap.yml配置文件,添加Config Server配置(ConfigClient 服务启动后,默认会先访问bootstrap.yml,然后绑定ConfigServer,然后从ConfigServer获取application.yml 配置),如下:
spring:
cloud:
config:
name: eureka-client
label: master
discovery:
enabled: true
service-id: config-server
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8081/eureka/
ribbon-rest、feign-hystrix、zuul、zipkin-server等模块同理,在config-server的resources下新建配置文件,注释原来application.yml配置,新增bootstrap.yml配置,然后重新启动:
可以看到,eureka-client从config-server获取配置信息。访问:http://localhost:8089/feign/hello?token=token,可以正常返回:
8084:hello world, null
也可以把配置放到github上,然后,config-server从github获取,修改config-server的application.yml配置文件,如下:
spring:
# profiles:
# active: native
application:
name: config-server
cloud:
config:
server:
git:
uri: https://github.com/191720653/springcloud-config
search-paths: config
label: master
server:
port: 8090
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8081/eureka/
注释掉spring.profiles.active=native,让config-server从github上获取配置文件。
重新启动所有服务,查看日志:
可以看到,zipkin-server是从github上获取配置的。
九、完整代码
推荐阅读
-
搭建Spring Initializr服务器
-
Spring Cloud Alibaba | Sentinel: 服务限流高级篇
-
Spring Cloud第七篇 | 声明式服务调用Feign
-
spring cloud 初步搭建1-1(eureka配置)
-
微信小程序搭建自己的Https服务器
-
微信小程序访问node.js接口服务器搭建教程
-
[Spring cloud 一步步实现广告系统] 11. 使用Feign实现微服务调用
-
微服务架构下使用Spring Cloud Zuul作为网关将多个微服务整合到一个Swagger服务上
-
Spring Cloud Alibaba | Nacos服务中心初探
-
spring cloud 入门系列八:使用spring cloud sleuth整合zipkin进行服务链路追踪