com.microserver.myBlog
myBlog
1.0-SNAPSHOT
pom
UTF-8
1.8
1.8
4.12
1.2.17
1.16.18
org.springframework.cloud
spring-cloud-dependencies
Finchley.SR4
pom
import
org.springframework.boot
spring-boot-dependencies
2.2.2.RELEASE
pom
import
mysql
mysql-connector-java
5.0.4
com.alibaba
druid
1.0.31
org.mybatis.spring.boot
mybatis-spring-boot-starter
1.3.0
ch.qos.logback
logback-core
1.2.3
junit
junit
${junit.version}
test
log4j
log4j
${log4j.version}
@Accessors(chain = true)
com.microserver.myBlog
microservicecloud-api
${project.version}
yml文件
server:
port: 8001
mybatis:
config-location: classpath:mybatis/mybatis2.cfg.xml #mybatis 配置路径
type-aliases-package: com.microserver.myBlog.entity #所有entity别名类所在包
mapper-locations:
- classpath:mybatis/mapper/**/*.xml #mapper映射文件
spring:
application:
name: microservicecloud-blog
datasource:
type: com.alibaba.druid.pool.DruidDataSource #当前数据源操作类型
driver-class-name: org.gjt.mm.mysql.Driver #mysql驱动包
url: jdbc:mysql://localhost:3306/blog #url
username: root
password: root
dpcp2:
min-idle: 5 #数据库最小连接数
initial-size: 5 #初始化连接数
max-total: 5 #最大连接数
max-wait-millis: 200 #等待连接获取最大超时时间
mybatis配置文件
mysql创建数据库表
blog接口
mapper.xml
service、controller层编写
主类
测试运行
pom
com.microservice.springcloud.ConsumerMain
microservice-consumer
博客消费者
com.microservice.springcloud
microservice-api
${project.version}
org.springframework.boot
spring-boot-starter-web
org.springframework
springloaded
org.springframework.boot
spring-boot-devtools
runtime
org.springframework.boot
spring-boot-maven-plugin
${start-class}
ZIP
repackage
yml
server:
port: 80
添加组件
编写消费者模块的接口
pom
blog
com.microservice.springcloud
1.0-SNAPSHOT
4.0.0
microservice-eureka
org.springframework.cloud
spring-cloud-starter-eureka-server
org.springframework
springloaded
org.springframework.boot
spring-boot-devtools
runtime
yml配置
server:
port: 7001
eureka:
instance:
hostname: localhost #eureka服务调的实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己
fetch-registry: false #false 表示我就是注册中心,职责是维护服务实例,不需要检索服务
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #设置与eureka server交互的地址 查询服务和注册服务依赖这个地址
server:
#是否开启自我保护模式,默认为true。
enable-self-preservation: true
#续期时间,即扫描失效服务的间隔时间(缺省为60*1000ms)
eviction-interval-timer-in-ms: 10000
spring:
devtools:
livereload:
port: 35731
remote:
restart:
enabled: false
add-properties: true
主启动类
@SpringBootApplication
@EnableEurekaServer //eureka服务注释
public class EurekaMain {
public static final Logger logger = LoggerFactory.getLogger(EurekaMain.class);
public static void main(String[] args) {
SpringApplication.run(EurekaMain.class, args);
logger.info("*************************EurekaMain:启动成功******************************");
}
}
修改provider模块
pom新增
org.springframework.cloud
spring-cloud-starter-eureka
org.springframework.cloud
spring-cloud-starter-config
application.yml新增
#服务注册的eureka地址
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka
主启动类添加注解
@EnableEurekaClient
主机映射名称修改
eureka:
instance:
instance-id: microservice-provider #映射名称
主机ip信息提示
eureka:
instance:
instance-id: microservice-provider #映射名称
prefer-ip-address: true #访问路径可以显示ip地址
provider pom添加
org.springframework.boot
spring-boot-starter-actuator
父工程添加build信息
${project.name}
src/main/resources
true
org.apache.maven.plugins
maven-resources-plugin
$
修改provider工程yml
info:
app.name: blog-microsoftcloud
company.name: www.microsoftcloud.com
build.artifactId: $project.artifactId$
build.version: $project.version$
springcoud的自我保护机制(eureka模块)
eureka:
server:
#是否开启自我保护模式,默认为true。
enable-self-preservation: true
eureka服务发现
对于注册进eureka中的服务,可以通过服务发现获取服务信息
添加获取服务信息接口
@Autowired
private DiscoveryClient discoveryClient;
@RequestMapping(value = "/discovery", method = RequestMethod.GET)
@ResponseBody
public Object discovery(){
List list = discoveryClient.getServices();
System.out.println("******" + list);
List srvList = discoveryClient.getInstances("MICROSERVICECLOUD-BLOG");
for (ServiceInstance element : srvList) {
System.out.println(element.getServiceId() + "\t" + element.getHost() + "\t" + element.getPort() + "\t" + element.getUri());
}
return this.discoveryClient;
}
provicer主启动类添加注释
@EnableDiscoveryClient//服务发现
消费端调用发现接口
//消费端调用服务发现
@RequestMapping(value = "/blog/discovery")
public Object discovery(){
return restTemplate.getForObject(RES_URL_PREFIX + "/blog/discovery", Object.class);
}
127.0.0.1 eureka7001.com
127.0.0.1 eureka7002.com
127.0.0.1 eureka7003.com
server:
port: 7001
eureka:
instance:
hostname: eureka7001.com #eureka服务调的实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己
fetch-registry: false #false 表示我就是注册中心,职责是维护服务实例,不需要检索服务
service-url:
defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
#defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #设置与eureka server交互的地址 查询服务和注册服务依赖这个地址
server:
#是否开启自我保护模式,默认为true。
enable-self-preservation: true
#续期时间,即扫描失效服务的间隔时间(缺省为60*1000ms)
#eviction-interval-timer-in-ms: 10000
spring:
devtools:
livereload:
port: 35731
remote:
restart:
enabled: false
add-properties: true
server:
port: 7002
eureka:
instance:
hostname: eureka7002.com #eureka服务调的实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己
fetch-registry: false #false 表示我就是注册中心,职责是维护服务实例,不需要检索服务
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7003.com:7003/eureka/
#defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #设置与eureka server交互的地址 查询服务和注册服务依赖这个地址
server:
#是否开启自我保护模式,默认为true。
enable-self-preservation: true
#续期时间,即扫描失效服务的间隔时间(缺省为60*1000ms)
#eviction-interval-timer-in-ms: 10000
spring:
devtools:
livereload:
port: 35732
remote:
restart:
enabled: false
add-properties: true
server:
port: 7003
eureka:
instance:
hostname: eureka7003.com #eureka服务调的实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己
fetch-registry: false #false 表示我就是注册中心,职责是维护服务实例,不需要检索服务
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
#defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #设置与eureka server交互的地址 查询服务和注册服务依赖这个地址
server:
#是否开启自我保护模式,默认为true。
enable-self-preservation: true
#续期时间,即扫描失效服务的间隔时间(缺省为60*1000ms)
#eviction-interval-timer-in-ms: 10000
spring:
devtools:
livereload:
port: 35733
remote:
restart:
enabled: false
add-properties: true
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
#defaultZone: http://localhost:7001/eureka
//例如
@EnableEurekaServer
含义 麦当劳排队买汉堡,新来的排在人少的一队
ribbon配置
1)consumer模块 pom文件新增
org.springframework.cloud
spring-cloud-starter-eureka
org.springframework.cloud
spring-cloud-starter-config
org.springframework.cloud
spring-cloud-starter-ribbon
2)consumer模块 yml文件新增
eureka: #ribbon相关eureka配置
client:
register-with-eureka: false
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
3)consumer模块 restTemplate模型配置类ConfigBean添加注解
@Configuration
public class ConfigBean {
@Bean
//spring cloud Ribbon是基于Netfix Ribbon实现的一套客户端 负载均衡工具
@LoadBalanced //添加负在均衡注解
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
4)consumer模块 主启动类添加注解
@EnableEurekaClient
5)consumer模块 controller层
//修改:
public static final String RES_URL_PREFIX = "http://localhost:8001";
//修改为:
public static final String RES_URL_PREFIX = "http://MICROSERVICECLOUD-BLOG";
测试地址:http://localhost/consumer/blog/list
Ribbon和Eureka整合可以直接调用服务而不用关心地址和端口
2)添加模块microservice-provider02和microservice- provider03
DROP DATABASE IF EXISTS clouddb03;
CREATE DATABASE clouddb03 CHARACTER SET UTF8;
USE clouddb03;
CREATE TABLE blog (
id INT PRIMARY KEY AUTO_INCREMENT COMMENT 'ID',
title VARCHAR(200) NOT NULL,
content TEXT ,
views INT DEFAULT 0,
blog_type VARCHAR(50),
update_time DATETIME,
create_time DATETIME,
db_source VARCHAR(5`clouddb02`0)
);
INSERT INTO blog(title, content, views, blog_type, update_time, create_time, db_source)
VALUES('my first blog','my first blog',0,'JavaScript',NOW(),NOW(), DATABASE())
拷贝模块microservice-provider对应配置文件mybatis文件夹和yml文件(端口/数据库名/livereload/instance-id(映射名))
测试地址
http://localhost:8001/blog/getBlogs
http://localhost:8002/blog/getBlogs
http://localhost:8003/blog/getBlogs
http://localhost/consumer/blog/list #不断刷新该地址 查看访问服务变化
根据特定算法从服务列表中选取一个要访问的服务
consumer模块 restTemplate模型配置类ConfigBean添加新访问顺序方法
@Bean
public IRule myRule(){
// return new RoundRobinRule();//默认轮询算法
// return new RandomRule();//用随机算法替换默认轮询算法
return new RetryRule();//用重试算法替换默认轮询算法,默认轮询算法,若多次重试失败回自动跳过失败服务
}
//在启动该微服务的时候就能加载我们自定义的Ribbon配置类
@RibbonClient(name = "MICROSERVICECLOUD-BLOG", configuration = MySelfRule.class)
1.新建包
2.配置类
@Configuration
public class MySelfRule {
@Bean
public IRule myRule(){
return new RandomRule();//编写自己的自定义算法
}
}
org.springframework.cloud
spring-cloud-starter-feign
@FeignClient(value = "MICROSERVICECLOUD-BLOG")
@EnableFeignClients(basePackages = {"com.microservice.springcloud"})
复杂分布式系统结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免的失败
访问失败后,向调用方返回一个符合预期的、可处理的备选响应,而不是长时间等待或抛出调用方法无法处理的异常
借鉴provider模块创建Hystrix模块microservice-hystrix,拷贝provider代码,yml,配置文件
pom文件添加
org.springframework.cloud
spring-cloud-starter-hystrix
yml修改属性
instance-id: microservice-hystrix #映射名称
修改controller
@RequestMapping(value = "/getBlogById/{id}", method = RequestMethod.GET)
@HystrixCommand(fallbackMethod = "processHystrix_Get")
public Blog getBlogById(@PathVariable("id") String id) {
Blog blog = blogService.getBlogById(id);
if(null == blog){
throw new RuntimeException("该ID:" + id + "没有对应信息");
}
return blog;
}
public Blog processHystrix_Get(@PathVariable("id") String id) {
return new Blog().setId(id).setTitle("该ID:" + id + "没有对应信息,null--@HystrixCommand")
.setDbSource("no this database in MySQL");
}
@EnableCircuitBreaker//hystrix熔断机制
即整体资源不够用了,忍痛将某些服务关掉,度过难关,再开启。
@FeignClient(value = "MICROSERVICECLOUD-BLOG")
//修改为
@FeignClient(value = "MICROSERVICECLOUD-BLOG", fallbackFactory = BlogClientServiceFallbackFactory.class)
feign:
hystrix:
enabled: true
org.springframework.cloud
spring-cloud-starter-hystrix
org.springframework.cloud
spring-cloud-starter-hystrix-dashboard
yml文件
server:
port: 9001
@EnableHystrixDashboard
确认各provider服务存在依赖
org.springframework.boot
spring-boot-starter-actuator
Zuul包含路由和过滤功能,zuul注册进Eureka
org.springframework.cloud
spring-cloud-starter-zuul
org.springframework.cloud
spring-cloud-starter-eureka
yml文件
server:
port: 9527
eureka:
instance:
instance-id: myzuul.com #映射名称
prefer-ip-address: true #访问路径可以显示ip地址
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
#defaultZone: http://localhost:7001/eureka
info:
app.name: blog-microsoftcloud
company.name: www.microsoftcloud.com
build.artifactId: $project.artifactId$
build.version: $project.version$
spring:
application:
name: microservice-zuul-gateway
@EnableZuulProxy
修改hosts文件,添加
127.0.0.1 myzuul.com
yml文件,添加
zuul:
routes:
myBlog.serviceId: microservicecloud-blog
myBlog.path: /myBlog/**
修改yml文件
zuul:
routes:
myBlog.serviceId: microservicecloud-blog
myBlog.path: /myBlog/**
#ignored-services: “*” #忽略多个服务
zuul:
routes:
myBlog.serviceId: microservicecloud-blog
myBlog.path: /myBlog/**
ignored-services: "*" #忽略多个微服务
#ignored-services: microservicecloud-blog #新增 忽略单个服务
prefix: /dev #服务前加前缀
spring:
profiles:
active:
- dev
---
spring:
profiles: dev #开发环境
application:
name: microservice-cofig-myblog-dev
---
spring:
profiles: test #测试环境
application:
name: microservice-cofig-myblog-test
#请保存为UTF-8格式
org.springframework.cloud
spring-cloud-config-server
yml文件
server:
port: 3344
spring:
application:
name: microservice-config-server
cloud:
config:
server:
git:
uri: [email protected]:/home/gitrepo/microservice-config.git #git远程仓库名称
@EnableConfigServer
修改hosts文件
127.0.0.1 config-3344.com
测试地址:
http://config-3344.com:3344/application-dev.ym
http://config-3344.com:3344/application-test.yml
http://config-3344.com:3344/application-abcd.yml
在git文件夹下创建yml文件microservicecloud-config-client
spring:
profiles:
active:
- dev
---
server:
port: 8201
spring:
profiles: dev #开发环境
application:
name: microservice-cofig-client-myblog-dev
eureka:
client:
service-url:
defaultZone: http://eureka-dev.com:7001/eureka/
---
server:
port: 8202
spring:
profiles: test #测试环境
application:
name: microservice-cofig-client-myblog-test
eureka:
client:
service-url:
defaultZone: http://eureka-test.com:7001/eureka/
#请保存为UTF-8格式
org.springframework.cloud
spring-cloud-config
server:
port: 3355
spring:
cloud:
config:
name: microservice-config-client
profile: dev
label: master
uri: http://config-3344.com:3344 #本微服务启动后先去找3344服务,通过SpringCloudConfig获取Github的服务地址
application.yml
spring:
application:
name: microservice-config-client
127.0.0.1 client-config.com
@Value("${spring.application.name}")
private String applicationName;
@Value("${eureka.client.service-url.defaultZone}")
private String eurekaServers;
@Value("${server.port}")
private String port;
@RequestMapping("/config")
public String getConfig() {
String str = "applicationName:" + applicationName + "\t eurekaServers:"
+ eurekaServers + "\t port:" + port;
System.out.println("******str:" + str);
return str;
}
修改bootstrap.yml 中profile: dev 改为 profile: test
地址: http://client-config.com:8202/config
spring:
cloud:
config:
name: microservice-config-eureka-client #github上的配置文件名称,没有yml文件后缀
profile: dev
label: master
uri: http://config-3344.com:3344 #本微服务启动后先去找3344服务,通过SpringCloudConfig获取Github的服务地址
application.yml文件
spring:
application:
name: microservice-config-eureka-client
测试
启动服务microservice-config-server
地址: http://config-3344.com:3344/application-dev.yml
启动服务microservice-config-eureka-client
地址: http://eureka7001.com:7001/
添加模块microservice-config-blog-client
pom文件拷贝provider 模块pom文件
bootstrap.yml
spring:
cloud:
config:
name: microservice-config-blog-client #github上的配置文件名称,没有yml文件后缀
profile: dev
label: master
uri: http://config-3344.com:3344 #本微服务启动后先去找3344服务,通过SpringCloudConfig获取Github的服务地址
application.yml
spring:
application:
name: microservice-config-blog-client
github上文件:
https://github.com/xiaoxiongxiong/microservice-config.git
项目代码:https://github.com/xiaoxiongxiong/springcloud.git
ssh :[email protected]:xiaoxiongxiong/springcloud.git
待更新 延申启动多服务需要写脚本
规范:约定》配置》编码
遇到异常:
1.无法引入api模块问题
//没有执行 mvn clean instal 命令
2.java.lang.IllegalStateException: Restarter has not been initialized
//因为devtools jar包依赖版本问题
3.org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
//mapper.xml内的namespace写错
4.com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class com.microservice.springcloud.entity.Blog and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: java.util.ArrayList[0])
//实体类没有实现Serializable implements Serializable
5.The error occurred while handling results ### SQL: select * from blog ### Cause: java.lang.UnsupportedOperationException
//
6.Could not find result map 'com.microservice.springcloud.entity.Blog' referenced from
//resultMap改为resultType
7.mybatisMapper.xml jdbcType = int 改为 jdbcType = INTEGER
8.如果表单删除数据
public Map deleteBlog(@RequestParam("id") String id){...
如果参数未json数据:
public Map deleteBlog(@RequestBody Map map){...
9.Could not autowire. No beans of 'RestTemplate' type found. less... (Ctrl+F1)
Inspection info:Checks autowiring problems in a bean class.
原因:provider模块的controller层与consumer模块的contrller层再同一包下,类名相同导致,修改类名错误消失
10.Error:(27, 60) java: 无法访问org.springframework.core.NestedRuntimeException
找不到org.springframework.core.NestedRuntimeException的类文件
原因:没有引用spring-core和spring-context jar包
11.java.lang.ClassNotFoundException: org.springframework.core.KotlinDetector
更改spring-core版本为5.0.1以上即可
12.org.springframework.core.KotlinDetector.isKotlinReflectPresent()
pom.xml中引入了spring-boot-starter-web ,同时pom.xml也引入了spring-core,spring-beans,这里去掉spring-core,spring-beans即可
12.maven窗口 模块为灰色
解决办法:
Preferences -> build -> maven -> ignore files,找到对应的maven模块,取消勾选。
jar包删除重新加载
13.java.lang.NoSuchMethodError: org.yaml.snakeyaml.nodes.ScalarNode.getScalarStyle()Lorg/yaml/snakeyaml/DumperOptions$ScalarStyle;
jar包依赖 环境问题
解决方法:确认模块jdk选择是否正确
参考资料:
阿里云大学
springcloud官网
工程打包