Dawell的博客

我不是一个简单的少年~


  • 首页

  • 分类

  • 归档

  • 标签

SpringCloud-番外篇-临时任务

发表于 2018-08-11 | 分类于 技术 | 阅读次数

SpringCloud文章系列

  1. SpringCloud
  2. SpringCloud-注册中心
  3. SpringCloud-配置中心
  4. SpringCloud-链路跟踪
  5. SpringCloud-消息总线
  6. SpringCloud-API网关
  7. SpringCloud-异步消息
  8. SpringCloud-同步调用
  9. SpringCloud-断路降级
  10. SpringCloud-监控管理
  11. 【当前文章】SpringCloud-番外篇-临时任务
  12. SpringCloud-番外篇-文档生成
  13. SpringCloud-番外篇-源码解析

接入说明

  1. 目前采用最新的1.xRelease版本:1.5.15.RELEASE
  2. SpringCloud项目可以在start.spring.io下载,不过更方便的应该是通过idea新建项目,建立Spring Initializr项目
  3. 我一般习惯将具体实现服务用具体的服务名,而公共组件用service-xxx来命名,当然还有一些比较固定名字的公共组件

Task

1. 新建项目

新建artifactId为service-task的服务

2. 导入依赖

依赖说明

  1. actuator用于暴露监控的接口
  2. eureka-server是Eureka服务器的依赖
  3. config是Config客户端,从配置中心拉取配置
  4. task用于短命服务的依赖
  5. jpa与mysql的依赖用于存储task相关的数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<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>
<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-task</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>

3. 编写启动类

打开ServiceTaskApplication,在class上加入@EnableTask注解

4. 修改配置

1
2
3
4
5
6
7
8
9
10
11
12
13
server.port=8060
spring.application.name=service-task

#private
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springcloud
spring.datasource.username=root
spring.datasource.password=xxx
spring.jpa.database=MySQL
spring.jpa.show-sql=true
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.ImprovedNamingStrategy

主要配置jpa与datasource链接到mysql数据库,如果使用内存存储则不需要任何数据库配置

5. 编写方法

在main类中编写CommandLineRunner相关接口task会全部执行完

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@EnableTask
@SpringBootApplication
public class ServiceTaskApplication {

public static void main(String[] args) {
SpringApplication.run(ServiceTaskApplication.class, args);
}

@Bean
public CommandLineRunner commandLineRunner() {
return strings -> System.out.println("Hello World!");
}

@Bean
public CommandLineRunner commandLineRunner2() {
return strings -> System.out.println("Hello 2!");
}

}

5. 启动main

6. 验证

main方法运行后会直接退出,同时控制台会打印”Hello World!”与”Hello 2!”

疑问

这个干嘛用的?
官方叫做短命任务,就是执行一次就结束的任务,用于一些临时处理的代码场景,每次执行都会记录在数据库中执行的结果,正常,异常信息

20180501架构设计

发表于 2018-08-11 | 阅读次数

准备介绍内容如下

  1. 领域驱动
  2. 前后端分离
  3. 微服务设计
  4. 缓存策略
  5. 限流策略

SpringCloud-监控管理

发表于 2018-08-10 | 分类于 技术 | 阅读次数

SpringCloud文章系列

  1. SpringCloud
  2. SpringCloud-注册中心
  3. SpringCloud-配置中心
  4. SpringCloud-链路跟踪
  5. SpringCloud-消息总线
  6. SpringCloud-API网关
  7. SpringCloud-异步消息
  8. SpringCloud-同步调用
  9. SpringCloud-断路降级
  10. 【当前文章】SpringCloud-监控管理
  11. SpringCloud-番外篇-临时任务
  12. SpringCloud-番外篇-文档生成
  13. SpringCloud-番外篇-源码解析

接入说明

  1. 目前采用最新的1.xRelease版本:1.5.15.RELEASE
  2. SpringCloud项目可以在start.spring.io下载,不过更方便的应该是通过idea新建项目,建立Spring Initializr项目
  3. 我一般习惯将具体实现服务用具体的服务名,而公共组件用service-xxx来命名,当然还有一些比较固定名字的公共组件

Admin监控

1. 新建项目

新建artifactId为service-admin的服务

2. 导入依赖

依赖说明

  1. actuator用于暴露监控的接口
  2. eureka-server是Eureka服务器的依赖
  3. config是Config客户端,从配置中心拉取配置
  4. admin-starter-server是admin监控平台的依赖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<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>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
</dependency>

3. 编写启动类

打开ServiceAdminApplication,在class上加入@EnableAdminServer注解

4. 修改配置

1
2
3
4
5
6
7
server.port=7088
spring.application.name=service-admin

# public
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka,http://localhost:8762/eureka
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.service-id=service-config

5. 启动main

6. 验证

访问 http://localhost:8761/ 看到service-admin已经注册了一台
访问 http://localhost:7088 可以看到admin的列表,首页就是与注册中心信息差不多,全部的应用,还有detail可以点进去看到各个endpoint数据

客户端使用

admin其实是基于SpringBoot诞生的,在注册中心引入之前本来也是有一个admin的client的,用于发现服务维持心跳的
但是基于SpringCloud的注册中心就不需要在客户端依赖了

