1.Eureka

1.1RestTemplate

它提供了多种访问远程http服务的方法,是一种简单便捷的访问restful服务模板类,是spring提供的用于访问Rest服务的客户端模板工具集。

1.2RestTemplate项目模块搭建

这里使用maven和mybatis进行模块的搭建,步骤如下。

1.2.1搭建父模块cloud-eureka-demo

1)创建一个maven工程名为cloud-eureka-demo,删除src目录

2)在pom中导入依赖

<!--统一管理jar包版本-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<junit.version>4.12</junit.version>
<lombok.version>1.16.18</lombok.version>
<log4j.version>1.2.17</log4j.version>
<mysql.version>5.1.47</mysql.version>
<druid.version>1.1.16</druid.version>
<mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version>
</properties> <!-- 依赖管理,父工程锁定版本-->
<dependencyManagement>
<dependencies>
<!--spring boot 2.2.2-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud Hoxton.SR1-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud alibaba 2.1.0-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!--druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.spring.boot.version}</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<!--log4j-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
</dependencies>
</dependencyManagement> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<addResources>true</addResources>
</configuration>
</plugin>
</plugins>
</build>

1.2.2搭建公共服务模块eureka-demo-api

公共服务模块用于存放公用的东西,如实体类等。

1)创建maven的工程名为eureka-demo-api,在pom中导入依赖

 <dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>

2)创建包com.zys.cloud.entity,在包下创建实体类User,内容如下

package com.zys.cloud.entity;

import lombok.*;

@Getter
@Setter
@ToString
public class User {
private Long id;
private String name;
private String phone;
}

1.2.3搭建服务提供者模块eureka-demo-provider

1)创建maven的工程名为eureka-demo-provider,在pom中导入依赖

<dependencies>
<!--web-->
<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>com.zys.springcloud</groupId>
<artifactId>eureka-demo-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<!--mysql-connector-java-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--eureka-client--> </dependencies>

2)创建包com.zys.cloud,在包下新建启动类ProviderMain8001

package com.zys.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication
public class ProviderMain8001 {
public static void main(String[] args) {
SpringApplication.run(ProviderMain8001.class, args);
}
}

3)在com.zys.cloud包下在创建controller包,存放UserController

package com.zys.cloud.controller;

import com.zys.cloud.entity.User;
import com.zys.cloud.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import java.util.HashMap;
import java.util.Map; @RestController
@RequestMapping("/user")
public class UserController { @Autowired
private UserService userService; @GetMapping("/get/{id}")
public User getUser(@PathVariable("id")long id){
return userService.getUser(id);
} @PostMapping("/add")
public Map<String,Object> addUser(User user){
System.out.println(user);
Map<String,Object> map=new HashMap<>();
if(userService.addUser(user)!=0){
map.put("msg","添加成功");
map.put("code",200);
}else{
map.put("msg","添加失败");
map.put("code",444);
}
return map;
}
}

4)在com.zys.cloud包下在创建service包,存放UserService

package com.zys.cloud.service;

import com.zys.cloud.entity.User;

public interface UserService {
public User getUser(long id); int addUser(User user);
}

5)在com.zys.cloud.service包下在创建impl包,存放UserServiceImpl

package com.zys.cloud.service.impl;

import com.zys.cloud.dao.UserDao;
import com.zys.cloud.entity.User;
import com.zys.cloud.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; @Service
public class UserServiceImpl implements UserService { @Autowired
private UserDao userDao; @Override
public User getUser(long id) {
return userDao.getById(id);
} @Override
public int addUser(User user) {
return userDao.create(user);
}
}

6)在com.zys.cloud包下在创建dao包,存放UserDao

package com.zys.cloud.dao;

import com.zys.cloud.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param; @Mapper
public interface UserDao {
int create(User user); User getById(@Param("id") Long id);
}

7)在资源目录下新建mapper文件夹,然后再创建UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zys.cloud.dao.UserDao"> <insert id="create" parameterType="User" >
insert into user values(null,#{name},#{phone})
</insert> <resultMap id="BaseResultMap" type="com.zys.cloud.entity.User">
<id column="id" property="id" jdbcType="BIGINT"/>
<result column="name" property="name" jdbcType="VARCHAR"/>
<result column="phone" property="phone" jdbcType="VARCHAR"/>
</resultMap>
<select id="getById" parameterType="Long" resultMap="BaseResultMap">
select * from user where id=#{id};
</select>
</mapper>

8)在资源目录下创建配置文件application.yml  

