springboot+consul注册中心实现分布式
Consul 是 HashiCorp 公司推出的开源工具,用于实现分布式系统的服务发现与配置。Consul 是分布式的、高可用的、 可横向扩展的。
特点:
服务发现: Consul 提供了通过 DNS 或者 HTTP 接口的方式来注册服务和发现服务。一些外部的服务通过 Consul 很容易的找到它所依赖的服务。
健康检测: Consul 的 Client 提供了健康检查的机制,可以通过用来避免流量被转发到有故障的服务上。
Key/Value 存储: 应用程序可以根据自己的需要使用 Consul 提供的 Key/Value 存储。 Consul 提供了简单易用的 HTTP 接口,结合其他工具可以实现动态配置、功能标记、领袖选举等等功能。
多数据中心: Consul 支持开箱即用的多数据中心. 这意味着用户不需要担心需要建立额外的抽象层让业务扩展到多个区域。
下载地址https://www.consul.io/downloads.html
解压后consul agent -dev运行
运行成功后在浏览器输入http://localhost:8500/出现以下内容表示成功
新建生产者项目
pom.xml文件
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-consul-discovery -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.at.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
yml文件
#端口号
server:
port: 8006
#数据库链接设置
spring:
application:
# 应用名称
name: consul-provider-payment
cloud:
consul:
host: localhost
port: 8500
discovery:
service-name: ${spring.application.name}
heartbeat:
enabled: true
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/consul?useUnicode=true&characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull&useSSL=false
username: root
password: root
mybatis:
mapper-locations: classpath*:mapper/*.xml
type-aliases-package: com.at.springcloud.entities
主方法
@SpringBootApplication
@EnableDiscoveryClient
public class PaymentMain {
public static void main(String[] args) {
SpringApplication.run(PaymentMain.class,args);
}
}
DAO层
@Mapper
@Component
public interface PaymentDao {
public int create(Payment payment);
}
Service层
public interface PaymentService {
public int create(Payment payment);
}
ServiceImpl层
@Service
public class PaymentServiceImpl implements PaymentService {
@Autowired
private PaymentDao paymentDao;
@Override
public int create(Payment payment) {
return paymentDao.create(payment);
}
}
controller层
@RestController
@Slf4j
public class PaymentController {
@Value("${server.port}")
private String serverport;
@Autowired
private PaymentService paymentService;
@RequestMapping("/payment/consul/create")
public CommonResult<Payment> create(@RequestBody Payment payment){
int result=paymentService.create(payment);
CommonResult commonResult=new CommonResult();
if(result>0){
commonResult.setCode(200);
commonResult.setMessage("插入成功"+serverport);
commonResult.setData("成功插入条数为"+result);
}else {
commonResult.setCode(400);
commonResult.setMessage("插入失败");
commonResult.setData(null);
}
return commonResult;
}
//不需要添加@RequestBody因为消费者端将传过来的数据进行了改造不是以json字符串的形式和上面那个意思是一样的只不过上面那个需要接收json
@RequestMapping("/payment/consul/create1")
public CommonResult<Payment> create1(Payment payment){
int result=paymentService.create(payment);
CommonResult commonResult=new CommonResult();
if(result>0){
commonResult.setCode(200);
commonResult.setMessage("插入成功"+serverport);
commonResult.setData("成功插入条数为"+result);
}else {
commonResult.setCode(400);
commonResult.setMessage("插入失败");
commonResult.setData(null);
}
return commonResult;
}
@RequestMapping("/payment/consul")
public String paymentzk(){
return "springcloud with consul"+serverport+"\t"+ UUID.randomUUID().toString();
}
}
mapper.xml
<mapper namespace="com.at.springcloud.dao.PaymentDao">
<!-- 如果插入成功返回主键 keyProperty 为正数,否则失败返回非正数 -->
<insert id="create" parameterType="Payment" useGeneratedKeys="true" keyProperty="id">
insert into payment(serial) values (#{serial});
</insert>
运行项目打开浏览器如何显示如下图表示已经成功将生产者注册到consul中
新建消费者
pom.xml文件
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-consul-discovery -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.at.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
yml文件
#端口号
server:
port: 80
#数据库链接设置
spring:
application:
# 应用名称
name: consul-consumer-payment
cloud:
consul:
host: localhost
port: 8500
discovery:
service-name: ${spring.application.name}
heartbeat:
enabled: true
RestTemplate工具方法
@Configuration
public class ApplicationContextConfig {
@Bean
//使用轮询的负载均衡 @LoadBalanced
@LoadBalanced
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
controller类
@RestController
@Slf4j
public class OrderConsulController {
@Autowired
private RestTemplate restTemplate;
public static final String INVOME_URL = "http://consul-provider-payment";
@RequestMapping("/consumer/payment/consul")
public String paymentzk(){
String forObject = restTemplate.getForObject(INVOME_URL + "/payment/consul", String.class);
return forObject;
}
//需要生产者方法上添加@RequestBody,因为方法传过去的是json串
@RequestMapping("/consumer/payment/consul/create")
public CommonResult<Payment> create(@RequestBody Payment payment){
return restTemplate.postForObject(INVOME_URL+"/payment/consul/create",payment,CommonResult.class);
}
//不需要生产者添加@RequestBody
@RequestMapping("/consumer/payment/consul/create1")
public CommonResult create1(@RequestBody Payment payment){
//下面这两句是必须添加到否则不生效
MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
params.add("serial", payment.getSerial());
return restTemplate.postForEntity(INVOME_URL+"/payment/consul/create1",params,CommonResult.class).getBody();
}
}
新建成功后运行程序,打开浏览器如果出现consul-consumer-payment说明已经将消费者注册到consul中
然后运行消费者调用生产者的方法如果有数据就证明程序正确。