? 今天倒腾一下Springcloud,整体感觉会Springboot,上手Springcloud也相对容易,下面简单梳理了Springcloud的几个组件;
整个项目结构
一、服务注册与发现
1.创建单节点注册中心
1.1 创建eureka-server模块并导入坐标
<dependencies>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.7</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.11.4</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
<version>3.0.3</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
1.2 创建application.properties配置文件
spring.application.name=spring-cloud-eureka
eureka.instance.hostname=localhost
server.port=11111
# 不向注册中心注册自己
eureka.client.register-with-eureka=false
# 检测服务
eureka.client.fetch-registry=false
# 注册中心
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
1.3 创建启动类
@SpringBootApplication
@EnableEurekaServer //开启服务注册中心
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
1.4 创建eureka-client-userservice模块服并导入坐标
<dependencies>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.7</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.11.4</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.2.4.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>3.0.3</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR8</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>
1.5 创建配置文件
spring.application.name=user-service
eureka.instance.hostname=localhost
server.port=9999
service.port=11111
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${service.port}/eureka/
1.6 创建启动类
@SpringBootApplication
@EnableEurekaClient //开启服务注册
public class UserApplication {
public static void main(String[] args) {
SpringApplication.run(UserApplication.class, args);
}
}
1.7 创建测试接口
@RestController
public class UserController {
@GetMapping("/getUser")
public String getUser(){
return "new User";
}
}
1.8 测试
?2.创建高可用注册中心
拷贝一份eureka-server(也可直接修改配置文件)
?2.1 修改配置文件,使eureka-server、eureka-server2互为注册,配置如下:
spring.application.name=spring-cloud-eureka
eureka.instance.hostname=localhost
server.port=11111
service.port=22222
# 注册中心
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${service.port}/eureka/
spring.application.name=spring-cloud-eureka
eureka.instance.hostname=localhost
server.port=22222
service.port=11111
# 注册中心
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${service.port}/eureka/
2.2 同时修改user-serice模块的配置文件,如下所示:
spring.application.name=user-service
eureka.instance.hostname=localhost
server.port=9999
service.port=11111
service2.port=22222
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${service.port}/eureka/,http://${eureka.instance.hostname}:${service2.port}/eureka/
2.3 测试结果如下:
?
2.4?再起一个服务提供方user-service,改个端口即可
spring.application.name=user-service
eureka.instance.hostname=localhost
server.port=9998
service.port=11111
service2.port=22222
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${service.port}/eureka/,http://${eureka.instance.hostname}:${service2.port}/eureka/
二、ribbon?负载均衡
3.1 创建服务消费模块order-service,pom.xml配置如下:
<dependencies>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.7</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.11.4</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.2.4.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
<version>1.3.1.RELEASE</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR8</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>
3.2 创建配置文件
spring.application.name=order-service
eureka.instance.hostname=localhost
server.port=9989
service.port=11111
service2.port=22222
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${service.port}/eureka/,http://${eureka.instance.hostname}:${service2.port}/eureka/
3.3 创建启动类,开启负载均衡
@EnableEurekaClient
@SpringBootApplication
public class OrderApplication {
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class,args);
}
}
3.4 编写测试接口
@RestController
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/user")
public String getUser(){
ResponseEntity<String> entity = restTemplate.getForEntity("http://user-service/getUser", String.class);
return entity.getBody();
}
}
3.5 测试
这里简单的使用要了轮询的方式
三、断路器?
这里断开一个user-service,再访问http://localhost:9989/user 会出现以下情形;
?
这里可引入断路器
1 pom.xml添加如下坐标
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.3.1.RELEASE</version>
</dependency>
2.主启动类加如下注解
@EnableCircuitBreaker//开启断路器注解
这里也可用@SpringCloudApplication这一个注解代替三个注解,原因如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public @interface SpringCloudApplication {
}
3 对代码做简单改造处理
3.1 OrderController接口更改如下:
@RestController
public class OrderController {
@Autowired
private OrderService orderServiceImpl;
@GetMapping("/user")
public String getUser(){
return orderServiceImpl.user();
}
}
3.2 添加 OrderService 接口
public interface OrderService {
public String user();
}
3.3 OrderService实现类更改如下
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private RestTemplate restTemplate;
@HystrixCommand(fallbackMethod="getBackError")
public String user() {
ResponseEntity<String> entity = restTemplate.getForEntity("http://USER-SERVICE/getUser", String.class);
return entity.getBody();
}
public String getBackError(){
return "error";
}
}
3.4 测试结果如下:
?
?四.Feign
1?Feign远程访问
1.1新建一个模块feign-order-service,pom.xml配置如下:
<dependencies>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.7</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.11.4</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.2.4.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.2.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.2.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
<version>2.2.9.RELEASE</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR8</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>
1.2 创建配置文件
spring.application.name=order-service2
eureka.instance.hostname=localhost
server.port=9979
service.port=11111
service2.port=22222
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${service.port}/eureka/,http://${eureka.instance.hostname}:${service2.port}/eureka/
1.3 创建启动类,并开启Feign功能
@EnableEurekaClient
@SpringBootApplication
@EnableFeignClients
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class,args);
}
}
1.4 创建OrderController 接口
@RestController
public class OrderController {
@Autowired
private OrderService orderService;
@GetMapping("/user")
public String getUser(){
return orderService.getUser();
}
}
1.5 引入user-service服务
@FeignClient(value="user-service")
public interface OrderService {
@GetMapping("getUser")
public String getUser();
}
#全局关闭熔断功能
feign.hystrix.enabled=false
2.服务降级
2.1?这里要配置feign.hystrix.enabled=true
spring.application.name=order-service2
eureka.instance.hostname=localhost
server.port=9979
service.port=11111
service2.port=22222
feign.hystrix.enabled=true
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${service.port}/eureka/,http://${eureka.instance.hostname}:${service2.port}/eureka/
2.2 修改OrderService接口
@FeignClient(value="user-service",fallback = FallBack.class)
public interface OrderService {
@GetMapping("getUser")
public String getUser();
}
2.3?FallBack 类代码如下:
@Component
public class FallBack implements OrderService {
public String getUser() {
return "Error";
}
}
五、Zuul 路由与过滤
1 路由功能
1.1 创建模块zuul-service,导入坐标
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
<version>2.2.9.RELEASE</version>
</dependency>
1.2 开启zuul功能 @EnableZuulProxy
@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class,args);
}
}
1.3 创建配置文件,如下所示:
spring.application.name=zuul-service
eureka.instance.hostname=localhost
server.port=9969
service.port=11111
service2.port=22222
zuul.routes.zuulname.path=/user/**
zuul.routes.zuulname.service-id=USER-SERVICE
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${service.port}/eureka/,http://${eureka.instance.hostname}:${service2.port}/eureka/
注意:为了避免jar的不匹配问题,这里在<dependencyManagement>中引入了如下配置;
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.4.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
1.4 测试结果如下:
?这里也可注释掉配置文件中的路由配置
spring.application.name=zuul-service
eureka.instance.hostname=localhost
server.port=9969
service.port=11111
service2.port=22222
#zuul.routes.zuulname.path=/user/**
#zuul.routes.zuulname.service-id=USER-SERVICE
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${service.port}/eureka/,http://${eureka.instance.hostname}:${service2.port}/eureka/
直接通过serverId访问,原因是zuul默认按serverId维护了一个映射;
?对于单独配置几个server的情况,可以使用zuul.ignored-services忽略掉所有,然后再单独配置;
2.过滤器
2.1 创建过滤器类
@Component
public class ZuulFilterImpl extends ZuulFilter {
private Logger logger = LoggerFactory.getLogger(ZuulFilterImpl.class);
/**
* 过滤器类型
* @return
*/
@Override
public String filterType() {
return PRE_TYPE;
}
/**
* 过滤器执行的顺序
* @return
*/
@Override
public int filterOrder() {
return 0;
}
/**
* 过滤器是否需要执行
* @return
*/
@Override
public boolean shouldFilter() {
return true;
}
/**
* 过滤器执行的具体逻辑
* @return
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
logger.info("into run");
return null;
}
}
2.2 测试结果如下:
?六、配置中心
准备工作:
1 配置中心服务端
1.1 创建config-service模块,导入坐标
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
1.2 创建启动类,开启配置服务
@SpringBootApplication
@EnableConfigServer
public class ConfigApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigApplication.class,args);
}
}
1.3 配置文件如下:
spring.application.name=config-service
server.port=8888
spring.cloud.config.server.git.uri=
spring.cloud.config.label=master
spring.cloud.config.server.git.search-paths=main
spring.cloud.config.server.git.username=
spring.cloud.config.server.git.password=
1.4 测试
?2?配置客户端
2.1 创建配置客户端模块config-client,坐标如下:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR8</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.4.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
2.2 创建配置文件bootstrap.properties
#spring.config.name=application
spring.cloud.config.label=master
spring.cloud.config.profile=pro
spring.cloud.config.uri=http://localhost:8888/
2.3 创建application.properties配置文件
spring.application.name=config-client
server.port=55555
2.4.创建测试接口
@RefreshScope
@RestController
public class ClientController {
@Autowired
private Environment environment;
@Value("${server-port}")
private String port;
@GetMapping("/port")
public String getProperties(){
String property = environment.getProperty("server-port");
return property;
}
}
2.5 创建启动类
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class,args);
}
}
2.6 测试结果如下:
|