欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring Cloud微服务搭建

程序员文章站 2022-04-30 18:22:41
...

目录

一、创建springcloud项目

二、创建eureka-server项目-高可用服务注册中心

三、创建eureka-client项目-服务提供者

四、创建ribbon-rest项目-服务消费者(rest方式负载均衡调用)

五、创建feign-hystrix项目-服务消费者(声明式HTTP调用、服务降级处理)

六、创建zuul项目-网关(过滤请求、路由)

七、创建zipkin-server项目-服务调用链路追踪

八、创建config-server项目-配置中心

九、完整代码


一、创建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,可以看到如下界面:

Spring Cloud微服务搭建

三、创建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,如下:

Spring Cloud微服务搭建

可以看到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,如下:

Spring Cloud微服务搭建

可以看到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,如下:

Spring Cloud微服务搭建

可以看到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,如下:

Spring Cloud微服务搭建

可以看到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,如下:

Spring Cloud微服务搭建

可以看到zipkin-server服务已经注册到Eureka Server集群上了,访问:http://localhost:8094/zipkin/,会出现如下界面:

Spring Cloud微服务搭建

然后修改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/,就可以看到服务之间调用的信息了,如下:

Spring Cloud微服务搭建

八、创建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,如下:

Spring Cloud微服务搭建

 

可以看到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配置,然后重新启动:

Spring Cloud微服务搭建

可以看到,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上获取配置文件。

重新启动所有服务,查看日志:

Spring Cloud微服务搭建

可以看到,zipkin-server是从github上获取配置的。

九、完整代码

https://github.com/191720653/springcloud