server:
port: 8001 spring:
application:
name: cloud-eureka-demo-provider
datasource:
type: com.alibaba.druid.pool.DruidDataSource #当前数据源操作类型
driver-class-name: org.gjt.mm.mysql.Driver #mysql驱动包
url: jdbc:mysql://localhost:3306/db2020?useUnicode=true&characterEncoding-utr-8&useSSL=false
username: root
password: 123456 mybatis:
mapper-locations: classpath:mapper/*.xml
#所有Entity别名类所在包
type-aliases-package: com.zys.cloud.entity

9)创建mysql的数据库和表

create database db2020;
use db2021;
create table user (
id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
name varchar(200) DEFAULT '',
phone varchar(200) DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; insert into user values(null,'李明','101');
insert into user values(null,'赵慧','101');
insert into user values(null,'李凯','101');

10)运行测试

启动主启动类,使用postman工具输入http://127.0.0.1:8001/user/get/2使用get方式测试,再输入http://127.0.0.1:8001/user/add?name=哈哈哈&phone=101使用post方式测试。

1.2.4搭建服务消费者模块eureka-demo-consumer

1)创建maven的工程名为eureka-demo-consumer,在pom中导入依赖

    <dependencies>
<!--web-->
<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>com.zys.springcloud</groupId>
<artifactId>eureka-demo-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency> </dependencies>

2)创建包com.zys.cloud,在包下新建启动类ConsumerMain80

package com.zys.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication
public class ConsumerMain80 {
public static void main(String[] args) {
SpringApplication.run(ConsumerMain80.class, args);
}
}

3)在com.zys.cloud包下在创建config包,存放配置类

package com.zys.cloud.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate; //相当于spring中的applicationContext.xml
@Configuration
public class ConfigBean { @Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}

4)在com.zys.cloud包下在创建controller包,存放UserController

package com.zys.cloud.controller;

import com.zys.cloud.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate; import java.util.Map; @RestController
@RequestMapping("/consumer")
public class UserController {
private final String BASE_URL="http://127.0.0.1:8001"; @Autowired
private RestTemplate restTemplate; @GetMapping("/get/{id}")
public User getUser(@PathVariable("id") long id){
return restTemplate.getForObject(BASE_URL+"/user/get/"+id,User.class);
} @PostMapping("/add")
public Map<String,Object> addUser(User user){
return restTemplate.postForObject(BASE_URL+"/user/add",user,Map.class);
} }

5)在资源目录下创建配置文件application.yml

server:
port: 80

6)修改eureka-demo-provider的UserController类中addUser方法,给User参数添加@RequestBody注解

7)运行测试

启动主启动类,使用postman工具输入http://127.0.0.1/consumer/get/1使用get方式测试,再输入http://127.0.0.1/consumer/add?name=嘻嘻嘻&phone=101使用post方式测试。

1.3Eureka

1.3.1定义

它是一个基于REST的服务,用于定位服务,以实现云端中间层发现和故障转移。简单来说就是服务注册与发现,只要使用服务的标识就可以访问到服务,类似于Dubbo的注册中心Zookeeper。
它采用cs架构,Eureka Server作为服务注册的服务器,是注册中心;Eureka Client是客户端,需要注册的服务使用客户端连接到服务器并维持心跳。可以通过服务器来监测各个微服务是否正常运行。

1.3.2原理图

1.4Eureka结合RestTemplate开发

有了1.2的例子,这里就在这个基础上进行后续的操作。完整的代码可参考https://github.com/zhongyushi-git/cloud-eureka-demo.git。

1.4.1搭建eureka的服务注册中心

所谓服务中心,也就是Eureka Server。服务中心需要在启动类上添加注解@EnableEurekaServer表示这是一个Eureka的服务中心

1)创建maven的工程名为eureka-demo-server7001,在pom中导入依赖

 <dependencies>
<!--eureka server-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<!--boot web actuator-->
<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> </dependencies>

2)创建包com.zys.cloud,在包下新建启动类EurekaMain7001

package com.zys.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @SpringBootApplication
@EnableEurekaServer
public class EurekaMain7001 {
public static void main(String[] args) {
SpringApplication.run(EurekaMain7001.class, args);
}
}

3)在资源目录下创建配置文件application.yml

server:
port: 7001 eureka:
instance:
#eureka服务端的实例名称
hostname: localhost
client:
#false表示不向注册中心注册自己
register-with-eureka: false
#false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
fetch-registry: false
service-url:
#设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

4)运行测试

启动主启动类,在浏览器输入http://127.0.0.1:7001测试server是否搭建成功,看到下图说明已搭建成功。

1.4.2将服务提供者注册到eureka

1)在eureka-demo-provider的pom中添加eureka客户端的依赖

  <!--eureka-client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

2)在eureka-demo-provider的yml文件中添加eureka客户端的配置

#把客户端注册到服务列表中
eureka:
client:
#表示是否将自己注册进EurekaServer默认为true
register-with-eureka: true
#是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetch-registry: true
service-url:
defaultZone: http://localhost:7001/eureka

3)在eureka-demo-provider的启动类上添加eureka客户端的注解@EnableEurekaClient

@SpringBootApplication
@EnableEurekaClient
public class ProviderMain8001 {
public static void main(String[] args) {
SpringApplication.run(ProviderMain8001.class, args);
}
}

4)运行测试

先运行eureka服务,再运行服务提供者,在浏览器输入http://127.0.0.1:7001,看到有一个服务,说明注册成功。注册成功后同样把消费者注册到eureka中。

1.4.3微服务优化

1)主机名称映射

在1.4.2中,可以看到运行测试时,status显示的主机名和服务名,太长了,不美观,可以直接指定服务名称。在eureka-demo-provider的配置文件yml中指定入驻实例的名称

#把客户端注册到服务列表中
eureka:
client:
#表示是否将自己注册进EurekaServer默认为true
register-with-eureka: true
#是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetch-registry: true
service-url:
defaultZone: http://localhost:7001/eureka
#设置入驻的服务的名称,是唯一的
instance:
instance-id: cloud-eureka-demo-provider

2)访问信息提示IP

在鼠标处于服务名称的位置时,在浏览器左下角只显示的是localhost,但是不同的服务应该显示具体 ip地址,在eureka-demo-provider的配置文件yml中开启显示即可

#把客户端注册到服务列表中
eureka:
client:
#表示是否将自己注册进EurekaServer默认为true
register-with-eureka: true
#是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetch-registry: true
service-url:
defaultZone: http://localhost:7001/eureka
#设置入驻的服务的名称,是唯一的
instance:
instance-id: cloud-eureka-demo-provider
#访问路径显示ip
prefer-ip-address: true

1.4.4 eureka自我保护

在刚刚启动的时候,并没有出现下面红色的部分,但是过一会再次刷新,就会出现下面的红色文字。也就是说是eureka的自我保护机制发挥的作用。简单来说,就是某一时刻,某个服务不使用了,但eureka并不会立即清除掉,而是依旧保持此微服务的信息。当它收到的心跳数重新恢复到阈值以上时该服务节点会自动退出保护模式。是一种应对网络异常的安全保护措施。

有时候就想某个服务不用了或者死掉了,就直接清理,如何操作呢?也是可以配置的。

在7001的yml设置server.enable-self-preservation为false,配置如下

  #关闭自我保护
eureka:
server:
enable-self-preservation: false
eviction-interval-timer-in-ms: 2000

在8001的yml设置连接的时间

eureka:
instance:
#eureka服务端在接受到最后一次心跳后等待的时间,默认90s,超时剔除服务
lease-expiration-duration-in-seconds: 2
#eureka客户端向服务端发送心跳的时间,默认30s
lease-renewal-interval-in-seconds: 1

然后启动7001和8001,访问http://eureka7001.com:7001/,出现下图说明关闭成功。

悄悄的关闭8001,刷新页面,发现8001的服务不在了。

1.4.5 eureka集群

如果eureka服务注册中心只有一台,当服务器宕机时,就不能正常提供服务了,因此集群也是很重要的。这里就由三个服务器组成一个集群。

1)新建maven工程eureka-demo-server7002和eureka-demo-server7003。后面就简称7002和7003

2)分别把eureka-demo-server7001的pom依赖复制到7002和7003中

3)参照7001创建7002和7003的启动类

4)修改域名映射文件C:\Windows\System32\drivers\etc\hosts, 在最后添加

127.0.0.1	eureka7001.com
127.0.0.1 eureka7002.com
127.0.0.1 eureka7003.com

5)修改配置文件yml

7001的yml

server:
port: 7001 eureka:
instance:
#eureka服务端的实例名称
#单机版
# hostname: localhost
#集群
hostname: eureka7001.com
client:
#false表示不向注册中心注册自己
register-with-eureka: false
#false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
fetch-registry: false
service-url:
#设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址
#单机版
# defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
#集群
defaultZone: http://eureka7002.com:7002/eureka/, http://eureka7003.com:7003/eureka/

7002的yml

server:
port: 7002 eureka:
instance:
#eureka服务端的实例名称
#单机版
# hostname: localhost
#集群
hostname: eureka7002.com
client:
#false表示不向注册中心注册自己
register-with-eureka: false
#false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
fetch-registry: false
service-url:
#设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址
#单机版
# defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
#集群
defaultZone: http://eureka7001.com:7001/eureka/, http://eureka7003.com:7003/eureka/

7003的yml

server:
port: 7003 eureka:
instance:
#eureka服务端的实例名称
#单机版
# hostname: localhost
#集群
hostname: eureka7003.com
client:
#false表示不向注册中心注册自己
register-with-eureka: false
#false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
fetch-registry: false
service-url:
#设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址
#单机版
# defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
#集群
defaultZone: http://eureka7001.com:7001/eureka/, http://eureka7002.com:7002/eureka/

6)修改eureka-demo-provider的yml,服务url设置为集群

defaultZone: http://eureka7001.com:7001/eureka/, http://eureka7002.com:7002/eureka/, http://eureka7003.com:7003/eureka/

7)启动测试

依次启动7001,7002,7003,8001,然后在浏览器分别访问eureka7001.com:7001,eureka7002.com:7002,eureka7003.com:7003。会发现他们都和另外两个服务器连接着。如访问7003的:

1.4.6CAP

1)定义

C:(Consistency)强一致性

A:(Availability)可用性

P:(Partition tolerance)分区容错性

2)3进2

任何的分布式系统只能同时满足以上3个中的2个。

1.4.7Eureka与Zookeeper的区别

Zookeeper保证CP,而Eureka保证AP,各个节点都是平等的。因此Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,不会像Zookeeper使得整个注册服务瘫痪。

1.4.8Eureka服务发现Discovery

它的功能就是获取注册进eureka中的微服务的信息。

1)修改eureka-demo-provider模块的controller,在里面添加获取服务信息的方法

 @GetMapping("/discovery")
public Object discovery(){
//获取注册的服务列表信息
List<String> services = discoveryClient.getServices();
//根据服务名称获取实例列表信息
List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-EUREKA-DEMO-PROVIDER"); Map<String,Object> map=new HashMap<>();
map.put("服务列表",services);
map.put("实例列表",instances);
return map;
}

2)在启动类上添加注解@EnableDiscoveryClient

@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
public class ProviderMain8001 {
public static void main(String[] args) {
SpringApplication.run(ProviderMain8001.class, args);
}
}

3)启动测试

先启动eureka集群,然后启动8001,最后启动80,在浏览器输入即可看到服务的相关信息,包括服务列表,实例列表,主机ip等。

2.Zookeeper

zookeeper也可以做注册中心。这里默认已经在linux上安装好了Zookeeper服务并允许外部访问。

源代码:https://github.com/zhongyushi-git/cloud-zookeeper-demo.git

2.1项目搭建

创建maven工程cloud-zookeeper-demo,导入依赖

 <!--统一管理jar包版本-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<junit.version>4.12</junit.version>
<lombok.version>1.16.18</lombok.version>
<log4j.version>1.2.17</log4j.version>
<mysql.version>5.1.47</mysql.version>
<druid.version>1.1.16</druid.version>
<mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version>
</properties> <!-- 依赖管理,父工程锁定版本-->
<dependencyManagement>
<dependencies>
<!--spring boot 2.2.2-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud Hoxton.SR1-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud alibaba 2.1.0-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!--druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.spring.boot.version}</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<!--log4j-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
</dependencies>
</dependencyManagement> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<addResources>true</addResources>
</configuration>
</plugin>
</plugins>
</build>

创建子模块cloud-api-common,用于存放公共类

子模块先导入依赖

 <dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>

创建包com.zys.cloud.entity,然后创建User类

package com.zys.cloud.entity;

import lombok.*;

@Getter
@Setter
@ToString
public class User {
private Long id;
private String name;
private String phone;
}

2.2服务提供者注册

1)创建子模块cloud-zk-provider,导入依赖

 <dependencies>
<!--web-->
<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>com.zys.cloud</groupId>
<artifactId>cloud-api-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<!--mysql-connector-java-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--springboot整合zookeeper客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
<!--先排除自带的zookeeper3.5.3-->
<exclusions>
<exclusion>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--添加zookeeper3.4.14版本-->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.14</version>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>

2)配置yml

server:
port: 8001 spring:
application:
name: cloud-provider
datasource:
type: com.alibaba.druid.pool.DruidDataSource #当前数据源操作类型
driver-class-name: org.gjt.mm.mysql.Driver #mysql驱动包
url: jdbc:mysql://localhost:3306/db2020?useUnicode=true&characterEncoding-utr-8&useSSL=false
username: root
password: 123456
#配置zookeeper
cloud:
zookeeper:
connect-string: 101.37.23.71:2181 mybatis:
mapper-locations: classpath:mapper/*.xml
#所有Entity别名类所在包
type-aliases-package: com.zys.cloud.entity

3)创建包com.zys.cloud,然后创建controller、service等包及类用于数据测试,详见源代码

4)创建启动类并添加注解@EnableDiscoveryClient

package com.zys.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient; //@EnableDiscoveryClient用于向consul或Zookeeper作为注册中心时注册服务 @SpringBootApplication
@EnableDiscoveryClient
public class ProviderMain8001 {
public static void main(String[] args) {
SpringApplication.run(ProviderMain8001.class, args);
}
}

@EnableDiscoveryClient用于向consul或Zookeeper作为注册中心时注册服务

5)启动测试

启动服务后,在浏览器输入http://127.0.0.1:8001/user/get/1,数据可以正常访问。打开连接linux的软件,启动Zookeeper客户端。

查看注册的服务

ls /

查看注册的具体服务

ls /services
ls /services/cloud-provider

获取服务的具体信息

ls /services/cloud-provider/d619cc0e-d460-454a-8238-5ac87c0dd3f8

需要注意的是cloud-provider是注册的时候的服务名称,后面的字符串是生成的服务的id。这个服务节点是临时节点。至此服务提供者已注册到Zookeeper中。

2.3服务消费者注册

1)创建子模块cloud-zk-consumer,导入依赖

<dependencies>
<!--web-->
<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>com.zys.cloud</groupId>
<artifactId>cloud-api-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--springboot整合zookeeper客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
<!--先排除自带的zookeeper3.5.3-->
<exclusions>
<exclusion>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--添加zookeeper3.4.14版本-->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.14</version>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency> </dependencies>

2)配置yml

server:
port: 80 spring:
application:
name: cloud-consumer
#配置zookeeper
cloud:
zookeeper:
connect-string: 101.37.23.71:2181

3)创建包com.zys.cloud,然后创建controller和config包及类用于数据测试,详见源代码

4)创建启动类并添加注解@EnableDiscoveryClient

package com.zys.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication
@EnableDiscoveryClient
public class ConsumerMain80 {
public static void main(String[] args) {
SpringApplication.run(ConsumerMain80.class, args);
}
}

@EnableDiscoveryClient用于向consul或Zookeeper作为注册中心时注册服务

5)启动测试

启动服务后,在浏览器输入http://127.0.0.1/consumer/get/1,数据可以正常访问。也是可以在Zookeeper中进行查看的。

3.Consul

是一套开源的分布式服务发现和配置管理系统,提供了服务治理、配置中心、控制总线等功能。它拥有一个web的可视化界面。

3.1下载与安装

下载网站:https://www.consul.io/downloads.html
下载对应的版本后解压,然后打开cmd,输入consul agent -dev来以开发者模式启动
测试:在浏览器输入localhost:8500就可以看到consul控制界面

3.2项目开发

源代码:https://github.com/zhongyushi-git/cloud-consul.git

3.2.1环境搭建

为了简单化,本项目不操作数据库,使用简单的方式来做练习。

新建maven的父工程cloud-consul,导入依赖

  <!--统一管理jar包版本-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<junit.version>4.12</junit.version>
<log4j.version>1.2.17</log4j.version>
</properties> <!-- 依赖管理,父工程锁定版本-->
<dependencyManagement>
<dependencies>
<!--spring boot 2.2.2-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud Hoxton.SR1-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<!--log4j-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
</dependencies>
</dependencyManagement> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<addResources>true</addResources>
</configuration>
</plugin>
</plugins>
</build>

3.2.2服务提供者注册

1)新建maven的子工程cloud-consul-provider8001,导入依赖

  <!--统一管理jar包版本-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<junit.version>4.12</junit.version>
<log4j.version>1.2.17</log4j.version>
</properties> <!-- 依赖管理,父工程锁定版本-->
<dependencyManagement>
<dependencies>
<!--spring boot 2.2.2-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud Hoxton.SR1-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<!--log4j-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
</dependencies>
</dependencyManagement> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<addResources>true</addResources>
</configuration>
</plugin>
</plugins>
</build>

2)配置yml

server:
port: 8001 spring:
application:
name: cloud-consul-provider
cloud:
consul:
host: localhost
port: 8500
discovery:
service-name: ${spring.application.name}

3)创建包com.zys.cloud,在包下创建启动类并加@EnableDiscoveryClient注解

package com.zys.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication
@EnableDiscoveryClient
public class ConsulProviderMain8001 {
public static void main(String[] args) {
SpringApplication.run(ConsulProviderMain8001.class,args);
}
}

4)创建controller接口

package com.zys.cloud.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import java.util.Date;
import java.util.UUID; @RestController
@RequestMapping("/provider")
public class PaymentController { @Value("${server.port}")
private String serverPort; @GetMapping("/consul")
public String paymentConsul(){
return "consul message:服务端口号:"+serverPort+"\t 现在时间:"+ new Date().toString();
}
}

5)启动测试

先启动consul服务,然后启动8001,在浏览器输入http://localhost:8500/可以看到提供者服务注册进来了。访问http://127.0.0.1:8001/provider/consul也是正常的。

3.2.3服务消费者注册

1)新建maven的子工程cloud-consul-consumer80,导入依赖

<dependencies>
<!--web-->
<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>
<!--consul-server-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
</dependencies>

2)配置yml

server:
port: 80 spring:
application:
name: cloud-consul-consumer
cloud:
consul:
host: localhost
port: 8500
discovery:
service-name: ${spring.application.name}

3)创建包com.zys.cloud,在包下创建启动类并加注解@EnableDiscoveryClient

package com.zys.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication
@EnableDiscoveryClient
public class ConsulConsumerMain80 {
public static void main(String[] args) {
SpringApplication.run(ConsulConsumerMain80.class,args);
}
}

4)bean配置

package com.zys.cloud.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate; @Configuration
public class ApplicationContextConfig {
@Bean
@LoadBalanced
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}

5)创建controller接口

package com.zys.cloud.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource; @RestController
public class OrderConsulController { public static final String INVOKE_URL = "http://cloud-consul-provider"; @Resource
private RestTemplate restTemplate; @GetMapping("/consumer/consul")
public String paymentInfo(){
String result = restTemplate.getForObject(INVOKE_URL+"/provider/consul",String.class);
return result;
}
}

6)启动测试

先启动consul服务,然后启动8001,最后启动80,在浏览器输入http://localhost:8500/可以看到消费者服务注册进来了。访问http://127.0.0.1/consumer/consul也是正常的。

3.3Eureka、Zookeeper与Consul的异同

组件名 所用语言 CAP 对外暴露接口
Eureka java AP HTTP
Zookeeper java CP 客户端
Consul go CP HTTP/DNS

SpringCloud之服务注册中心的更多相关文章

  1. springcloud 笔记-服务注册中心

    1.搭建springcloud服务注册中心需要添加eureka的依赖: <?xml version="1.0" encoding="UTF-8"?> ...

  2. SpringCloud + Consul服务注册中心 + gateway网关

    1  启动Consul 2  创建springcloud-consul项目及三个子模块 2.1 数据模块consul-producer 2.2 数据消费模块consul-consumer 2.3 ga ...

  3. SpringCloud的服务注册中心(三) - 进一步了解 Eureka

    一.服务治理参与者 服务注册中心: eureka-server 服务提供者:HELLO-SERVICE 服务消费者 :HELLO-CONSUMER 很多时候,客户端既是服务提供者又是服务消费者,-&g ...

  4. SpringCloud的服务注册中心(四)- 高可用服务注册中心的搭建

    一.双 服务注册注册中心 1.服务注册中心的服务端 - EurekaServer 1.1.EurekaServer1 String.application.name=eureka-server ser ...

  5. SpringCloud的服务注册中心(一)

    一.概念和定义 1.服务治理:服务注册与服务发现 服务注册中心,提供服务治理功能,用来实现各个微服务实例的自动注册与发现. 服务注册与发现对于微服务系统来说非常重要.有了服务发现与注册,维护人员就不需 ...

  6. springcloud搭建服务注册中心与服务发现

    1.创建服务注册中心 创建一个普通的Spring Boot工程 首先我们需要创建一个普通的Spring Boot工程,命名为eureka-server,普通到什么程度呢?就是一个starter都不需要 ...

  7. SpringCloud(四):服务注册中心Eureka Eureka高可用集群搭建 Eureka自我保护机制

    第四章:服务注册中心 Eureka 4-1. Eureka 注册中心高可用集群概述在微服务架构的这种分布式系统中,我们要充分考虑各个微服务组件的高可用性 问题,不能有单点故障,由于注册中心 eurek ...

  8. SpringCloud的服务注册中心(二)注册中心服务端和两个微服务应用客户端

    一.构建EurekaServer工程 1.pom.xml 2.application.yml 3. EurekaServerApp.java 4.启动EurekaServer 二.构建部署 Eurek ...

  9. SpringCloud之服务注册-eureka

    类似于DUBBO 的zookeeper, SpringCloud本身提供一套服务注册中心--eureka 与zookeeper的区别在于 1:zookeeper本身就是一个应用,安装即可用:eurek ...

随机推荐

  1. DedeCMS程序使用拼音首字母做栏目名称的方法

    Dedecms织梦程序默认使用拼音为保存目录的时候使用的是中文全拼,当遇到栏目名称比较长的时候目录名称看起来有点冗长,这时候大多数站长喜欢使用拼音首字母作为栏目的保存目录,那么就需要修改 dede/c ...

  2. Flink-v1.12官方网站翻译-P026-State Backends

    状态后台 Flink提供了不同的状态后端,指定状态的存储方式和位置. 状态可以位于Java的堆上或离堆.根据你的状态后端,Flink还可以为应用程序管理状态,这意味着Flink处理内存管理(必要时可能 ...

  3. Flink-v1.12官方网站翻译-P023-The Broadcast State Pattern

    广播状态模式 在本节中,您将了解如何在实践中使用广播状态.请参考状态流处理,了解状态流处理背后的概念. 提供的API 为了展示所提供的API,我们将在介绍它们的全部功能之前先举一个例子.作为我们的运行 ...

  4. springboot源码解析-管中窥豹系列之web服务器(七)

    一.前言 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...

  5. HarmonyOS应用开发-Component体系介绍(一)

    目录: 1. Component的内部类/接口 2. Component方法简介 3.总结 在HarmonyOS的UI框架中,Component为用户界面提供基本组件,Component类位于ohos ...

  6. Codeforces Round #655 (Div. 2) D. Omkar and Circle

    题目链接:https://codeforces.com/contest/1372/problem/D 题意 给出奇数个数围成的环,每次可以将一个数替换为相邻两个数的和并删除相邻的两个数,问最后余下的数 ...

  7. HDU 6880 Permutation Counting dp

    题意: 给你一个n和一个长度为n-1的由0/1构成的b序列 你需要从[1,n]中构造出来一个满足b序列的序列 我们设使用[1,n]构成的序列为a,那么如果ai>ai+1,那么bi=1,否则bi= ...

  8. C# 之 dynamic

    C#中的dynamic用于避免编译时类型检查,编译器在运行时获取类型. dynamic无法使用VisualStudio的intelliSense(智能感知),即调用dynamic修饰的对象的方法或字段 ...

  9. 二进制安装kubernetes(二) kube-apiserver组件安装

    根据架构图,我们的apiserver部署在hdss7-21和hdss7-22上: 首先在hdss7-200上申请证书并拷贝到21和22上: 创建证书文件: # cd /opt/certs # vi c ...

  10. cin的用法

    int val=0; cin>>val; 上述程序先定义了一个整型数据val,通过cin读取数据放在val中,如果输入的整型数据,则读取成功,返回的是>>左侧的对象,也就是is ...