扩展

集成Hystrix大盘

之前介绍过断路降级的hystrix大盘,其实可以集成在admin中更加方便统一
导入依赖

1
2
3
4
5
6
7
8
9
10
 <dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-server-ui-hystrix</artifactId>
<version>1.5.4</version>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-server-ui-turbine</artifactId>
<version>1.5.4</version>
</dependency>

配置文件中引入

1
2
spring.boot.admin.routes.endpoints=env,metrics,dump,jolokia,info,configprops,trace,logfile,refresh,flyway,liquibase,heapdump,loggers,auditevents,hystrix.stream,turbine.stream,activiti
spring.boot.admin.turbine.location=turbine-service

这样打开页面时在每个服务的detail中可以看到hystrix的信息,同时在大菜单上加入了Tuibine的视图

同时有个方便的方式是将turbine服务直接在admin中去集成,不用单独开turbine服务

集成登录验证

简单的方式引入spring-boot-starter-security即可用basic验证了
不过admin也有一个登录界面
引入如下

1
2
3
4
5
6
7
8
9
  <dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-server-ui-login</artifactId>
<version>1.5.4</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

然后建立登录认证的配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true, proxyTargetClass = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Override
public void configure(WebSecurity web) throws Exception {
//忽略css.jq.img等文件
web.ignoring()
.antMatchers("/**.html", "/**.css", "/img/**", "/**.js", "/third-party/**");
}

@Override
protected void configure(HttpSecurity http) throws Exception {

http
.csrf().disable() //HTTP with Disable CSRF
.authorizeRequests() //Authorize Request Configuration
.antMatchers("/login",
"/api/**",
"/**/heapdump",
"/**/loggers",
"/**/liquibase",
"/**/logfile",
"/**/flyway",
"/**/auditevents",
"/**/jolokia").permitAll() //放开"/api/**":为了给被监控端免登录注册并解决Log与Logger冲突
.and()
.authorizeRequests()
.antMatchers("/**").hasRole("USER")
.antMatchers("/**").authenticated()
.and() //Login Form configuration for all others
.formLogin()
.loginPage("/login.html")
.loginProcessingUrl("/login").permitAll()
.defaultSuccessUrl("/")
.and() //Logout Form configuration
.logout()
.deleteCookies("remove")
.logoutSuccessUrl("/login.html").permitAll()
.and()
.httpBasic();

}
}

配置文件中引入

1
2
3
4
# 权限
security.user.name=admin
security.user.password=123
security.basic.enabled=false

这样在访问监控时会先要求登录 使用admin与123访问

集成监控报警

可以在应用状态变更与endpoin异常时自动邮件报警
导入

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>

配置中需要开启通知与邮件的配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
spring.boot.admin.notify.mail.to=456@qq.com
spring.boot.admin.notify.mail.from=123@qq.com
#从任何状态到up状态都不要发邮件通知
#spring.boot.admin.notify.mail.ignore-changes: *:UP
# 邮件
spring.mail.host=smtp.qq.com
spring.mail.username=123@qq.com
spring.mail.password=xxxxx
spring.mail.properties.mail.debug=false
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.properties.mail.smtp.ssl.enable=true
spring.mail.port=465

上面配置是开启SSL的邮件配置

SpringCloud-断路降级

发表于 2018-08-09 | 分类于 技术 | 阅读次数

SpringCloud文章系列

  1. SpringCloud
  2. SpringCloud-注册中心
  3. SpringCloud-配置中心
  4. SpringCloud-链路跟踪
  5. SpringCloud-消息总线
  6. SpringCloud-API网关
  7. SpringCloud-异步消息
  8. SpringCloud-同步调用
  9. 【当前文章】SpringCloud-断路降级
  10. SpringCloud-监控管理
  11. SpringCloud-番外篇-临时任务
  12. SpringCloud-番外篇-文档生成
  13. SpringCloud-番外篇-源码解析

接入说明

  1. 目前采用最新的1.xRelease版本:1.5.15.RELEASE
  2. SpringCloud项目可以在start.spring.io下载,不过更方便的应该是通过idea新建项目,建立Spring Initializr项目
  3. 我一般习惯将具体实现服务用具体的服务名,而公共组件用service-xxx来命名,当然还有一些比较固定名字的公共组件

断路监控大盘

1. 新建项目

新建artifactId为hystrix-dashboard的服务

2. 导入依赖

依赖说明

  1. actuator用于暴露监控的接口
  2. eureka-server是Eureka服务器的依赖
  3. config是Config客户端,从配置中心拉取配置
  4. netflix-hystrix-dashboard是hystrix监控大盘的依赖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<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>
<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-hystrix-dashboard</artifactId>
</dependency>

3. 编写启动类

打开HystrixDashboardApplication,在class上加入@EnableHystrixDashboard注解

4. 修改配置

1
2
3
4
5
6
7
server.port=8030
spring.application.name=hystrix-dashboard

# public
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka,http://localhost:8762/eureka
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.service-id=service-config

5. 启动main

6. 验证

访问 http://localhost:8761/ 看到hystrix-dashboard已经注册了一台
访问 http://localhost:8030 可以看到hystrix监控的页面,上面需要配置一个xxx.stream的http地址,客户度集成后就有这个地址了

