Spring Boot Admin 是一个针对spring-boot的actuator接口进行UI美化封装的监控工具。他可以:在列表中浏览所有被监控spring-boot项目的基本信息,详细的Health信息、内存信息、JVM信息、垃圾回收信息、各种配置信息(比如数据源、缓存列表和命中率)等。
pom 文件 如下:
springcloud-monitor-admin
springcloud-monitor
1.0-SNAPSHOT
4.0.0
springcloud-monitor-admin
springcloud-admin-server
de.codecentric
spring-boot-admin-starter-server
2.0.3
de.codecentric
spring-boot-admin-server-ui
2.0.3
org.springframework.boot
spring-boot-starter-security
#将服务注册到注册中心
eureka:
client:
serviceUrl:
defaultZone: http://localhost:9000/eureka/
#healthcheck:
#enabled: true #开启自定义健康检查
instance:
#eureka服务器在接收到最后一个心跳之后等待的时间,然后才能从列表中删除此实例 默认90s(开发环境)
lease-expiration-duration-in-seconds: 10
#eureka客户端需要向eureka服务器发送心跳的频率 默认30s (开发环境)
lease-renewal-interval-in-seconds: 1
metadata-map:
user.name: ${spring.security.user.name}
user.password: ${spring.security.user.password}
#配置服务名称及端口
server:
port: 9015
spring:
application:
name: springcloud-admin-server
# 登录管理
security:
user:
name: 'admin'
password: 'admin'
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: ALWAYS
@EnableAdminServer// 开启监控
@EnableDiscoveryClient
@SpringBootApplication
public class AdminServerApplication {
public static void main(String[] args) {
SpringApplication.run(AdminServerApplication.class, args);
}
}
可能你需要有权限,登录才能查看监控
如果不需要可以注释掉这个类,并去掉spring-boot-starter-security 依赖jar包
@Configuration
public class SecuritySecureConfig extends WebSecurityConfigurerAdapter {
private final String adminContextPath;
public SecuritySecureConfig(AdminServerProperties adminServerProperties) {
this.adminContextPath = adminServerProperties.getContextPath();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
successHandler.setTargetUrlParameter("redirectTo");
http.authorizeRequests()
.antMatchers(adminContextPath + "/assets/**").permitAll()
.antMatchers(adminContextPath + "/login").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().loginPage(adminContextPath + "/login").successHandler(successHandler).and()
.logout().logoutUrl(adminContextPath + "/logout").and()
.httpBasic().and()
.csrf().disable();
}
}
访问地址 http://localhost:9015
账号:admin 密码:admin
登录成功,显示如下:
监控服务端会监控注册中心的所有服务实例
启动 服务提供者 springcloud-provider-1项目
手写Api文档的几个痛点:
1.文档需要更新的时候,需要再次发送一份给前端,也就是文档更新交流不及时。
2.接口返回结果不明确
3.不能直接在线测试接口,通常需要使用工具,比如postman
4.接口文档太多,不好管理
Swagger也就是为了解决这个问题,当然也不能说Swagger就一定是完美的,
当然也有缺点,最明显的就是代码移入性比较强。
pom 文件如下:
springcloud-doc-swagger2
springcloud-doc
1.0-SNAPSHOT
4.0.0
springcloud-doc-swagger2
springcloud-swagger2-test
2.9.2
io.springfox
springfox-swagger2
${swagger2-version}
io.springfox
springfox-swagger-ui
${swagger2-version}
#将服务注册到注册中心
eureka:
client:
serviceUrl:
defaultZone: http://localhost:9000/eureka/
#healthcheck:
#enabled: true #开启自定义健康检查
instance:
#eureka服务器在接收到最后一个心跳之后等待的时间,然后才能从列表中删除此实例 默认90s(开发环境)
lease-expiration-duration-in-seconds: 10
#eureka客户端需要向eureka服务器发送心跳的频率 默认30s (开发环境)
lease-renewal-interval-in-seconds: 1
# Swagger2
status-page-url: http://${spring.cloud.client.ip-address}:${server.port}/swagger-ui.html
#配置服务名称及端口
server:
port: 9017
spring:
application:
name: springcloud-swagger2-test
kd:
app:
name: springcloud-swagger2-test提供者-1
@SpringBootApplication
@EnableDiscoveryClient
public class Swagger2Run {
public static void main(String[] args) {
SpringApplication.run(Swagger2Run.class, args);
}
}
@Configuration
@EnableSwagger2 // 启用Swagger2
public class Swagger2 {
@Bean
public Docket createRestApi() {// 创建API基本信息
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("org.kd.controller"))// 扫描该包下的所有需要在Swagger中展示的API,@ApiIgnore注解标注的除外
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {// 创建API的基本信息,这些信息会在Swagger UI中进行显示
return new ApiInfoBuilder()
.title("springcloud-swagger2-test中使用Swagger2构建RESTful APIs")// API 标题
.description("kd hello ")// API描述
.contact("隐无为")// 联系人
.version("1.0")// 版本号
.build();
}
}
@RestController
@Api(value = "测试接口", description = "描述", tags = {"测试接口标签"})
public class TestController {
@Value("${server.port}")
String port;
@Value("${spring.application.name}")
String name;
@Value("${kd.app.name}")
String appName;
@RequestMapping("/test")
@ApiOperation("doc接口测试方法")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "用户id", required = true, paramType = "query"),
@ApiImplicitParam(name = "age", value = "用户age", required = true, paramType = "query")
})
public Object test(Integer id, Integer age) {
HashMap map = new HashMap<>();
map.put("id", id);
map.put("msg", "ok");
return map;
}
}
http://localhost:9017/swagger-ui.html
注意 application.yml 这个属性代表的意思是你在点击注册中心的服务应用实例跳转链接的时候就可以查看有哪些接口 类似dubbo点击服务应用实例查看里面有哪些提供的接口
# Swagger2
status-page-url: http://${spring.cloud.client.ip-address}:${server.port}/swagger-ui.html
只需要修改swagger-ui替换成swagger-ui-layer
还有 status-page-url: http:// s p r i n g . c l o u d . c l i e n t . i p − a d d r e s s : {spring.cloud.client.ip-address}: spring.cloud.client.ip−address:{server.port}/api-docs.html
因为swagger-ui-layer默认的地址是/api-docs.html
pom 文件如下:
springcloud-doc-swagger2
springcloud-doc
1.0-SNAPSHOT
4.0.0
springcloud-swagger2-test
springcloud-swagger2-layui
2.9.2
io.springfox
springfox-swagger2
${swagger2-version}
com.github.ohcomeyes
swagger-ui-layer
1.2
修改 配置 application.yml
# Swagger2
status-page-url: http://${spring.cloud.client.ip-address}:${server.port}/api-docs.html
随着微服务数量不断增长,它们之间的关系会越来越复杂, 如果链路上任何一个服务出现问题或者网络超时,都会形成导致接口调用失败, 需要跟踪一个请求从一个微服务到下一个微服务的传播过程
pom 文件如下:
springcloud-sleuth-zipkin
SpringCloud-demo
1.0-SNAPSHOT
4.0.0
springcloud-sleuth-zipkin
springcloud-zipkin-server
pom
springcloud-zipkin-test
springcloud-zipkin-mysql
springcloud-zipkin-elk
2.9.4
org.springframework.boot
spring-boot-starter-web
io.zipkin.java
zipkin-server
${zipkin-version}
io.zipkin.java
zipkin-autoconfigure-ui
${zipkin-version}
#配置服务名称及端口
spring:
application:
name: springcloud-zipkin-server
server:
port: 9009
#将服务注册到注册中心
eureka:
client:
serviceUrl:
defaultZone: http://localhost:9000/eureka/
#healthcheck:
#enabled: true #开启自定义健康检查
instance:
#eureka服务器在接收到最后一个心跳之后等待的时间,然后才能从列表中删除此实例 默认90s(开发环境)
lease-expiration-duration-in-seconds: 10
#eureka客户端需要向eureka服务器发送心跳的频率 默认30s (开发环境)
lease-renewal-interval-in-seconds: 1
# ip地址
#ip-address: 固定ip地址
instance-id: ${spring.cloud.client.ip-address}:${server.port}
preferIpAddress: true
#spring:
# cloud:
# inetutils:
# ignoredInterfaces:
# - docker
# - VM.*
# - Vir.*
---
#zipkin
spring:
sleuth:
enabled: false
sampler:
#采样率,推荐0.1, 测试 百分百
percentage: 1
@SpringBootApplication
@EnableZipkinServer
@EnableDiscoveryClient
public class ZipkinServerApplication {
public static void main(String[] args) {
SpringApplication.run(ZipkinServerApplication.class, args);
}
}
向服务提供者项目和消费者项目添加以下属性
spring:
zipkin:
base-url: http://localhost:9009
具体可以看springcloud-sleuth-zipkin项目代码
管理地址:http://localhost:9009/zipkin/
Spring Cloud Stream本质上就是整合了Spring Boot和Spring Integration,
实现了一套轻量级的消息驱动的微服务框架。通过使用Spring Cloud Stream,
可以有效地简化开发人员对消息中间件的使用复杂度,
让系统开发人员可以有更多的精力关注于核心业务逻辑的处理。
kafka安装教程
springcloud-kafka-consumer
pom 文件如下:
SpringCloud-demo
SpringCloud-demo
1.0-SNAPSHOT
4.0.0
SpringCloud-demo
springcloud-stream-kafka
pom
springcloud-kafka-provider
springcloud-kafka-consumer
org.springframework.cloud
spring-cloud-starter-stream-kafka
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.boot
spring-boot-starter-web
public interface InputChannel {
// test 通道协议字段
String INPUT = "kd";
@Input(InputChannel.INPUT)
public SubscribableChannel input();
}
@EnableBinding(value = {InputChannel.class})
public class MyReceiver {
@StreamListener(InputChannel.INPUT)
public void messageListen(String message) {
System.out.println("收到信息:" + message);
}
}
@SpringBootApplication
@EnableDiscoveryClient
public class KafkaConsumerRun {
public static void main(String[] args) {
SpringApplication.run(KafkaConsumerRun.class, args);
}
}
启动消费者,监听生产者发送过来的消息
springcloud-kafka-provider
pom 文件如下:
SpringCloud-demo
SpringCloud-demo
1.0-SNAPSHOT
4.0.0
SpringCloud-demo
springcloud-stream-kafka
pom
springcloud-kafka-provider
springcloud-kafka-consumer
org.springframework.cloud
spring-cloud-starter-stream-kafka
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.boot
spring-boot-starter-web
#将服务注册到注册中心
eureka:
client:
serviceUrl:
defaultZone: http://localhost:9000/eureka/
#healthcheck:
#enabled: true #开启自定义健康检查
instance:
#eureka服务器在接收到最后一个心跳之后等待的时间,然后才能从列表中删除此实例 默认90s(开发环境)
lease-expiration-duration-in-seconds: 10
#eureka客户端需要向eureka服务器发送心跳的频率 默认30s (开发环境)
lease-renewal-interval-in-seconds: 1
#配置服务名称及端口
server:
port: 9014
spring:
application:
name: springcloud-provider
---
spring:
cloud:
stream:
kafka:
binder:
brokers: 127.0.0.1:9092
zkNodes: 127.0.0.1:2181
bindings:
# 通道协议字段
kd:
# 生产者和消费者要一样
destination: topic-test
# 传输格式
#content-type: application/json
public interface OutChannel {
String OUTPUT = "kd";
@Output(OutChannel.OUTPUT)
MessageChannel output();
}
@EnableBinding(OutChannel.class)
public class KafkaSend {
@Autowired
private OutChannel outChannel;
/*
* 发送消息
* */
public void sendMessage(String msg) {
try {
outChannel.output().send(MessageBuilder.withPayload(msg).build());
} catch (Exception e) {
e.printStackTrace();
}
}
}
@RestController
public class SendController {
@Autowired
KafkaSend kafkaSend;
@RequestMapping("/")
public String test (){
kafkaSend.sendMessage("===================我是一条消息的小尾巴=========================");
return "发送测试";
}
}
@SpringBootApplication
@EnableDiscoveryClient
public class KafkaProviderRun {
public static void main(String[] args) {
SpringApplication.run(KafkaProviderRun.class, args);
}
}
http://localhost:9014/
消费者监听到消息
随着程序功能的日益复杂,程序的配置日益增多:各种功能的开关、参数的配置、服务器的地址……
对程序配置的期望值也越来越高:配置修改后实时生效,灰度发布,分环境、分集群管理配置,完善的权限、审核机制……
在这样的大环境下,传统的通过配置文件、数据库等方式已经越来越无法满足开发人员对配置管理的需求。
Apollo配置中心应运而生!
Apollo(阿波罗)是携程框架部门研发的开源配置管理中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性。
Apollo支持4个维度管理Key-Value格式的配置:
application (应用)
environment (环境)
cluster (集群)
namespace (命名空间)
请参考官网安装方式:https://github.com/ctripcorp/apollo/wiki/Quick-Start
我觉得已经官网安装已经很详细了
pom 文件如下:
springcloud-config-apollo
SpringCloud-demo
1.0-SNAPSHOT
4.0.0
SpringCloud-demo
springcloud-apollo-demo
org.springframework.boot
spring-boot-starter-web
com.ctrip.framework.apollo
apollo-client
1.0.0
org.springframework.boot
spring-boot-devtools
true
server:
port: 8093
name: a #测试用的
创建 resources/META-INF文件下app.properties
app.id=test
apollo.meta=http://localhost:8080
当然官网也介绍application.properties配置也是可以的
对于Spring Boot环境建议通过以下方式来接入Apollo(需要0.10.0及以上版本)。
使用方式很简单,只需要在application.properties/bootstrap.properties中按照如下样例配置即可
@SpringBootApplication
@EnableApolloConfig
public class ApolloApplication {
public static void main(String[] args) {
SpringApplication.run(ApolloApplication.class, args);
}
}
@RestController
public class ApolloTest {
@Value("${name}")
String name;
@Value("${age:25}")
int age;
@Value("${timeout:200}")
private int timeout;
@RequestMapping("/")
public String test(){
return "name:"+name+"->timeout:"+timeout+"->age:"+age;
}
}
Git Bash 启动 /demo.sh start
Quick Start脚本会在本地启动3个服务,分别使用8070, 8080, 8090端口,
请确保这3个端口当前没有被使用。
也不要忘记修改编辑demo.sh,修改ApolloPortalDB和ApolloConfigDB
相关的数据库连接串信息。
15
浏览器地址:http://localhost:8070
注意关闭服务命令是:./demo.sh stop
访问地址:http://localhost:8093/
springcloud-apollo-demo项目不重启, apollo服务端改变name为kd666再发布看看效果
可以看到,值已经变,不重启项目的情况下,
动态改变参数值就是我们想要的看到的
第十六章-定时任务调度-xxl-job
XXL-JOB是一个轻量级分布式任务调度平台,其核心设计目标是开发迅速、 学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线,开箱即用。
大众点评目前已接入XXL-JOB,内部别名《Ferrari》(Ferrari基于XXL-JOB的V1.1版本定制而成,新接入应用推荐升级最新版本)。 据最新统计, 自2016-01-21接入至2017-12-01期间,该系统已调度约100万次,表现优异。新接入应用推荐使用最新版本,因为经过数十个版本的更新,系统的任务模型、UI交互模型以及底层调度通讯模型都有了较大的优化和提升,核心功能更加稳定高效。
查看官网安装方式 http://www.xuxueli.com/xxl-job/
1、“调度中心”向“执行器”发送http调度请求: “执行器”中接收请求的服务,实际上是一台内嵌jetty服务器,默认端口9999;
2、“执行器”执行任务逻辑;
3、“执行器”http回调“调度中心”调度结果: “调度中心”中接收回调的服务,是针对执行器开放一套API服务;
pom 文件如下:
springcloud-job-task
SpringCloud-demo
1.0-SNAPSHOT
4.0.0
springcloud-job-task
springcloud-xxl-job
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
com.xuxueli
xxl-job-core
1.9.2
server.port=9020
#logging.config=classpath:logback.xml
xxl.job.admin.addresses=http://127.0.0.1:9300/xxl-job-admin
xxl.job.executor.appname=springcloud-xxl-job
xxl.job.executor.ip=127.0.0.1
xxl.job.executor.port=9999
xxl.job.accessToken=
xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
xxl.job.executor.logretentiondays=-1
package org.kd.config;
import com.xxl.job.core.executor.XxlJobExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = "org.kd.job")
public class XxlJobConfig {
private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);
@Value("${xxl.job.admin.addresses}")
private String adminAddresses;
@Value("${xxl.job.executor.appname}")
private String appName;
@Value("${xxl.job.executor.ip}")
private String ip;
@Value("${xxl.job.executor.port}")
private int port;
@Value("${xxl.job.accessToken}")
private String accessToken;
@Value("${xxl.job.executor.logpath}")
private String logPath;
@Value("${xxl.job.executor.logretentiondays}")
private int logRetentionDays;
@Bean(initMethod = "start", destroyMethod = "destroy")
public XxlJobExecutor xxlJobExecutor() {
logger.info(">>>>>>>>>>> xxl-job config init.");
XxlJobExecutor xxlJobExecutor = new XxlJobExecutor();
xxlJobExecutor.setAdminAddresses(adminAddresses);
xxlJobExecutor.setAppName(appName);
xxlJobExecutor.setIp(ip);
xxlJobExecutor.setPort(port);
xxlJobExecutor.setAccessToken(accessToken);
xxlJobExecutor.setLogPath(logPath);
xxlJobExecutor.setLogRetentionDays(logRetentionDays);
return xxlJobExecutor;
}
}
@JobHandler(value="demoJobHandler")
@Component
public class DemoJobHandler extends IJobHandler {
@Override
public ReturnT execute(String param) throws Exception {
XxlJobLogger.log("XXL-JOB, Hello World.");
System.out.println(new Date() + "测试");
for (int i = 0; i < 5; i++) {
XxlJobLogger.log("beat at:" + i);
TimeUnit.SECONDS.sleep(2);
}
return SUCCESS;
}
}
流程
@SpringBootApplication
public class JobApplication {
public static void main(String[] args) {
SpringApplication.run(JobApplication.class, args);
}
}
改为 springcloud-xxl-job
执行器实际上是一个内嵌的Jetty服务器,默认端口9999(配置项:xxl.job.executor.port)。
在项目启动时,执行器会通过“@JobHandler”识别Spring容器中“Bean模式任务”,以注解的value属性为key管理起来。
“执行器”接收到“调度中心”的调度请求时,如果任务类型为“Bean模式”,将会匹配Spring容器中的“Bean模式任务”,然后调用其execute方法,执行任务逻辑。如果任务类型为“GLUE模式”,将会加载GLue代码,实例化Java对象,注入依赖的Spring服务(注意:Glue代码中注入的Spring服务,必须存在与该“执行器”项目的Spring容器中),然后调用execute方法,执行任务逻辑。
请点击任务右侧 “执行” 按钮,可手动触发一次任务执行(不会影响调度队列的触发)
注意:任务不是立即执行的,任务会进入调度队列
(也就是说不能指定时间执行,不过作者说可以用他的xxl-mq完成指定时间消费)