一、创建原始直连项目
这个没什么可说的,直接创建两个项目(服务提供者和服务消费者),用来模拟原始的使用http的调用。
对于项目内部的实现不再赘述,都是简单的增删改查,这里主要演示一下服务提供者提供的服务以及服务消费者对服务的调用。
1、服务提供者提供的服务
@RequestMapping("/provider/depart") @RestController public class DepartController { @Autowired private DepartService service; //新增 @PostMapping("/save") public boolean saveHandle(@RequestBody Depart depart) { return service.saveDepart(depart); } //删除 @DeleteMapping("/del/{id}") public boolean deleteHandle(@PathVariable("id") int id) { return service.removeDepartById(id); } //修改 @PutMapping("/update") public boolean updateHandle(@RequestBody Depart depart) { return service.modifyDepart(depart); } //根据id查询 @GetMapping("/get/{id}") public Depart getHandle(@PathVariable("id") int id) { return service.getDepartById(id); } //查询列表 @GetMapping("/list") public List<Depart> listHandle() { return service.listAllDeparts(); } }
配置文件信息
server: port: 8081 spring: application: name: provider01-depart jpa: generate-ddl: true show-sql: true hibernate: ddl-auto: none datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://172.20.10.14:3306/test?useUnicode=true&characterEncoding=utf8 username: root password: root logging: pattern: console: level-%level %msg%n level: root: info org.hibernate: info org.hibernate.type.descriptor.sql.BasicBinder: trace org.hibernate.type.descriptor.sql.BasicExtractor: trace com.abc: debug
2、服务消费者消费服务
@RestController @RequestMapping("/consumer/depart") public class DepartController { //注入RestTemplate模板对象 @Autowired private RestTemplate restTemplate;//配置请求地址 private static final String SERVICE_PROVIDER = "http://localhost:8081"; //跨服务新增 @PostMapping("/save") public boolean saveHandle(@RequestBody Depart depart) { String url = SERVICE_PROVIDER + "/provider/depart/save"; //TODO 问题:消费者直连提供者行不行? Boolean result = restTemplate.postForObject(url, depart, Boolean.class); return result; } //跨服务根据id删除 @DeleteMapping("/del/{id}") public void deleteHandle(@PathVariable("id") int id) { String url = SERVICE_PROVIDER + "/provider/depart/del/" + id; restTemplate.delete(url); } //跨服务修改 @PutMapping("/update") public void updateHandle(@RequestBody Depart depart) { String url = SERVICE_PROVIDER + "/provider/depart/update"; restTemplate.put(url, depart, Boolean.class); } //跨服务根据id查询 @GetMapping("/get/{id}") public Depart getHandle(@PathVariable("id") int id) { String url = SERVICE_PROVIDER + "/provider/depart/get/" + id; Depart depart = restTemplate.getForObject(url, Depart.class); return depart; } //跨服务根据列表查询 @GetMapping("/list") public List<Depart> listHandle() { String url = SERVICE_PROVIDER + "/provider/depart/list/"; List list = restTemplate.getForObject(url, List.class); return list; } }
这里用到了restTemplate,在主类上进行注入
@SpringBootApplication public class Consumer01Application { public static void main(String[] args) { SpringApplication.run(Consumer01Application.class, args); } @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } }
配置文件
server: port: 8080 spring: application: name: consumer01-depart
效果就不演示了,就是最简单的服务调用。
二、Nacos服务注册与发现
上面使用的是最简单的http服务调用,但是存在很多问题,例如服务提供者ip变化等,者就用到了注册中心,而SpringCloudAlibaba的注册中心是Nacos。
(一)安装
nacos官网地址:https://nacos.io/zh-cn/,Nacos既是一个注册中心,又是一个配置中心。
下载:在官网中有对应的github地址,进入github进行下载。这里下载使用的是最新的2.0.3版本。
下载后解压,进入解压后的bin目录,直接运行即可。
sh startup.sh -m standalone
这里需要设置启动的模式为单机模式,因为不设置的话,会默认使用集群模式。
启动后,可以直接访问nacos控制台(端口为默认的8848,可以在nacos解压目录中的conf/application.properties中修改),登录账号默认为nacos/nacos
(二)应用
在项目中使用Ncos作为注册中心是比较简单的,只需要在配置文件中将其作为注册中心即可,然后在服务调用的时候使用服务名进行调用即可。
1、pom文件
我这里直接在父项目中直接进行了配置,所有的子项目都无需再单独配置。
这里需要特殊说明一点,Springboot版本和SpringCloud版本一定要匹配,否则会启动报错,具体的版本对应关系可以上Spring官网进行查看。
<properties> <java.version>1.8</java.version> <spring-cloud.version>Hoxton.SR8</spring-cloud.version> <spring-cloud-alibaba.version>2.2.3.RELEASE</spring-cloud-alibaba.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--nacos discovery依赖--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!--actuator依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>${spring-cloud-alibaba.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
2、配置文件修改
在原来的基础项目上修改配置文件:
(1)provider加上如下配置
spring: cloud: nacos: discovery: server-addr: 172.20.10.2:8848 application: name: provider01-depart
(2)consumer加上如下配置
spring: application: name: consumer01-depart cloud: nacos: discovery: server-addr: 172.20.10.2:8848
3、调用修改
直接使用配置的服务名进行调用即可。
@Autowired private RestTemplate restTemplate; //配置请求地址 private static final String SERVICE_PROVIDER = "http://provider01-depart"; //跨服务新增 @PostMapping("/save") public boolean saveHandle(@RequestBody Depart depart) { String url = SERVICE_PROVIDER + "/provider/depart/save"; //TODO 问题:消费者直连提供者行不行? Boolean result = restTemplate.postForObject(url, depart, Boolean.class); return result; }
(三)修改数据库地址及集群搭建
1、修改内置数据库,改为使用自己的数据库
Nacos中使用的数据库是内置的,我们可以将其改为自己的数据库。
数据库的建表及数据信息在Nacos的解压文件中:cat conf/nacos-mysql.sql
创建完相应的表和数据后,修改配置文件中的数据库地址:conf/application.peopertites
spring.datasource.platform=mysql db.num=1 db.url.0=jdbc:mysql://172.20.10.14:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC db.user.0=root db.password.0=root
2、集群搭建
这里搭建一个伪集群演示,实际的集群与伪集群一样。
首先随意创建一个目录,用于存放三个 Nacos 服务器。然后再复制原来配置好的单机版的 Nacos 到这个目录,并重命名为 nacos8840。打开 nacos8847/conf,重命名其中的 cluster.conf.example 为 cluster.conf。然后打开该文件,在其中写入三个 nacos 的 ip:port。
172.20.10.2:8840 172.20.10.2:8845 172.20.10.2:8849
然后修改端口号为8847即可(application.properties文件)
同样的,创建nacos8848和nacos8849两个文件夹,并做同样的操作。
最后启动三个nacos服务即可,集群搭建完毕。
sh nacos8840/bin/startup.sh sh nacos8845/bin/startup.sh sh nacos8849/bin/startup.sh
3、集群搭建中的问题
(1)在集群搭建好启动时吗,出现No DataSource set的错误
原因:数据库连接地址有问题,nacos2.0.2中默认的数据库名称是nacos,但是貌似1.x版本的数据库名称都是nacos_config,我这里配置错误导致的。
(2)集群启动时报:Failed to bind
原因:nacos2.0需要4个端口,其他的端口号都是依赖于server.port的,我第一次设置的时候,设置的三个端口分别为8847、8848、8849,从而导致grpc端口冲突
解决方案:保证伪集群的节点端口不要连续即可,我这里设置为8840、8845、8849,启动成功
server.port(默认8848) raft port: ${server.port} - 1000 grpc port: ${server.port} + 1000 grpc port for server: ${server.port} + 1001
三、Nacos Config配置中心
(一)配置中心使用
上面提到,Nacos既可以作为注册中心又可以作为配置中心,首先需要添加pom依赖。
<!--nacos config 依赖--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency>
然后就是删除掉原来的application.yml配置文件(后续在配置中心中直接配置即可),同时新增一个boostrap.yml文件,用来配置项目名称和配置中心地址。
spring: cloud: nacos: config: server-addr: 172.20.10.2:8848 file-extension: yml application: name: provider02-depart
然后在Nacos控制台的配置管理里面新增配置文件,其实就是原来项目中的application配置文件:
配置完成,项目可以正常启动,说明配置中心已经配置成功。
(二)动态更新配置
动态更新配置比较简单,就是在使用配置的地方使用@RefreshScope注解即可,为了演示,在配置中心中新增depart.name配置内容,修改get方法
@Service @RefreshScope public class DepartServiceImpl implements DepartService { @Autowired private DepartRepository repository; @Value("${depart.name}") private String departName; @Override public Depart getDepartById(int id) { if(repository.existsById(id)) { return repository.getOne(id); } Depart depart = new Depart(); depart.setName(departName); return depart; } }
然后更新depart.name的内容,无需重启项目,改动即可生效。
(三)多环境部署
首先在Nacos控制台新增不同环境的配置文件,这里可以使用克隆。
在bootstrap.yml中新增多环境配置
spring: cloud: nacos: config: server-addr: 172.20.10.2:8848 file-extension: yml application: name: provider02-depart profiles: active: test