客户端使用

基于刚同步调用章节business-service服务调用account-service服务接口的例子

1. 添加依赖

1
2
3
4
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>

2. 开启注解

BusinessServiceApplication加入注解 @EnableCircuitBreaker 打开断路器功能

3. 修改代码

基于feign远程调用的降级非常简单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@RestController
class AccountController {

@Autowired
private AccountRead accountRead;

public String fallback() {
return "掛了";
}

@HystrixCommand(fallbackMethod = "fallback")
@RequestMapping("/account-msg")
public String read() {
return accountRead.read();
}

}

增加@HystrixCommand注解,注解种指定fallbackMethod对应同参数与返回值的方法即可

其他的方法也可以在方法上面标注@HystrixCommand(fallbackMethod = “xxx”)注解就实现降级了,比如用restTempldate请求的方法上加上

监控大盘集成

只需将客户的的http://localhost:8010/hystrix.stream填入hystrix-dashboard的url中点击下面按钮注册就可以看到监控数据
但是这样只能看到一台机器的,有时候我们想关注整个集群的情况,多个业务服务的链路情况,则需要使用数据聚合服务turbine-service

turbine服务

导入依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<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>
<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-turbine</artifactId>
</dependency>

添加bootstrap.properties

1
2
3
4
5
6
7
8
9
10
11
12
13
server.port=8001
spring.application.name=turbine-service

# private
turbine.app-config=api-gateway,business-service
turbine.aggregator.clusterConfig=default
turbine.cluster-name-expression="default"
turbine.combine-host-port=true

# public
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka,http://localhost:8762/eureka
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.service-id=service-config

turbine.app-config用于指定具体聚合哪些服务,这里聚合2个有调用请求的服务网关+business服务

在TurbineServiceApplication类上加入@EnableTurbine

将地址 http://localhost:8001/hystrix.stream 配置在hystrix-dashboard上就可以看到服务网关+business服务2个集群的调用情况了

疑问

如果触发了断路器一定是调用服务不可用么?

不是,因为断路器触发不止远程服务不可行,包括调用异常的情况,只要是异常都会触发断路,比如bug导致的

如果fallback代码报错了呢?

fallback报错了会抛出一个异常,而fallback一般都是简单的返回默认值固定值的逻辑,如果担心这里处理也有问题,可以在fallback上再加上@HystrixCommand降级
可以这样一直降级下去

其他注册中心

其他更多的是限流的方案与设置调用超时与trycatch的简单处理方案,相对不是太灵活,这里不展开了

SpringCloud-同步调用

发表于 2018-08-08 | 分类于 技术 | 阅读次数

SpringCloud文章系列

  1. SpringCloud
  2. SpringCloud-注册中心
  3. SpringCloud-配置中心
  4. SpringCloud-链路跟踪
  5. SpringCloud-消息总线
  6. SpringCloud-API网关
  7. SpringCloud-异步消息
  8. 【当前文章】SpringCloud-同步调用
  9. SpringCloud-断路降级
  10. SpringCloud-监控管理
  11. SpringCloud-番外篇-临时任务
  12. SpringCloud-番外篇-文档生成
  13. SpringCloud-番外篇-源码解析

接入说明

  1. 目前采用最新的1.xRelease版本:1.5.15.RELEASE
  2. SpringCloud项目可以在start.spring.io下载,不过更方便的应该是通过idea新建项目,建立Spring Initializr项目
  3. 我一般习惯将具体实现服务用具体的服务名,而公共组件用service-xxx来命名,当然还有一些比较固定名字的公共组件
  4. 基于配置中心,请先按照配置中心章节,配置公共配置
  5. 依赖链路追踪章节

同步调用

同步调用主要是通过HTTP去请求的,这里演示Feign的调用,重点在客户端的实现,服务端暴露接口就是普通的SpringMVC的使用

1. 新建项目

继续使用”异步调用”章节的artifactId为account-service的服务

2. 导入依赖

依赖说明

  1. 可以显示引入web的依赖
  2. actuator与eureka-server已经依赖web,其实SC中大部分组件已经强依赖web了,依赖这些组件可以不显示依赖(不过建议还是明确引入)
1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

3. 编写服务端暴露接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@RefreshScope
@RestController
class MessageController {

private final String msg;

@Autowired
public MessageController(@Value("${message}") String msg){
this.msg = msg;
}

@RequestMapping("/msg")
public String read() {
return msg;
}

}

这个接口还是使用配置中心章节使用的/msg接口暴露服务

4. 启动main

5. 验证

访问http://localhost:8020/msg 可以返回配置中心的msg配置数据

客户端使用

客户端使用项目business-service演示

1. 添加依赖

1
2
3
4
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>

2. 开启注解

BusinessServiceApplication上加入@EnableFeignClients开启Feign

3. 添加调用代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@FeignClient("account-service")
interface AccountRead {

@RequestMapping(method = RequestMethod.GET, value = "/msg")
String read();

}

@RestController
class AccountController {

@Autowired
private AccountRead accountRead;

@RequestMapping("/account-msg")
public String read() {
return accountRead.read();
}
}

