首页IT科技springcloud注册服务原理(Spring Cloud使用Consul作为注册中心示例)

springcloud注册服务原理(Spring Cloud使用Consul作为注册中心示例)

时间2025-05-27 23:13:10分类IT科技浏览5095
导读:最近在极客时间上面学习丁雪丰老师的《玩转 Spring 全家桶》,学到了服务注册中心这块,动手实践了一下,老师的视频录制是3年前,现在也有了些变化,自己也动手解决了一下,只有自己写一写才理解的更加细致一些,不然光看一遍视频,有点走马观花。 现将主要过程记录如下...

最近在极客时间上面学习丁雪丰老师的《玩转 Spring 全家桶》            ,学到了服务注册中心这块                    ,动手实践了一下       ,老师的视频录制是3年前         ,现在也有了些变化                   ,自己也动手解决了一下           ,只有自己写一写才理解的更加细致一些      ,不然光看一遍视频                  ,有点走马观花              。 现将主要过程记录如下

准备工作

首先在本地docker上面安装Consul

docker pull consul docker run --name my_consul -d -p 8500:8500 -p 8600:8600/udp consul

在8500端口上面启动了consul              , 在浏览器上输入http://localhost:8500/ 就可以看到打开如下图的一个界面                   。

编写两个服务

我们这里简单的做两个服务   ,一个bookshop-service                  , 它提供读写表的服务;另外一个是book-customer-service                 , 它调用bookshop-service在控制台输出读取到的数据      。

父POM文件定义 <properties> <java.version>19</java.version> <spring-cloud.version>2022.0.0</spring-cloud.version> <spring-boot.version>3.0.0</spring-boot.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>

在dependencyManagement中引入spring-boot-dependencies和spring-cloud-dependencies

编写bookshop-service服务

首先在POM中引入需要用到的包

<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-consul-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> </dependencies>

spring-cloud-starter-consul-discovery就是用来和consul通信的包

spring-boot-starter-data-jpa 和 h2是我们访问数据库的包,我们使用内存数据库h2

定义一个model @Entity @Table(name = "T_BOOK") @Data @Builder @NoArgsConstructor @AllArgsConstructor public class Book implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private String author; @Column(updatable = false) @CreationTimestamp private Date createTime; @UpdateTimestamp private Date updateTime; }

在resouces下面放入schema.sql用来建表和插入数据

drop table t_book if exists; create table t_book ( id bigint auto_increment, create_time timestamp, update_time timestamp, name varchar(255), author varchar(200), primary key (id) ); insert into t_book (name, author, create_time, update_time) values (python, zhangsan, now(), now()); insert into t_book (name, author, create_time, update_time) values (hadoop, lisi, now(), now()); insert into t_book (name, author, create_time, update_time) values (java, wangwu, now(), now());

定义一个JpaRepository

@RepositoryRestResource(collectionResourceRel = "rest-books", path = "rest-books") public interface BookRepository extends JpaRepository<Book, Long> { List<Book> findByName(@Param("name") String name); }

我还加了一个hateoas的注解               ,可以对外提供restful服务                    ,

定义一个controller提供服务

@RestController @RequestMapping("/book") @Slf4j public class BookController { @Autowired private BookService bookService; @GetMapping(path = "/getAll", params = "!name") public List<Book> getAll() { return bookService.getAllBook(); } @GetMapping("/{id}") public Optional<Book> getById(@PathVariable Long id) { Optional<Book> book = bookService.getBook(id); return book; } @GetMapping(path = "/", params = "name") public Optional<Book> getByName(@RequestParam String name) { return bookService.getBook(name); } }

BookService就是调用BookRepository   ,这里代码省略

在application.properties中加入如下配置 spring.application.name=bookshop-service server.port=0 spring.cloud.consul.host=localhost spring.cloud.consul.port=8500 spring.cloud.consul.discovery.prefer-ip-address=true spring.jpa.hibernate.ddl-auto=none spring.jpa.properties.hibernate.show_sql=true spring.jpa.properties.hibernate.format_sql=true management.endpoints.web.exposure.include=* management.endpoint.health.show-details=always management.health.redis.enabled=false

到这里这个服务就编写好了            ,我们启动它

我们可以看到这个服务就已经上来了          。

编写book-customer-service

它是一个控制台程序                    ,我们为了演示它       ,也把它弄成了一个service

首先依然是pom文件 <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-rest</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-consul-discovery</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.7</version> </dependency> </dependencies>

定义一个ApplicationRunner来取数据和打印数据

@Component @Slf4j public class BookCustomerRunner implements ApplicationRunner { @Autowired private RestTemplate restTemplate; @Autowired private DiscoveryClient discoveryClient; @Override public void run(ApplicationArguments args) throws Exception { showServiceInstances(); readBooks(); queryBook(1L); } private void showServiceInstances() { log.info("DiscoveryClient: {}", discoveryClient.getClass().getName()); discoveryClient.getInstances("bookshop-service").forEach(s -> { log.info("Host: {}, Port: {}", s.getHost(), s.getPort()); }); } private void readBooks() { ParameterizedTypeReference<List<Book>> ptr = new ParameterizedTypeReference<List<Book>>() {}; ResponseEntity<List<Book>> list = restTemplate .exchange("http://bookshop-service/book/getAll", HttpMethod.GET, null, ptr); list.getBody().forEach(c -> log.info("Book: {}", c)); } private void queryBook(Long id){ Book book = restTemplate .getForObject("http://bookshop-service/book/{id}", Book.class, id); log.info("Book: {}", book); } }

这里我们可以看到我们使用了“http://bookshop-service/book/getAll            ”         , 它就是我们注册到consul的服务                   ,我们在浏览器输入是拿不到数据的           ,这里spring帮我们做了转换      ,我们的showServiceInstances                  ,就是打印出真实的host和port                    。

在这个示例中我们的输出如下

它打印出来对应的Host和Post              ,然后打印出来了我们从数据库里读出来的几条数据         。

我们来看一下现在consul是怎么显示的   , 可以看到book-customer-service也已经上来了      。

最后

代码我上传到了https://github.com/dengkun39/redisdemo

在学习的时候我还使用了zookeeper来作为服务注册中心                  , 代码几乎不需要动                 ,只是需要把spring-cloud-starter-consul-discovery 换成spring-cloud-starter-zookeeper-discovery,然后配置文件中加上spring.cloud.zookeeper.connect-string=localhost:2181                    。 使用zookeeper遇到一段时间后再访问就出现                    ”I/O error on GET request for "http://bookshop-service/book/getAll": Permission denied: no further information“ 应该是有些设置没有弄到位               , 刚开始学习                    ,没有办法细究是怎么回事            。

服务注册中心学完了   ,如果需要对外提供服务应该怎么弄呢?总不能像我这样明明是控制台也把它弄成一个服务吧   。 这个问题我暂时不知道答案            ,留在这里                    ,后面学习了再来回答它                    。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
vue3搭建脚手架(Vue3创建项目(四)main.js配置,避坑指南) 注册接口异常是什么意思啊(登录注册接口搭建)