本文是看某课网关于 SpringCloud 微服务实战的视频总结的笔记,其中涉及了
- Eureka Server 和 Eureka Client 的配置
- Eureka Server 高可用性
- 服务间通信的两种方式:RestTemplate 和 Feign
- RabbitMQ 的安装和使用
- 配置中心的使用
- Spring Cloud Stream 的使用
- 服务网关 Zuul 的各种用法
由于是随堂笔记,写的有点随意,大佬们见谅~
文中提到的大部分技术都会在我的一个开源项目中用到,这个项目后端业务逻辑部分已经基本写完了,就差权限验证、网关配置和后期优化啦,感兴趣的大佬可以看看。
项目地址:https://github.com/cachecats/coderiver
一、关于命令行
启动 SpringBoot 项目
java -jar test.jar
启动 SpringBoot 项目并指定端口
java -jar -Dserver.port=8899 test.jar
启动 SpringBoot 项目并指定后台运行
nohup java -jar test.jar > /dev/null 2>&1 &
查看进程
ps -ef | grep eureka
杀死进程
kill -9 进程号
在本地安装项目到本地 maven 仓库
mvn -Dmaven.test.skip=true -U clean install
二、Eureka Server
2.1 新建
选 CloudDiscovery -> Eureka Server
注意 SpringBoot 版本
2.2 配置
在启动类 Application 上加注解
@EnableEurekaServer
在配置文件 application.yml
注册服务
eureka:
client:
service-url:
defaultZone: http://localhost:8080/eureka/
启动项目,浏览器输入地址 http://localhost:8080
即可看到项目正常启动,并将自己注册上去了
ApplicationName
是 UNKNOWN
,想改应用名字的话在 application.yml
做以下配置
eureka:
client:
service-url:
defaultZone: http://localhost:8080/eureka/
spring:
application:
name: eureka
再启动项目,浏览器中查看,名字正确显示
如果不想让注册中心出现在注册列表中,配置 register-with-eureka: false
eureka:
client:
service-url:
defaultZone: http://localhost:8080/eureka/ #配置默认注册地址
register-with-eureka: false #不让该服务显示在应用列表中
spring:
application:
name: eureka #配置应用名字
三、Eureka Client
3.1 新建项目
选 CloudDiscovery -> Eureka Discovery
注意 SpringBoot 和 SpringCloud 版本与server一致
3.2 配置
- 入口
Application
添加注解@EnableDiscoveryClient
@SpringBootApplication
@EnableDiscoveryClient
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
- 配置 server 地址
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
spring:
application:
name: client
- 自定义链接地址,配置完后浏览器地址会变成
http://clientname:8080/
eureka:
instance:
hostname: clientName
- 如果频繁重启 client 服务,会出现如下警告
这是 SpringCloud 的自我保护机制,就是不管这个服务在不在线,都把它当成在线。开发环境中为了调试方便可以关闭这个功能,注意生产环境一定要打开。
在 server 的 applicaitono.yml
中做如下配置
eureka:
server:
enable-self-preservation: false
四、Eureka Server 高可用性
目前是 Client 注册到一个 Eureka Server 上,如果这个 Server 挂掉了怎么办呢?
可以启动多个 Eureka Server ,让他们相互注册。
这里演示启动三个 Eureka Server 相互注册,并把 Client 分别注册到这三个 Server 上。
配置 server
分别在 8761, 8762, 8763 三个端口上启动 EurekaApplication
、EurekaApplication2
、EurekaApplication3
三个服务,在三个服务的 applicaiton.yml
中分别配置其他两个服务的地址。
如EurekaApplication
就配 http://localhost:8762/eureka/,http://localhost:8763/eureka/
,
EurekaApplication2
就配 http://localhost:8761/eureka/,http://localhost:8763/eureka/
,
EurekaApplication3
就配 http://localhost:8761/eureka/,http://localhost:8762/eureka/
,
EurekaApplication
的 applicaiton.yml
如下:
eureka:
client:
service-url:
defaultZone: http://localhost:8762/eureka/,http://localhost:8763/eureka/
这样就把三个服务互相关联上了。
配置 client
然后在 Client 的 applicaiton.yml
中把三个服务地址都配上
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/,http://localhost:8763/eureka/
查看EurekaApplication
,发现注册到了8762 和 8763 上。三个server只要还有一个活着,服务就不会挂。
五、应用间通信
应用间通信有两种主流通信方式:
HTTP代表: SpringCloud
RPC代表: Dubbo
SpringCloud 中服务间两种 restful 调用方式
- RestTemplate
- Feign
5.1 RestTemplate 方式
RestTemplate 调用一共有三种方法,下面一一介绍。
先在要提供数据的应用里写个 Controller 暴露接口,叫 ServerController
吧
@RestController
@RequestMapping("/product")
public class ServerController {
@GetMapping("/msg")
public String getMsg(){
return "I am product msg";
}
}
然后在需要接收数据的应用写个 Controller ,叫 ClientController
5.1.1 方法一
直接使用 RestTemplate
手动写入提供数据的 url 地址
@RestController
@RequestMapping("/order")
@Slf4j
public class ClientController {
@GetMapping("/getmsg")
public String getMsg(){
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject("http://localhost:8080/product/msg", String.class);
log.info("result={}", result);
return result;
}
}
5.1.2 方法二
不手动输入 url 地址,使用 LoadBalancerClient
通过应用名动态获取,然后再使用 RestTemplate
。
loadBalancerClient.choose("product");
这个 product
是提供数据的应用 id
@RestController
@RequestMapping("/order")
@Slf4j
public class ClientController {
@Autowired
LoadBalancerClient loadBalancerClient;
@GetMapping("/getmsg")
public String getMsg(){
ServiceInstance serviceInstance = loadBalancerClient.choose("product");
String url = String.format("http://%s:%s/product/msg", serviceInstance.getHost(), serviceInstance.getPort());
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject(url, String.class);
return result;
}
}
5.1.3方法三
用 @LoadBalanced
注解
新建 RestTemplateConfig
类
@Component
public class RestTemplateConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
然后在 ClientController
中使用。
restTemplate.getForObject("http://product/product/msg", String.class);
url 中的两个 product
,第一个表示应用名,第二个是 api 的地址。如果 api 地址是 /abc
,那 url 就是 http://product/abc
@RestController
@RequestMapping("/order")
@Slf4j
public class ClientController {
@Autowired
RestTemplate restTemplate;
@GetMapping("/getmsg")
public String getMsg(){
String result = restTemplate.getForObject("http://product/product/msg", String.class);
return result;
}
}
5.2 Feign 方式
使用 Feign 有以下几个步骤
步骤一:引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>