之前在account-service中声明的/msg接口在这里使用同样的SpringMVC的注解标注AccountRead接口接口代表远程调用的客户端
然后调用时只需要@Autowired注入即可使用

其他同步调用方式

如restfulTemplate也可以远程调用,不过不如feign方便,需要拼请求参数的URL,当前例子因为不需要拼接参数,所以看起来差不多

快速接入

在main类或者config类中构建一个RestTemplate,标记@LoadBalanced,则会采用Ribbon提供的负载均衡算法

1
2
3
4
5
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}

1
2
3
4
5
6
7
8
9
10
11
12
@RestController
public class AccountController2 {

@Autowired
private RestTemplate restTemplate;

@RequestMapping("/account-msg")
public String read(){
return restTemplate.getForObject("http://account-service/msg", String.class);
}

}

疑问

如果返回的不是String,而是一个对象呢?

对象只需要在客户端这里声明一个类似的对象即可自动转换,其实中间数据都是用json传输的,类名可以不一样,只要属性一样即可匹配

请求调用的IP与端口号我想获取或者单独控制怎么实现?

Feign其实是依赖Ribbon去做负载均衡的,可以在配置中配置负载均衡策略
具体获取请求IP与端口控制可以直接使用Ribbon去请求可以获取到负载的IP与端口号,结合RestfulTempldate去请求服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@RestController
class AccountController {

@Autowired
private LoadBalancerClient client;
@Autowired
private RestTemplate restTemplate;

@RequestMapping("/account-msg2")
public String read2() {
ServiceInstance serviceInstance = client.choose("account-service");
String url = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/msg";
return restTemplate.getForObject(url, String.class);
}

}

SpringCloud-异步消息

发表于 2018-08-07 | 分类于 技术 | 阅读次数

SpringCloud文章系列

  1. SpringCloud
  2. SpringCloud-注册中心
  3. SpringCloud-配置中心
  4. SpringCloud-链路跟踪
  5. SpringCloud-消息总线
  6. SpringCloud-API网关
  7. 【当前文章】SpringCloud-异步消息
  8. SpringCloud-同步调用
  9. SpringCloud-断路降级
  10. SpringCloud-监控管理
  11. SpringCloud-番外篇-临时任务
  12. SpringCloud-番外篇-文档生成
  13. SpringCloud-番外篇-源码解析

接入说明

  1. 目前采用最新的1.xRelease版本:1.5.15.RELEASE
  2. SpringCloud项目可以在start.spring.io下载,不过更方便的应该是通过idea新建项目,建立Spring Initializr项目
  3. 我一般习惯将具体实现服务用具体的服务名,而公共组件用service-xxx来命名,当然还有一些比较固定名字的公共组件
  4. 基于配置中心,请先按照配置中心章节,配置公共配置
  5. 依赖链路追踪章节

Stream-Kafka

0. 搭建kafka

详见中间件kafka章节

1. 新建项目

新建artifactId为account-service的服务

2. 导入依赖

依赖说明

  1. actuator用于暴露监控的接口
  2. eureka是Eureka客户端,注册到注册中心
  3. config是Config客户端,从配置中心拉取配置
  4. sleuth + zipkin是链路追踪客户端,用于监控链路调用
  5. bus-kafka是基于kafka的bus消息总线客户端,用于接收消息总线异步事件
  6. stream + stream-binder-kafka + spring-kafka配置的是kafka的发送/消费端依赖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<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>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-kafka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-kafka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>

3. 编写启动类

打开AccountServiceApplication,在class上加入@EnableBinding(Source.class)注解

4. 修改配置

1
2
3
4
5
6
7
8
9
server.port=8020
spring.application.name=account-service

private
spring.cloud.stream.bindings.output.destination=accounts

#kafka
spring.cloud.stream.kafka.binder.zk-nodes=localhost:2181
spring.cloud.stream.kafka.binder.brokers=localhost:9092

stream.bindings.output.destination主要是配置kafka发送端的topic

5. 编写调用代码

1
2
3
4
5
6
7
8
9
10
11
12
13
@RestController
class MessageController {

@Autowired
private Source source;

@PostMapping(value = "/accounts")
public void write(@RequestBody Account account) {
source.output().send(MessageBuilder.withPayload(account.getMob()).build());
log.info("kafka send!");
}

}

暴露一个/accounts接口,提交POST方法请求,传递包含mob字段的json数据,会将mob字段作为kafka消息体发送
其中Source直接注入即可,Source是Stream自带的接口类,默认Source中的配置关联到”output”中,刚才配置了output的destination也就是topic是accounts

6. 启动main

7. 验证

可以打开一个控制台,通过kafka-console-consumer.sh/bat去监听accounts的topic的kafka
通过暴露/accounts接口post提交信息,通过kafka-console-consumer.sh/bat控台可以看到消息结构
stream会自动封装一个content-type类型,用于标识数据类型

客户端使用

1. 添加依赖

1
2
3
4
5
6
7
8
9
10
11
12
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-kafka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>

stream + stream-binder-kafka + spring-kafka配置的是kafka的发送/消费端依赖
这个配置与发送端是一样的

2. 开启注解

BusinessServiceApplication添加@EnableBinding(Sink.class)

