SpringCloud Eureka实战
来源:互联网 发布:c语言99个例题 编辑:程序博客网 时间:2024/06/06 03:13
一 开发环境
MacOS10.12+JDK8u133+Git2.10+Maven3.3.9+Tomcat8.5+MySQL5.7
SpringBoot1.5.4.RELEASE+SpringCloud Dalston.SRL
二 搭建SpringCloud Eureka注册中心(单点)
2.1 实现单点的Eureka注册中心
pom.xml
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.ekeyfund.springcloud</groupId> <artifactId>springcloud-eureka-server</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>springcloud-eureka-server</name> <description>SpringCloud Eureka Server</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <spring-cloud.version>Dalston.SR1</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </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> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build></project>
application.properties
##定义注册中心服务的端口server.port=8888#定义注册中心服务的ipeureka.instance.hostname=127.0.0.1#不向注册中心注册自己eureka.client.register-with-eureka=false#注册中心的职责就是维护服务的实例,并不需要检索服务eureka.client.fetch-registry=false## 注册中心的访问地址eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
启动类
package com.ekeyfund.springcloud;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;@EnableEurekaServer //启用Eureka 注册中心@SpringBootApplicationpublic class SpringcloudEurekaServerApplication { public static void main(String[] args) { SpringApplication.run(SpringcloudEurekaServerApplication.class, args); }}
2.2 访问Eureka注册中心
访问地址:http://127.0.0.1:8888/eureka/
访问界面
三 实现服务注册提供者
说明:为了保证项目的完整性,这里会使用SpringBoot的JPA,Web模块提供一个完整的RestFulAPI的例子。
3.1 实体
包含User,Department,Role三个实体类
package com.ekeyfund.springcloud.entity;import com.fasterxml.jackson.annotation.JsonBackReference;import org.apache.commons.lang3.builder.ToStringBuilder;import org.springframework.format.annotation.DateTimeFormat;import javax.persistence.*;import java.util.Date;import java.util.List;/** * User Entity * * @author Liuguanglei liugl@ekeyfund.com * @create 2017-06-下午2:32 */@Entity@Table(name = "springboot_user")public class User { @Id @Column(name = "user_id") @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "user_name") private String name; @Column(name = "user_password") private String password; @Column(name = "user_create_date") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date createDate; @ManyToOne @JoinColumn(name = "department_id") @JsonBackReference private Department department; @ManyToMany(cascade = {},fetch = FetchType.EAGER) @JoinTable(name = "springboot_user_role",joinColumns = {@JoinColumn(name="user_id")}, inverseJoinColumns = {@JoinColumn(name = "role_id")} ) private List<Role> roleList; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Date getCreateDate() { return createDate; } public void setCreateDate(Date createDate) { this.createDate = createDate; } public Department getDepartment() { return department; } public void setDepartment(Department department) { this.department = department; } public List<Role> getRoleList() { return roleList; } public void setRoleList(List<Role> roleList) { this.roleList = roleList; } @Override public String toString() { return new ToStringBuilder(this) .append("id", id) .append("name", name) .append("password", password) .append("createDate", createDate) .append("department", department) .append("roleList", roleList) .toString(); }}
Department.java
package com.ekeyfund.springcloud.entity;import org.apache.commons.lang3.builder.ToStringBuilder;import org.hibernate.annotations.CacheConcurrencyStrategy;import javax.persistence.*;/** * Department Entity * * @author Liuguanglei liugl@ekeyfund.com * @create 2017-06-下午2:31 */@Entity@Table(name = "springboot_department")@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)public class Department { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "department_id") private Long id; @Column(name = "department_name") private String name; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return new ToStringBuilder(this) .append("id", id) .append("name", name) .toString(); }}
Role.java
package com.ekeyfund.springcloud.entity;import javax.persistence.*;/** * Role Entity * * @author Liuguanglei liugl@ekeyfund.com * @create 2017-06-下午2:36 */@Entity@Table(name = "springboot_role")public class Role { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "role_id") private Long id; @Column(name = "role_name") private String name; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return new org.apache.commons.lang3.builder.ToStringBuilder(this) .append("id", id) .append("name", name) .toString(); }}
3.2 持久层
主要是UserRepository和DepartmentRepository
UserRepository.java
package com.ekeyfund.springcloud.repository;import com.ekeyfund.springcloud.entity.User;import org.springframework.data.jpa.repository.JpaRepository;import org.springframework.stereotype.Repository;import java.util.Collection;import java.util.Date;import java.util.List;/** * User Repository * * @author Liuguanglei liugl@ekeyfund.com * @create 2017-06-下午2:54 */@Repositorypublic interface UserRepository extends JpaRepository<User,Long>{ /** * and * @param id * @param name * @return */ User findByIdAndName(Long id, String name); User findByNameAndPassword(String name, String password); /** * or * @param id * @param name * @return */ User findByIdOrName(Long id, String name); /** * between * @param start * @param end * @return */ List<User> findByCreateDateBetween(Date start, Date end); /** * lessThan * @param start * @return */ List<User> getByCreateDateLessThan(Date start); /** * Greater Than * @param start * @return */ List<User> findByCreateDateGreaterThan(Date start); /** * is null * @return */ List<User> findByNameIsNull(); /** * in * @param nameList * @return */ List<User> findByNameIn(Collection<String> nameList);}
DepartmentRepository.java
package com.ekeyfund.springcloud.repository;import com.ekeyfund.springcloud.entity.Department;import org.springframework.data.jpa.repository.JpaRepository;import org.springframework.stereotype.Repository;/** * Created by tony on 2017/6/19. */@Repositorypublic interface DepartmentRepository extends JpaRepository<Department,Long> {}
3.3 业务逻辑层
主要包含UserService,UserServiceImpl,DepartmentService,DepartmentServiceImpl
UserService.java
package com.ekeyfund.springcloud.service;import com.ekeyfund.springcloud.entity.User;import java.util.List;/** * Created by tony on 2017/6/19. */public interface UserService { /** * 登录 * @param name * @param password * @return */ public User login(String name, String password); /** * 注册 * @param user * @return */ public User register(User user); /** * 注销 * @param user * @return */ void writeOff(User user); /** * 当前用户是否已经存在 * @param user * @return */ boolean isExists(User user); List<User> getAllUser(); User getUserById(Long id);}
UserServiceImpl.java
package com.ekeyfund.springcloud.service.impl;import com.ekeyfund.springcloud.entity.User;import com.ekeyfund.springcloud.repository.UserRepository;import com.ekeyfund.springcloud.service.UserService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import javax.transaction.Transactional;import java.util.List;/** * User Service Impl * * @author Liuguanglei liugl@ekeyfund.com * @create 2017-06-下午3:34 */@Service@Transactionalpublic class UserServiceImpl implements UserService { @Autowired private UserRepository userRepository; @Override public User login(String name, String password) { return userRepository.findByNameAndPassword(name,password); } @Override public User register(User user) { return userRepository.save(user); } @Override public void writeOff(User user) { userRepository.delete(user); } @Override public boolean isExists(User user) { return userRepository.findOne(user.getId())!=null?true:false; } @Override public List<User> getAllUser() { return userRepository.findAll(); } @Override public User getUserById(Long id) { return userRepository.findOne(id); }}
DepartmentService.java
package com.ekeyfund.springcloud.service;import com.ekeyfund.springcloud.entity.Department;/** * Created by tony on 2017/6/19. */public interface DepartmentService { Department saveDepartment(Department department); Department getDepartmentById(Long id);}
DepartmentServiceImpl.java
package com.ekeyfund.springcloud.service.impl;import com.ekeyfund.springcloud.entity.Department;import com.ekeyfund.springcloud.repository.DepartmentRepository;import com.ekeyfund.springcloud.service.DepartmentService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import javax.transaction.Transactional;/** * Department Impl * * @author Liuguanglei liugl@ekeyfund.com * @create 2017-06-下午3:12 */@Transactional@Servicepublic class DepartmentImpl implements DepartmentService { @Autowired private DepartmentRepository departmentRepository; @Override public Department saveDepartment(Department department) { return departmentRepository.save(department); } @Override public Department getDepartmentById(Long id) { return departmentRepository.findOne(id); }}
3.4 Controller
UserController.java
package com.ekeyfund.springcloud.controller;import com.ekeyfund.springcloud.entity.User;import com.ekeyfund.springcloud.service.UserService;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.cloud.client.ServiceInstance;import org.springframework.cloud.client.discovery.DiscoveryClient;import org.springframework.web.bind.annotation.*;import java.util.Date;import java.util.List;/** * UserController * Restful API * @author Liuguanglei liugl@ekeyfund.com * @create 2017-06-下午11:24 */@RestControllerpublic class UserController { private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(UserController.class); @Autowired private DiscoveryClient discoveryClient; @Autowired private UserService userService; @RequestMapping(value = "/user/list",method = RequestMethod.GET) public List<User> list(){ List<ServiceInstance> serviceInstanceList= discoveryClient.getInstances("user-service"); ServiceInstance instance=discoveryClient.getLocalServiceInstance(); LOGGER.info("call user/list service host is "+instance.getHost()+"service_id is "+instance.getServiceId()); return userService.getAllUser(); } @RequestMapping(value = "/user/register",method = RequestMethod.POST) public String register(@ModelAttribute User user){ User result =userService.register(user); return result!=null?"success":"fail"; } @RequestMapping(value = "/user/get/{id}") public User get(@PathVariable Long id){ return userService.getUserById(id); } @RequestMapping(value = "/user/update/{id}",method = RequestMethod.PUT) public String update(@PathVariable Long id,@ModelAttribute User user){ User updatedUser =userService.getUserById(id); updatedUser.setName(user.getName()); updatedUser.setPassword(user.getPassword()); updatedUser.setCreateDate(new Date()); User result= userService.register(updatedUser); return result!=null?"success":"fail"; } @RequestMapping(value = "/user/delete/{id}",method = RequestMethod.DELETE) public String delete(@PathVariable Long id){ User user =new User(); user.setId(id); userService.writeOff(user); return "success"; }}
3.5 Configuration
JPAConfiguration.java
package com.ekeyfund.springcloud.configuration;import com.alibaba.druid.pool.DruidDataSource;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Value;import org.springframework.boot.autoconfigure.domain.EntityScan;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.core.Ordered;import org.springframework.core.annotation.Order;import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;import org.springframework.data.jpa.repository.config.EnableJpaRepositories;import org.springframework.orm.jpa.JpaTransactionManager;import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;import org.springframework.orm.jpa.vendor.HibernateJpaDialect;import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;import org.springframework.transaction.PlatformTransactionManager;import org.springframework.transaction.annotation.EnableTransactionManagement;import javax.persistence.EntityManagerFactory;import javax.sql.DataSource;import java.sql.SQLException;import java.util.Properties;/** * JPA Persistence Configuration * * @author Liuguanglei liugl@ekeyfund.com * @create 2017-06-上午11:26 */@Order(Ordered.HIGHEST_PRECEDENCE)@Configuration@EnableTransactionManagement(proxyTargetClass = true) //启用JPA的事务管理@EnableJpaRepositories(basePackages = "com.ekeyfund.springcloud.repository" )//启用JPA资源库并指定资源库接口位置@EntityScan(basePackages = "com.ekeyfund.springcloud.entity")//指定实体的位置public class JPAPersistenceConfiguration { private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(JPAPersistenceConfiguration.class); /*******************数据库和连接池配置信息,读取application.properties文件的属性值****************************/ @Value("${spring.datasource.driver-class-name}") private String driverClass; @Value("${spring.datasource.username}") private String userName; @Value("${spring.datasource.password}") private String password; @Value("${spring.datasource.url}") private String url; @Value("${spring.datasource.initialSize}") private int initialSize; @Value("${spring.datasource.minIdle}") private int minIdle; @Value("${spring.datasource.maxActive}") private int maxActive; @Value("${spring.datasource.maxWait}") private long maxWait; @Value("${spring.datasource.timeBetweenEvictionRunsMillis}") private long timeBetweenEvictionRunsMillis; @Value("${spring.datasource.minEvictableIdleTimeMillis}") private long minEvictableIdleTimeMillis; @Value("${spring.datasource.filters}") private String filters; @Value("${spring.datasource.connectionProperties}") private String connectionProperties; @Bean(name = "druidDataSource",initMethod = "init",destroyMethod = "close") public DataSource dataSource(){ DruidDataSource druidDataSource =new DruidDataSource(); druidDataSource.setDriverClassName(driverClass); druidDataSource.setUsername(userName); druidDataSource.setPassword(password); druidDataSource.setUrl(url); druidDataSource.setInitialSize(initialSize); druidDataSource.setMinIdle(minIdle); druidDataSource.setMaxActive(maxActive); druidDataSource.setMaxWait(maxWait); druidDataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); druidDataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); druidDataSource.setConnectionProperties(connectionProperties); try { druidDataSource.setFilters(filters); } catch (SQLException e) { LOGGER.error("build datasoure exception ",e.getMessage()); } return druidDataSource; } @Bean(name = "entityManagerFactory") public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource druidDataSource){ LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean =new LocalContainerEntityManagerFactoryBean(); localContainerEntityManagerFactoryBean.setDataSource(druidDataSource); localContainerEntityManagerFactoryBean.setPackagesToScan("com.ekeyfund.springcloud.entity"); localContainerEntityManagerFactoryBean.setJpaProperties(buildHibernateProperties()); localContainerEntityManagerFactoryBean.setJpaDialect(new HibernateJpaDialect()); localContainerEntityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter(){ { setDatabase(org.springframework.orm.jpa.vendor.Database.MYSQL); setDatabasePlatform("org.hibernate.dialect.MySQL5Dialect"); } }); return localContainerEntityManagerFactoryBean; } @Bean public PlatformTransactionManager transactionManager(DataSource druidDataSource, EntityManagerFactory entityManagerFactory){ JpaTransactionManager jpaTransactionManager=new JpaTransactionManager(); jpaTransactionManager.setDataSource(druidDataSource); jpaTransactionManager.setEntityManagerFactory(entityManagerFactory); return jpaTransactionManager; } @Bean PersistenceExceptionTranslationPostProcessor persistenceExceptionTranslationPostProcessor(){ return new PersistenceExceptionTranslationPostProcessor(); } protected Properties buildHibernateProperties(){ Properties hibernateProperties =new Properties(); hibernateProperties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect"); hibernateProperties.setProperty("hibernate.hbm2ddl.auto","update"); hibernateProperties.setProperty("hibernate.show_sql", "false"); hibernateProperties.setProperty("hibernate.use_sql_comments", "false"); hibernateProperties.setProperty("hibernate.format_sql", "true"); hibernateProperties.setProperty("hibernate.generate_statistics", "false"); hibernateProperties.setProperty("javax.persistence.validation.mode", "none"); //Audit History flags hibernateProperties.setProperty("org.hibernate.envers.store_data_at_delete", "true"); hibernateProperties.setProperty("org.hibernate.envers.global_with_modified_flag", "true"); hibernateProperties.setProperty("hibernate.cache.use_second_level_cache", "true"); hibernateProperties.setProperty("hibernate.cache.region.factory_class", "org.hibernate.cache.ehcache.EhCacheRegionFactory"); hibernateProperties.setProperty("hibernate.cache.use_query_cache", "true"); return hibernateProperties; }}
3.6 配置文件
主要包含application.properties和logback-spring.xml以及ehcache.xml
application.properties
##DataSource Config##\u6570\u636e\u5e93\u8fde\u63a5\u6c60\u4fe1\u606f\u914d\u7f6espring.datasource.type=com.alibaba.druid.pool.DruidDataSourcespring.datasource.driver-class-name=com.mysql.jdbc.Driverspring.datasource.url=jdbc:mysql://127.0.0.1:3306/springboot?characterEncoding=utf-8spring.datasource.username=rootspring.datasource.password=guanglei# \u4e0b\u9762\u4e3a\u8fde\u63a5\u6c60\u7684\u8865\u5145\u8bbe\u7f6e\uff0c\u5e94\u7528\u5230\u4e0a\u9762\u6240\u6709\u6570\u636e\u6e90\u4e2d# \u521d\u59cb\u5316\u5927\u5c0f\uff0c\u6700\u5c0f\uff0c\u6700\u5927spring.datasource.initialSize=5spring.datasource.minIdle=5spring.datasource.maxActive=20# \u914d\u7f6e\u83b7\u53d6\u8fde\u63a5\u7b49\u5f85\u8d85\u65f6\u7684\u65f6\u95f4spring.datasource.maxWait=60000# \u914d\u7f6e\u95f4\u9694\u591a\u4e45\u624d\u8fdb\u884c\u4e00\u6b21\u68c0\u6d4b\uff0c\u68c0\u6d4b\u9700\u8981\u5173\u95ed\u7684\u7a7a\u95f2\u8fde\u63a5\uff0c\u5355\u4f4d\u662f\u6beb\u79d2spring.datasource.timeBetweenEvictionRunsMillis=60000# \u914d\u7f6e\u4e00\u4e2a\u8fde\u63a5\u5728\u6c60\u4e2d\u6700\u5c0f\u751f\u5b58\u7684\u65f6\u95f4\uff0c\u5355\u4f4d\u662f\u6beb\u79d2spring.datasource.minEvictableIdleTimeMillis=300000spring.datasource.validationQuery=SELECT 1 FROM DUALspring.datasource.testWhileIdle=truespring.datasource.testOnBorrow=falsespring.datasource.testOnReturn=false# \u6253\u5f00PSCache\uff0c\u5e76\u4e14\u6307\u5b9a\u6bcf\u4e2a\u8fde\u63a5\u4e0aPSCache\u7684\u5927\u5c0fspring.datasource.poolPreparedStatements=truespring.datasource.maxPoolPreparedStatementPerConnectionSize=20# \u914d\u7f6e\u76d1\u63a7\u7edf\u8ba1\u62e6\u622a\u7684filters\uff0c\u53bb\u6389\u540e\u76d1\u63a7\u754c\u9762sql\u65e0\u6cd5\u7edf\u8ba1\uff0c'wall'\u7528\u4e8e\u9632\u706b\u5899spring.datasource.filters=stat,wall,log4j# \u901a\u8fc7connectProperties\u5c5e\u6027\u6765\u6253\u5f00mergeSql\u529f\u80fd\uff1b\u6162SQL\u8bb0\u5f55spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000# \u5408\u5e76\u591a\u4e2aDruidDataSource\u7684\u76d1\u63a7\u6570\u636e#spring.datasource.useGlobalDataSourceStat=true# druid \u8bbf\u95ee\u5730\u5740 http://host:port/druid/index.html##Log Configlogging.config=classpath:logback-spring.xml## SpringData JPA Configspring.jpa.database=mysqlspring.jpa.show-sql=truespring.jpa.hibernate.ddl-auto=update#设置服务名称spring.application.name=user-service #指定服务注册中心的地址 ###高可用改造后可以加上多个注册中心的地址eureka.client.service-url.defaultZone=http://127.0.0.1:8888/eureka/,http://127.0.0.1:9999/eureka/#指定服务提供者的端口server.port=8080
logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?><configuration> <!--<include resource="org/springframework/boot/logging/logback/base.xml"/>--> <!-- 项目的appid --> <property name="APP_ID" value="SpringCloud-Eureka-User-Service-Provider"/> <property name="LOG_PATH" value="logs"></property> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss} %-4relative [%thread] %-5level %logger{35} - %msg %n</pattern> </encoder> </appender> <appender name="FILE_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender"> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>DEBUG</level> </filter> <file>${LOG_PATH}/${APP_ID}/access.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${LOG_PATH}/${APP_ID}/access.log.%d{yyyy-MM-dd}.zip </fileNamePattern> <maxHistory>10</maxHistory> </rollingPolicy> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss} %-4relative [%thread] %-5level %logger{35} - %msg%n</pattern> </encoder> </appender> <appender name="FILE_DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender"> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>DEBUG</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> <file>${LOG_PATH}/${APP_ID}/access_debug.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${LOG_PATH}/${APP_ID}/access_debug.log.%d{yyyy-MM-dd}.zip </fileNamePattern> <maxHistory>10</maxHistory> </rollingPolicy> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss} %-4relative [%thread] %-5level %logger{35} - %msg%n</pattern> </encoder> </appender> <appender name="FILE_INFO" class="ch.qos.logback.core.rolling.RollingFileAppender"> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>INFO</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> <file>${LOG_PATH}/${APP_ID}/access_info.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${LOG_PATH}/${APP_ID}/access_info.log.%d{yyyy-MM-dd}.zip </fileNamePattern> <maxHistory>10</maxHistory> </rollingPolicy> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss} %-4relative [%thread] %-5level %logger{35} - %msg%n</pattern> </encoder> </appender> <appender name="FILE_WARN" class="ch.qos.logback.core.rolling.RollingFileAppender"> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>WARN</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> <file>${LOG_PATH}/${APP_ID}/access_warn.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${LOG_PATH}/${APP_ID}/access_warn.log.%d{yyyy-MM-dd}.zip </fileNamePattern> <maxHistory>10</maxHistory> </rollingPolicy> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss} %-4relative [%thread] %-5level %logger{35} - %msg%n</pattern> </encoder> </appender> <appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender"> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>ERROR</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> <file>${LOG_PATH}/${APP_ID}/access_error.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${LOG_PATH}/${APP_ID}/access_error.log.%d{yyyy-MM-dd}.zip </fileNamePattern> <maxHistory>10</maxHistory> </rollingPolicy> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss} %-4relative [%thread] %-5level %logger{35} - %msg%n</pattern> </encoder> </appender> <appender name="ASYNC_LOG" class="ch.qos.logback.classic.AsyncAppender"> <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 --> <discardingThreshold>0</discardingThreshold> <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 --> <queueSize>512</queueSize> <appender-ref ref="FILE_LOG"/> </appender> <appender name="ASYNC_LOG" class="ch.qos.logback.classic.AsyncAppender"> <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 --> <discardingThreshold>0</discardingThreshold> <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 --> <queueSize>512</queueSize> <appender-ref ref="FILE_LOG"/> </appender> <appender name="ASYNC_LOG_DEBUG" class="ch.qos.logback.classic.AsyncAppender"> <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 --> <discardingThreshold>0</discardingThreshold> <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 --> <queueSize>512</queueSize> <appender-ref ref="FILE_DEBUG"/> </appender> <appender name="ASYNC_LOG_INFO" class="ch.qos.logback.classic.AsyncAppender"> <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 --> <discardingThreshold>0</discardingThreshold> <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 --> <queueSize>512</queueSize> <appender-ref ref="FILE_INFO"/> </appender> <appender name="ASYNC_LOG_WARN" class="ch.qos.logback.classic.AsyncAppender"> <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 --> <discardingThreshold>0</discardingThreshold> <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 --> <queueSize>512</queueSize> <appender-ref ref="FILE_WARN"/> </appender> <appender name="ASYNC_LOG_ERROR" class="ch.qos.logback.classic.AsyncAppender"> <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 --> <discardingThreshold>0</discardingThreshold> <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 --> <queueSize>512</queueSize> <appender-ref ref="FILE_ERROR"/> </appender> <root level="INFO"> <!-- appender referenced after it is defined --> <appender-ref ref="STDOUT"/> <appender-ref ref="ASYNC_LOG"/> <appender-ref ref="ASYNC_LOG_DEBUG"/> <appender-ref ref="ASYNC_LOG_INFO"/> <appender-ref ref="ASYNC_LOG_WARN"/> <appender-ref ref="ASYNC_LOG_ERROR"/> </root> <logger name="org.springframework" level="INFO"/></configuration>
ehcache.xml
<ehcache> <!-- Sets the path to the directory where cache .data files are created. If the path is a Java System Property it is replaced by its value in the running VM. The following properties are translated: user.home - User's home directory user.dir - User's current working directory java.io.tmpdir - Default temp file path --> <!-- 指定一个目录:当 EHCache 把数据写到硬盘上时, 将把数据写到这个目录下. --> <diskStore path="tempDirectory"/> <!--Default Cache configuration. These will applied to caches programmatically created through the CacheManager. The following attributes are required for defaultCache: maxInMemory - Sets the maximum number of objects that will be created in memory eternal - Sets whether elements are eternal. If eternal, timeouts are ignored and the element is never expired. timeToIdleSeconds - Sets the time to idle for an element before it expires. Is only used if the element is not eternal. Idle time is now - last accessed time timeToLiveSeconds - Sets the time to live for an element before it expires. Is only used if the element is not eternal. TTL is now - creation time overflowToDisk - Sets whether elements can overflow to disk when the in-memory cache has reached the maxInMemory limit. --> <!-- 设置缓存的默认数据过期策略 --> <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" /> <!-- 设定具体的命名缓存的数据过期策略。每个命名缓存代表一个缓存区域 缓存区域(region):一个具有名称的缓存块,可以给每一个缓存块设置不同的缓存策略。 如果没有设置任何的缓存区域,则所有被缓存的对象,都将使用默认的缓存策略。即:<defaultCache.../> Hibernate 在不同的缓存区域保存不同的类/集合。 对于类而言,区域的名称是类名。如:com.ekeyfund.springboot.jpa.entity.User 对于集合而言,区域的名称是类名加属性名。如com.ekeyfund.springboot.jpa.entity.User.roleList --> <!-- name: 设置缓存的名字,它的取值为类的全限定名或类的集合的名字 maxElementsInMemory: 设置基于内存的缓存中可存放的对象最大数目 eternal: 设置对象是否为永久的, true表示永不过期, 此时将忽略timeToIdleSeconds 和 timeToLiveSeconds属性; 默认值是false timeToIdleSeconds:设置对象空闲最长时间,以秒为单位, 超过这个时间,对象过期。 当对象过期时,EHCache会把它从缓存中清除。如果此值为0,表示对象可以无限期地处于空闲状态。 timeToLiveSeconds:设置对象生存最长时间,超过这个时间,对象过期。 如果此值为0,表示对象可以无限期地存在于缓存中. 该属性值必须大于或等于 timeToIdleSeconds 属性值 overflowToDisk:设置基于内存的缓存中的对象数目达到上限后,是否把溢出的对象写到基于硬盘的缓存中 --> <cache name="com.ekeyfund.springcloud.entity.Department" maxElementsInMemory="1" eternal="false" timeToIdleSeconds="300" timeToLiveSeconds="600" overflowToDisk="true" /> <cache name="com.ekeyfund.springcloud.entity.User" maxElementsInMemory="1000" eternal="true" timeToIdleSeconds="0" timeToLiveSeconds="0" overflowToDisk="false" /> <cache name="com.ekeyfund.springcloud.entity.Role" maxElementsInMemory="1000" eternal="true" timeToIdleSeconds="0" timeToLiveSeconds="0" overflowToDisk="false" /></ehcache>
四 访问注册服务后的注册中心
启动类
package com.ekeyfund.springcloud;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;@EnableDiscoveryClient //启动服务发现@SpringBootApplicationpublic class SpringcloudEurekaProviderApplication { public static void main(String[] args) { SpringApplication.run(SpringcloudEurekaProviderApplication.class, args); }}
运行该类,并刷新服务注册中心,会发现新增user-service服务,如下图:
五 服务注册中心高可用实现
高可用的实现主要在于配置文件,这里模拟高可用的场景是单台机器部署了两个服务注册中心。
5.1服务注册中心的配置
这里使用了application.properties,application-master.properties和application-slave.properties,使用springboot的多环境配置特性来激活两个注册中心,其配置如下:
application-master.properties
spring.application.name=eureka-serverserver.port=8888eureka.instance.hostname=127.0.0.1eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:9999/eureka/
application-slave.properties
spring.application.name=eureka-serverserver.port=9999eureka.instance.hostname=127.0.0.1eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:8888/eureka/
application.properties
spring.profiles.active=master##使用ip地址的形式定义注册中心的地址eureka.instance.prefer-ip-address=true
5.2 服务注册提供者配置
服务注册提供者配置和之前的不同在于eureka.client.service-url.defaultZone增加了多个地址。
#设置服务名称spring.application.name=user-service #指定服务注册中心的地址 ###高可用改造后可以加上多个注册中心的地址eureka.client.service-url.defaultZone=http://127.0.0.1:8888/eureka/,http://127.0.0.1:9999/eureka/#指定服务提供者的端口server.port=8080
5.3 启动类
为了模拟高可用,这里准备了两个启动类:
SpringcloudEurekaServerMasterApplication
package com.ekeyfund.springcloud;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;/** * Eureka高可用 Master Server */@EnableEurekaServer //启用Eureka 注册中心@SpringBootApplicationpublic class SpringcloudEurekaServerMasterApplication { public static void main(String[] args) { SpringApplication.run(SpringcloudEurekaServerMasterApplication.class, args); }}
SpringcloudEurekaServerSlaveApplication
package com.ekeyfund.springcloud;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;/** * Eureka高可用 Slave Server */@EnableEurekaServer //启用Eureka 注册中心@SpringBootApplicationpublic class SpringcloudEurekaServerSlaveApplication { public static void main(String[] args) { SpringApplication.run(SpringcloudEurekaServerSlaveApplication.class, args); }}
可以通过修改application.properties文件中的spring.profiles.active属性来分别启动,然后访问http://127.0.0.1:8888或者是127.0.0.1:9999,会看到eureka-service注册中心成功注册到两个注册中心上,如下图:
http://127.0.0.1:8888
http://127.0.0.1:9999
当启动SpringcloudEurekaProviderApplication后
访问 http://127.0.0.1:8888
访问http://127.0.0.1:9999
就可以看到应用USER-SERVICE注册到高可用的注册中心EUREKA-SERVICE上了。
- SpringCloud Eureka实战
- SpringCloud Eureka
- SpringCloud.Eureka
- SpringCloud Eureka
- SpringCloud 之 Eureka体验
- SpringCloud---Eureka Server集群
- SpringCloud服务发现Eureka
- SpringCloud Eureka 源码分析
- SpringCloud-Eureka(三)常见问题
- springcloud day01【eureka】
- springcloud学习一 Eureka
- springcloud实战之2 服务注册与发现(eureka实现)
- springcloud实战之3 高可用服务注册中心(eureka集群)
- springcloud(第七篇)springcloud ribbon with eureka
- springcloud(二):注册中心Eureka
- SpringCloud系列(2)---Netfilx-Eureka
- SpringCloud---单节点Eureka Server
- SpringCloud---Eureka添加用户认证
- android app版本升级(DownloadManager、适配6.0、7.0)
- Git 常用命令速查表(图文+表格)
- pat 精度问题
- POJ.1552 Doubles(水)
- android监听事件的三种实现方式
- SpringCloud Eureka实战
- PHP删除数组中指定下标的元素
- 欢迎使用CSDN-markdown编辑器
- 【重要安全预警】Hadoop未授权访问可导致数据泄露
- MAC 命令行启动MySql
- ViewPager系列之仿魅族应用的广告BannerView
- 进程-execve
- 170620 tensorflow中如何随迭代次数更改学习率learning rate
- POJ.2739 Sum of Consecutive Prime Numbers(水)