Cet article rappelle ce qu'AWS, java (presque) débutants ont fait avant d'insérer des objets S3 dans la base de données d'EC2 (SQL Server) avec Lambda @ java. Il s'agit de la dernière édition de la première trilogie post (+ α). Si vous faites remarquer que c'est mieux ici, s'il vous plaît! !!
1: Édition AWS 2: Java [Partie 1] 3: Java [Partie 2] 3.5: Java [suite] <-Main
Avant de modifier la source à l'étape finale, configurons Lambda. Lorsque Lambda accède à d'autres services tels que EC2 et RDS dans le VPC, la fonction elle-même exécutée par Lambda doit également appartenir au VPC. Pour cela, il est nécessaire de définir le rôle IAM, etc., mais une fois terminé, le rôle qui permet d'accéder au VPC lorsque Lambda détecte un événement déclencheur, ENI (Elastic Network Interface) Étant donné que //docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/using-eni.html) est automatiquement attribué, les fonctions Lambda peuvent accéder aux ressources du VPC. Je vais. (Plus vous en savez, mieux AWS est ...)
Note) La version source doit être mssql-jdbc-7.0.0.jre8.jar.
Dans la console de gestion Lambda, sélectionnez le lambda_s3_exec_role créé et ajoutez une stratégie. Ajoutons une stratégie, "AWSLambdaVPCAccessExecutionRole", pour accéder aux ressources dans le VPC. Si le droit d'accès à CloudWatch Logs est également joint et saisi, la préparation est terminée.
Ouvrez la console Lambda, définissez l'environnement d'exécution sur Java8 et créez une nouvelle fonction. Ouvrez la page des détails de la fonction et définissez le rôle d'exécution sur lambda_s3_exec_role. Ensuite, dans [Réseau], sélectionnez "test_vpc" créé dans l'édition AWS (pour être exact, sélectionnez "VPC auquel appartient la ressource ciblée pour l'action", comme EC2 ou RDS). * 1 Cela entraînera l'appartenance de la fonction Lambda au VPC et émettra une ENI. En outre, sélectionnez le sous-réseau et le groupe de sécurité appropriés. Après avoir terminé les paramètres réseau, enregistrez les paramètres de fonction.
Il y a une partie à prendre en compte ici.
Pour accéder aux ressources (EC2, RDS, etc.) dans le VPC, il était nécessaire d'enregistrer la fonction Lambda dans le VPC comme dans le flux précédent. Cependant, une fois que la fonction Lambda devient une ressource au sein du VPC, elle ne pourra plus accéder aux services en dehors du VPC (S3, Kinesis, etc.).
Veuillez vous référer à l'article suivant pour plus de détails. Comment accéder aux services externes de Lambda dans VPC
Pour éviter cela,
--Création d'une passerelle NAT --Créer un point de terminaison
Il y en a, mais cette fois c'est facile, je voudrais donc procéder au réglage avec ce dernier.
Sélectionnez "Endpoint" dans la barre de navigation de la console de gestion VPC et cliquez sur Créer un point de terminaison. Étant donné que l'accès à un autre que S3 n'est pas requis cette fois, l'état sera le suivant. Ensuite, sélectionnez le VPC. Vous pouvez sélectionner la table de routage en sélectionnant le VPC auquel appartient la fonction Lambda ou l'instance EC2. Si vous avez plusieurs tables de routage, choisissez la bonne.
À ce stade, les réglages sont presque terminés. Le diagramme de configuration AWS qui résume les modifications apportées jusqu'à présent est le suivant.
1. EC2 appartient à VPC et se trouve dans un sous-réseau. EIP est également attribué. 2. Lambda appartient au même sous-réseau que EC2. 3. Endpoint est utilisé pour établir la communication entre Lambda à l'intérieur du VPC et S3 à l'extérieur du VPC. 4. Le point de terminaison est défini dans la table de routage du sous-réseau auquel appartiennent EC2 et Lambda.Maintenant, confirmons à nouveau que "la fonction Lambda peut être exécutée et le fichier correspondant peut être lu en utilisant le téléchargement du fichier CSV vers S3 comme déclencheur".
DetectS3Event.java
package lambdaTest.S3toLambda;
/*importation omise*/
public class DetectS3Event implements RequestHandler<S3Event, Object>
{
LambdaLogger lambdaLogger = null;
public AmazonS3 createS3Client() throws Exception
{
AWSCredentials credentials = new BasicAWSCredentials("<accessKey>","<secretKey>");
AmazonS3 client = AmazonS3ClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(credentials))
.build();
return client;
}
@Override
public Context handleRequest(S3Event event, Context context) {
context.getLogger().log("Input: " + event);
lambdaLogger = context.getLogger();
// ===== get event information (S3 Put) =====
S3EventNotificationRecord record = event.getRecords().get(0);
String bucketName = record.getS3().getBucket().getName(); // s3 bucket name
String key = record.getS3().getObject().getKey(); // s3 object key
lambdaLogger.log("bucketName = " + bucketName);
lambdaLogger.log("object key = " + key);
try {
AmazonS3 client = createS3Client();
// Get target object of event
S3Object object = client.getObject(new GetObjectRequest(bucketName, key));
lambdaLogger.log("S3 client = " + client.toString());
BufferedInputStream bis = new BufferedInputStream(object.getObjectContent());
BufferedReader br = new BufferedReader(new InputStreamReader(bis));
String line = "";
// Output contents of object line by line
while((line = br.readLine()) != null) {
lambdaLogger.log(line);
}
} catch (IOException e) {
lambdaLogger.log("IOException error message : " + e.getErrorMessage());
} catch (AmazonServiceException e) {
lambdaLogger.log("AWSException error message : " + e.getErrorMessage());
} catch (Exception e) {
lambdaLogger.log("Exception error message : " + e.getMessage());
}
return null;
}
}
Après avoir créé le fichier ci-dessus, téléchargez le fichier jar fourni avec Maven, etc. sur Lambda.
Téléchargez le CSV suivant sur S3.
emp_values.csv
1001,Dean,28
1002,Sam,25
1003,John,51
1004,Bobby,54
1005,Meg,26
Connectons-nous à CloudWatch et vérifions le journal. Vous pouvez voir que le CSV ci-dessus est sorti dans le journal ligne par ligne.
Enfin, insérons ce CSV dans la base de données sur EC2.
La base de données et la table sont la précédente [partie Java [Partie 2]](https://qiita.com/yut0201/items/0d955b37f1f461cce815#%E3%83%87%E3%83%BC%E3%82%BF%E3% 83% 99% E3% 83% BC% E3% 82% B9% E3% 81% 8A% E3% 82% 88% E3% 81% B3% E3% 83% A6% E3% 83% BC% E3% 82% Utilisez la table des employés LambdaTestDB créée dans B6% E3% 81% AE% E4% BD% 9C% E6% 88% 90).
Assurez-vous qu'il n'y a aucun enregistrement dans la table.
1> SELECT * FROM employee;
2> go
emp_id emp_name age
----------- -------------------- -----------
(0 rows affected)
Maintenant, éditons la source.
DetectS3Event.java
package lambdaTest.S3toLambda;
/*importation omise*/
public class DetectS3Event implements RequestHandler<S3Event, Object>
{
LambdaLogger lambdaLogger = null;
Connection mssqlCon = null;
public AmazonS3 createS3Client() throws Exception
{
AWSCredentials credentials = new BasicAWSCredentials(
"<accessKey>",
"<secretKey>");
AmazonS3 client = AmazonS3ClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(credentials))
.build();
return client;
}
@Override
public Context handleRequest(S3Event event, Context context) {
context.getLogger().log("Input: " + event);
lambdaLogger = context.getLogger();
// ===== get event information (S3 Put) =====
S3EventNotificationRecord record = event.getRecords().get(0);
String bucketName = record.getS3().getBucket().getName(); // s3 bucket name
String key = record.getS3().getObject().getKey(); // s3 object key
lambdaLogger.log("bucketName = " + bucketName);
lambdaLogger.log("object key = " + key);
try {
AmazonS3 client = createS3Client();
S3Object object = client.getObject(new GetObjectRequest(bucketName, key));
lambdaLogger.log("S3 client = " + client.toString());
BufferedInputStream bis = new BufferedInputStream(object.getObjectContent());
BufferedReader br = new BufferedReader(new InputStreamReader(bis));
ResourceBundle sqlServerResource = ResourceBundle.getBundle("sqlServer");
DatabaseInfo sqlServerInfo = new DatabaseInfo(sqlServerResource.getString("driver"),
sqlServerResource.getString("url"),
sqlServerResource.getString("user"),
sqlServerResource.getString("pass"));
/* ======== SQL Server connection ======== */
lambdaLogger.log("SQL Server Session creating...");
SqlServer sqlServer = new SqlServer();
mssqlCon = sqlServer.openConnection(sqlServerInfo);
lambdaLogger.log("SUCCESS : SQL Server session created !!");
String line = "";
Statement insertStmt = mssqlCon.createStatement();
while((line = br.readLine()) != null) {
String[] values = line.split(",");
String insertRecord = "INSERT INTO employee VALUES("
+ values[0] + ", '"
+ values[1] + "', "
+ values[2] + ");";
insertStmt.executeUpdate(insertRecord);
}
if (insertStmt != null) insertStmt.close();
if (mssqlCon != null) sqlServer.closeConnection(mssqlCon);
if (br != null) br.close();
} catch (IOException e) {
e.printStackTrace();
} catch (AmazonServiceException e) {
lambdaLogger.log("Error message : " + e.getErrorMessage());
} catch (Exception e) {
lambdaLogger.log("Exception error message : " + e.getMessage());
}
return null;
}
}
Dans l'instruction while, les CSV lus ligne par ligne sont disposés dans un tableau séparé par des virgules, et chacun est INSERT comme valeur de chaque colonne de l'enregistrement. Vous aurez besoin d'une connexion pour vous connecter à la base de données, alors créez un nouveau fichier ci-dessous.
SqlServer.java
package lambdaTest.db;
/*importation omise*/
public class SqlServer {
public SqlServer() {
super();
}
public Connection openConnection(DatabaseInfo dbInfo)
{
Connection con = null;
try {
Class.forName(dbInfo.getDriver());
con = DriverManager.getConnection(dbInfo.getUrl(), dbInfo.getDbUser(), dbInfo.getDbPass());
} catch (SQLException | ClassNotFoundException e) {
System.out.println("anything Exception : " + e);
}
return con;
}
public void closeConnection(Connection con) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Déléguez la gestion des connexions à la base de données à cette classe. Il n'y a aucun problème avec le codage en dur pour chaque paramètre requis pour la connexion tel que l'URL de connexion, le nom d'utilisateur, le mot de passe, etc. Mettez-le sous forme de fichier de propriétés en mettant l'accent sur la réutilisation
sqlServer.properties
driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
url=jdbc:sqlserver://<EC2-privateIP>:<portNo>;databaseName=<databaseName>
user=<userName>
pass=<password>
De plus, puisque vous avez besoin d'une classe pour lier le fichier de propriétés, créons également la classe suivante.
DatabaseInfo.java
package lambdaTest.S3toLambda;
final public class DatabaseInfo {
String driver;
String url;
String dbUser;
String dbPass;
public String getDriver() {
return driver;
}
public String getUrl() {
return url;
}
public String getDbUser() {
return dbUser;
}
public String getDbPass() {
return dbPass;
}
public DatabaseInfo(String driver, String url, String dbUser, String dbPass) {
this.driver = driver;
this.url = url;
this.dbUser = dbUser;
this.dbPass = dbPass;
}
}
Enfin, ajoutez quelques lignes à pom.xml afin que Maven puisse lire correctement le fichier de propriétés externes. Ici, seule la section de construction à ajouter est extraite et la ligne ajoutée est marquée d'une étoile.
pom.xml
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<configuration>
<encoding>UTF-8</encoding>
<createDependencyReducedPom>false</createDependencyReducedPom>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<archive>
<manifest>
<mainClass>com.gmail.greencoffeemaker.MainApp</mainClass>
<addClasspath>true</addClasspath>
</manifest>
<manifestEntries>
<Class-Path>./src/resources/</Class-Path>
</manifestEntries>
</archive>
</configuration>
<executions>
<execution>
<phase>package</phase>
<!--Partie Postscript-->
<configuration>
<target>
<!--copie: /src/main/resources => /target/resources -->
<mkdir dir="${project.build.directory}/resources" />
<copy todir="${project.build.directory}/resources">
<fileset dir="${project.basedir}/src/main/resources" />
</copy>
</target>
</configuration>
<!--Jusque là-->
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
La modification est maintenant terminée. Après la construction, téléchargez le fichier jar sur Lambda et placez à nouveau emp_values.csv dans S3.
Lorsque je me connecte à SQL Server sur EC2 et que je regarde le tableau. .. ..
1> SELECT * FROM employee;
2> go
emp_id emp_name age
----------- -------------------- -----------
1001 Dean 28
1002 Sam 25
1003 John 51
1004 Bobby 54
1005 Meg 26
(5 rows affected)
** C'est fait! !! !! ** **
Cela fait quelques années que j'ai touché Java pour la première fois en écrivant cet article et AWS est le premier La préparation était quasiment nulle, mais j'étais soulagé de pouvoir faire ce que je voulais faire. Lire le manuel, rechercher des connaissances, etc., le temps de travail par jour était inférieur à 3 heures et le sentiment de travail était d'environ 2 semaines. Je pense que l'essentiel du travail consistait à éviter les erreurs trébuchantes en cours de route.
Je veux améliorer l'efficacité du travail. Désespéré.
Recommended Posts