Sink用于接收kafka,当然如果是多个kafkaTopic这里可以设置多个,接口都是继承了Sink接口,也可以在一个接口中声明多个SubscribableChannel与注解如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public interface CustomSink {

String INPUT = "input3";

@Input(INPUT)
SubscribableChannel input();

String INPUT0 = "input0";

String INPUT1 = "input1";

String INPUT2 = "input2";

@Input(INPUT0)
SubscribableChannel input0();

@Input(INPUT1)
SubscribableChannel input1();

@Input(INPUT2)
SubscribableChannel input2();

}

3. 修改配置

1
2
spring.cloud.stream.bindings.input.destination=accounts
#spring.kafka.listener.poll-timeout=

这里是接收端,所以是input
headerMode用于配置是stream的格式还是原始数据
content-type用于配置数据解析类型

注意:如果通过kafka的kafka-console-producer.bat模拟发送kafka的时候,消费端会报如下错误
could not convert messages from Kafka异常
原因就是因为发送的内容不是stream发送出来的,stream有其固定的格式,至少要有content-type属性
如果想不用stream格式发送也能解析需要在消费方增加如下配置,进行raw源数据的解析

1
2
spring.cloud.stream.bindings.input.consumer.headerMode=raw
spring.cloud.stream.bindings.input.content-type=text/plain

4. 接收消息代码

1
2
3
4
5
6
7
8
@Component
class AccountConsumer {

@StreamListener(Sink.INPUT)
public void write(String name) {
log.info(name);
}
}

@StreamListener注解用于标识处理消息的方法

疑问

Stream是怎么保存链路追踪的数据的?

如果不引入sleuth + zipkin依赖,保存的消息格式只是带有content-type字段,而如果引入了这2个依赖就会在Stream消息格式里加入额外4个字段

  1. traceId
  2. spanId

消息体会变大,不过带来的好处是消息消费的时候依然可以记录链路信息,这样在链路图上就可以看到所有消息者消费的情况了

支持kafka的消息组及消息分区

在生产端需要增加分区规则与个数的配置

1
2
spring.cloud.stream.bindings.output.producer.partitionKeyExpression=payload
spring.cloud.stream.bindings.output.producer.partitionCount=2

partitionKeyExpression可以使用SpEL去解析具体传输数据体中的某个key值去作为分区key
partitionCount指定分区的总个数

在消费端也需要开启分区配置

1
2
3
spring.cloud.stream.bindings.input.comsumer.partitioned=true
spring.cloud.stream.instanceCount=2
spring.cloud.stream.instanceIndex=0

指定总分区个数与当然消费的分区

而消费端如果要指定消费组只需要指定消费组的名称即可开启

1
spring.cloud.stream.bindings.input.group=comsumer1

不加消费组每个订阅者都收到同样的消息,offset独立维护
消费组能保证所有组内消费同一topic中的消息只有一个组内的服务消费,串性消费,offset维护在公共区域,Stream默认存储在zookeeper中

在kafka中的zookeeper中存储个位置:/consumers/组名/offsets/主题/分区移动的位置

其他注册中心

其他还有RabbitMQ的实现

快速接入

略…

SpringCloud-API网关

发表于 2018-08-06 | 分类于 技术 | 阅读次数

SpringCloud文章系列

  1. SpringCloud
  2. SpringCloud-注册中心
  3. SpringCloud-配置中心
  4. SpringCloud-链路跟踪
  5. SpringCloud-消息总线
  6. 【当前文章】SpringCloud-API网关
  7. SpringCloud-异步消息
  8. SpringCloud-同步调用
  9. SpringCloud-断路降级
  10. SpringCloud-监控管理
  11. SpringCloud-番外篇-临时任务
  12. SpringCloud-番外篇-文档生成
  13. SpringCloud-番外篇-源码解析

接入说明

  1. 目前采用最新的1.xRelease版本:1.5.15.RELEASE
  2. SpringCloud项目可以在start.spring.io下载,不过更方便的应该是通过idea新建项目,建立Spring Initializr项目
  3. 我一般习惯将具体实现服务用具体的服务名,而公共组件用service-xxx来命名,当然还有一些比较固定名字的公共组件
  4. 基于配置中心,请先按照配置中心章节,配置公共配置
  5. 依赖链路追踪章节

API网关

1. 新建项目

新建artifactId为api-gateway的服务

2. 导入依赖

依赖说明

  1. actuator用于暴露监控的接口
  2. eureka是Eureka客户端,注册到注册中心
  3. config是Config客户端,从配置中心拉取配置
  4. sleuth + zipkin是链路追踪客户端,用于监控链路调用
  5. bus-kafka是基于kafka的bus消息总线客户端,用于接收消息总线异步事件
  6. zuul是zuul网关的依赖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<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>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-kafka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>

3. 编写启动类

打开ApiGatewayApplication,在class上加入@EnableZuulProxy注解

4. 修改配置

1
2
3
4
5
6
7
server.port=9998
spring.application.name=api-gateway

#private
feign.httpclient.connection-timeout=3000

#public 注册中心+配置中心+链路追踪+BUSkafka

feign.httpclient.connection-timeout:API网关依赖Fegion客户端,而API调用时可能超时,一般远程调用的时间需要调整下

5. 启动main

6. 验证

访问 http://localhost:8761/ 看到api-gateway已经注册了一台
访问 http://localhost:9998/应用名/接口名 即可验证,被代理的接口是否调用成功

API网关集群

只要配置2个端口区分开即可,如9998,9999

客户端使用

启动代理后就可以通过代理访问请求了,所以无客户端

疑问

其他API网关

目前还有SpringCLoud亲儿子,基于SpringBoot2的SpringCloud API Gateway

快速接入

略…

SpringCloud-消息总线

发表于 2018-08-05 | 分类于 技术 | 阅读次数

SpringCloud文章系列

  1. SpringCloud
  2. SpringCloud-注册中心
  3. SpringCloud-配置中心
  4. SpringCloud-链路跟踪
  5. 【当前文章】SpringCloud-消息总线
  6. SpringCloud-API网关
  7. SpringCloud-异步消息
  8. SpringCloud-同步调用
  9. SpringCloud-断路降级
  10. SpringCloud-监控管理
  11. SpringCloud-番外篇-临时任务
  12. SpringCloud-番外篇-文档生成
  13. SpringCloud-番外篇-源码解析

接入说明

  1. 目前采用最新的1.xRelease版本:1.5.15.RELEASE
  2. SpringCloud项目可以在start.spring.io下载,不过更方便的应该是通过idea新建项目,建立Spring Initializr项目
  3. 我一般习惯将具体实现服务用具体的服务名,而公共组件用service-xxx来命名,当然还有一些比较固定名字的公共组件
  4. 基于配置中心,请先按照配置中心章节,配置公共配置
  5. 依赖链路追踪章节

Bus

1. 新建项目

新建artifactId为service-bus的服务

2. 导入依赖

依赖说明

  1. actuator用于暴露监控的接口
  2. eureka是Eureka客户端,注册到注册中心
  3. config是Config客户端,从配置中心拉取配置
  4. sleuth + zipkin是链路追踪客户端,用于监控链路调用
  5. bus-kafka是基于kafka的bus消息总线客户端,用于接收消息总线异步事件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<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>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-kafka</artifactId>
</dependency>

3. 编写启动类

不需要添加任何注解,bus依赖进来后扩展了SpringBoot的endpoint

4. 修改配置

1
2
3
4
5
6
7
8
9
server.port=8901
spring.application.name=service-bus

## private
spring.cloud.bus.trace.enabled=true

#public
spring.cloud.stream.kafka.binder.zk-nodes=localhost:2181
spring.cloud.stream.kafka.binder.brokers=localhost:9092

bus.trace.enabled可以开启bus操作的链路跟踪,每次客户端处理都是异步接收消息去处理的,所以可以观察到每个客户端接收消息时间与ack的情况
由于bus依赖于异步消息Stream,这里采用kafka,所以需要配置下kafka的zk与brokers的地址(这里可以看下之前kafka搭建的文章)

5. 启动main

6. 验证

访问 http://localhost:8761/ 看到service-bus已经注册了一台
使用curl或者Postman用POST方式访问 http://localhost:8901/bus/refresh 可以通过/trace看到每台机器ack的情况
如果开启了链路追踪,也可以通过链路追踪看到每次bus请求的情况

客户端使用

1. 添加依赖

1
2
3
4
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-kafka</artifactId>
</dependency>

2. 开启注解

无注解,引入依赖既开启

3. 修改配置

1
2
3
#kafka
spring.cloud.stream.kafka.binder.zk-nodes=localhost:2181
spring.cloud.stream.kafka.binder.brokers=localhost:9092

依赖kafka,与服务端统一kafka

扩展

  1. 通过bus调用的命令不加参数是全局的,可以通过增加destination参数,如/bus/refresh?destination=business-service:**,只会请求business-service的所有服务
  2. 如果访问出现401,则配置需要加上management.security.enabled=false
  3. 很多BUS功能单一,一般主要与配置中心配合,所以往往BUS的功能可以直接集成在配置中心中,方便管理

其他消息总线

除了kafka的支持,还可以通过rabbitMQ

快速接入

略…

SpringCloud-链路跟踪

发表于 2018-08-04 | 分类于 技术 | 阅读次数

SpringCloud文章系列

  1. SpringCloud
  2. SpringCloud-注册中心
  3. SpringCloud-配置中心
  4. 【当前文章】SpringCloud-链路跟踪
  5. SpringCloud-消息总线
  6. SpringCloud-API网关
  7. SpringCloud-异步消息
  8. SpringCloud-同步调用
  9. SpringCloud-断路降级
  10. SpringCloud-监控管理
  11. SpringCloud-番外篇-临时任务
  12. SpringCloud-番外篇-文档生成
  13. SpringCloud-番外篇-源码解析

接入说明

  1. 目前采用最新的1.xRelease版本:1.5.15.RELEASE
  2. SpringCloud项目可以在start.spring.io下载,不过更方便的应该是通过idea新建项目,建立Spring Initializr项目
  3. 我一般习惯将具体实现服务用具体的服务名,而公共组件用service-xxx来命名,当然还有一些比较固定名字的公共组件
  4. 基于配置中心,请先按照配置中心章节,配置公共配置

Zipkin

1. 新建项目

新建artifactId为zipkin-service的服务

2. 导入依赖

依赖说明

  1. actuator用于暴露监控的接口
  2. eureka是Eureka客户端,注册到注册中心
  3. config是Config客户端,从配置中心拉取配置
  4. zipkin-server + zipkin-autoconfigure-ui是链路追踪客户端,用于监控链路调用
    1. 注意这个依赖属于zipkin的ui,并不是springcloud包下,需要单独引用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<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>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-server</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-ui</artifactId>
<scope>runtime</scope>
</dependency>

3. 编写启动类

打开ZipkinServiceApplication,在class上加入@EnableZipkinServer注解

4. 修改配置

1
2
3
4
5
6
7
8
server.port=9411
spring.application.name=zipkin-service

# public
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka,http://localhost:8762/eureka
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.service-id=service-config
zipkin.storage.type=mem

zipkin.storage.type默认也是用mem,默认数据存储在内存中,可以用mysql之类的存储去存储收集的信息

5. 启动main

6. 验证

访问 http://localhost:8761/ 看到zipkin-service已经注册了一台
访问 http://localhost:9411/zipkin 看到服务端的UI界面,上面有查找调用链、依赖分析等功能

客户端使用

1. 添加依赖

1
2
3
4
5
6
7
8
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>

2. 开启注解

无须添加注解

3. 修改配置

1
2
3
4
5
spring.sleuth.scheduled.enabled=false
spring.sleuth.async.enabled=false
spring.sleuth.annotation.enabled=false
spring.sleuth.sampler.percentage=1
spring.zipkin.sender.type=web

scheduled.enabled与async.enabled关闭定时与异步推送数据,开启实时同步,可以更实时的看到数据
sampler.percentage采集率,用于控制多少比例的数据进行采集,默认是0.1,请求10次采集1次,这里设置为1,每一次调用都会采集
zipkin.sender.type设置为web才会直接请求到zipkin-server,否则如果依赖binders会默认是放在kafka中的,所以明确使用web方式调用

扩展

除了通过web同步请求链路信息,还可以采用kafka异步采集信息

zipkin.collector可以采用kafka收集信息,而客户端也可以配置为kafka发送信息

配置略…

zipkin的数据可以采用mysql数据存储

配置略…

trace中的流转

一个是多出了trace信息,同时注意最后一个状态位
日志中[demo-trace1,63c082f6715c8979,63c082f6715c8979,true],true代表上传成功;

如果开启了kafka的日志,则kafka消息中会多出4个trace相关的key,详见异步消息章节

SpringCloud-配置中心

发表于 2018-08-03 | 分类于 技术 | 阅读次数

SpringCloud文章系列

  1. SpringCloud
  2. SpringCloud-注册中心
  3. 【当前文章】SpringCloud-配置中心
  4. SpringCloud-链路跟踪
  5. SpringCloud-消息总线
  6. SpringCloud-API网关
  7. SpringCloud-异步消息
  8. SpringCloud-同步调用
  9. SpringCloud-断路降级
  10. SpringCloud-监控管理
  11. SpringCloud-番外篇-临时任务
  12. SpringCloud-番外篇-文档生成
  13. SpringCloud-番外篇-源码解析

接入说明

  1. 目前采用最新的1.xRelease版本:1.5.15.RELEASE
  2. SpringCloud项目可以在start.spring.io下载,不过更方便的应该是通过idea新建项目,建立Spring Initializr项目
  3. 我一般习惯将具体实现服务用具体的服务名,而公共组件用service-xxx来命名,当然还有一些比较固定名字的公共组件

Config

1. 新建项目

新建artifactId为service-config的服务

2. 导入依赖

依赖说明

  1. actuator用于暴露监控的接口
  2. config-server是Config服务器的依赖
  3. eureka是Eureka客户端,这里配置中心依赖于注册中心
1
2
3
4
5
6
7
8
9
10
11
12
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

3. 编写启动类

打开ServiceConfigApplication,在class上加入@EnableConfigServer注解
并且加上@EnableEurekaClient,注册到注册中心

4. 修改配置

建立git仓库

可以是本地仓库,也可以是远程仓库,我们用本地仓库来模拟

  1. 找到一个目录E:/config
  2. git init 初始化仓库
  3. 新建文件application.properties
  4. git add .
  5. git commit -m ‘init’
  6. git push origin master
1
2
3
4
5
6
7
8
9
server.port=8888
spring.application.name=service-config
spring.cloud.config.server.git.uri=E:/config

# public
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.service-id=service-config
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka,http://localhost:8762/eureka
management.security.enabled=false

配置中心默认端口8888

config.server.git.uri设置为git的本地地址

  1. 注意spring.cloud.config.server.git.uri必须配置在应用本地,否则不知道远程配置的地址,而其他服务的配置都可以放到配置中心,这个是特别的

discovery.enabled与discovery.service-id其实是客户端的配置,配置中心自己是服务端也是客户端,作为客户端与其他服务一样,都需要通过配置中心去发现配置服务启动,读取公共配置

  1. discovery.enabled设置为通过注册中心暴露服务
  2. discovery.service-id是配置中心对在注册中心外暴露的id一致,与server端配置的spring.application.name一致

defaultZone注册中心地址
management.security.enabled用于关闭一些校验权限

抽出公共配置–其他微服务共享

application.properties文件添加以下配置,并去掉service-config配置中的配置

1
2
3
4
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka,http://localhost:8762/eureka
management.security.enabled=false
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.service-id=service-config

5. 启动main

6. 验证

访问 http://localhost:8761/ 看到service-config已经注册了一台
访问 http://localhost:8888/service-config/default 就可以访问到配置中心加载的配置了,中间改其他服务名,default是指配置的profile

Config集群

1. 修改配置文件

配置2个server,server1使用端口8888,server2使用端口8889

server1

1
2
3
4
5
6
7
8
9
server.port=8888
spring.application.name=service-config
spring.cloud.config.server.git.uri=E:/IdeaProjects/springcloud-test/config

# public
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.service-id=service-config
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka,http://localhost:8762/eureka
management.security.enabled=false

server2

1
2
3
4
5
6
7
8
9
server.port=8889
spring.application.name=service-config
spring.cloud.config.server.git.uri=E:/IdeaProjects/springcloud-test/config

# public
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.service-id=service-config
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka,http://localhost:8762/eureka
management.security.enabled=false

除了端口号不一样,其他都一样,本质上配置中心只要保证读取的git地址一样就可以了,客户端只是过来拉配置,git相当于数据库

2. 启动

启动server1
启动server2

3. 验证

访问 http://localhost:8761/ 看到service-config已经注册了2台
访问 http://localhost:8888/service-config/default 就可以访问到配置中心加载的配置了
访问 http://localhost:8889/service-config/default 就可以访问到配置中心加载的配置了

客户端使用

1. 添加依赖

客户端要通过注册中心查找注册中心服务,所以需要依赖注册中心

1
2
3
4
5
6
7
8
<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-config</artifactId>
</dependency>

2. 开启注解

开启注册中心的配置即可@EnableDiscoveryClient,配置中心不需要额外的注解

3. 修改配置

1
2
3
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka,http://localhost:8762/eureka
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.service-id=service-config

config.discovery.enabled与config.discovery.service-id是依赖配置中心启动的核心配置,指定配置中心暴露的名称

4. 编写代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@RefreshScope
@RestController
class MessageController {

private final String msg;

@Autowired
public MessageController(@Value("${message}") String msg){
this.msg=msg;
}

@RequestMapping("/msg")
public String read() {
return msg;
}

}

@RefreshScope 注意这里如果想通过/refresh接口能实时刷新配置的话,需要加这个注解,没有加的只是启动时加载的数据不会更新
注意这里进来保持好的使用习惯,使用final来保存数据

疑问

1. 为什么一定通过注册中心暴露配置中心服务?

如果不通过注册中心,客户端的配置如下:

1
spring.cloud.config.uri=http://localhost:8888

如果修改修改了域名或者端口,增加减少机器都需要去修改此启动配置,则通过注册中心就可以用其各种好处,减少依赖

2. 配置中心为什么依赖注册中心?怎么我看有的是注册中心依赖配置中心?

其实目前2种配置都有

  1. 注册中心依赖配置中心的解释:就是注册中心也是一个服务,启动所需要的配置从配置中心拉取,同时可以动态变更,启动顺序:先配置中心,再注册中心,配置中心不能依赖注册中心,否则无法启动。
  2. 配置中心依赖注册中心的解释:配置中心如果注册为集群模式那必然让客户端通过服务发现找到从注册中心找到配置中心,所以配置中心一定要注册到注册中心启动服务发现。启动顺序:注册中心,再配置中心,这样注册中心的配置是不经过配置中心的,而注册中心的配置一般也是固定不变的
    针对第一种还有一种解:先启动配置中心,开启注册失败仍然可以启动的配置,只是第一次注册失败依然可以启动,然后再启动注册中心,可以两全
    总体来说第二种更加合理一点,因为一般注册中心的defaultZone与其他应用不一样,注册中心的要排除掉自己的地址,而其他服务是全量,这样我在做公共配置时比较统一,不用开启注册中心的本地配置优先
    不过其他解决方案中注册中心与配置中心一般都是一体的,所以也就没有这种相互依赖的尴尬,不过领域上确实是2个东西

3. 为什么配置中心读取的配置变量声明为final的,但是调用/refresh后带@RefreshScope的对象里的final值还会发生变化?

首先final是不会变的,所以spring是把整个@RefreshScope标注的bean重新创建了一遍
final的好处是

  1. 控制只有配置中心才可以更改变量,在程序中是无法赋值替换的
  2. 配置中心的数据都是很少去变化的,应该当做常量处理,final虚拟机有优化
  3. 可以保证线程安全,无状态类与不可变类多线程安全

其他注册中心

因为consul与zookeeper本身具备配置存储的能力,所以这2个注册中心的配置中心一般用他们定制的,而非用SpringCloudConfig

快速接入

暂略…

1234…6
Dawell

Dawell

一个Java程序员日常学习、技术总结博客

60 日志
8 分类
34 标签
RSS
GitHub
Creative Commons
© 2019 Dawell
Best Wishes! 联系我