Bis INSERT S3-Objekt in EC2 DB mit Lambda @ java: Java [Fortsetzung]

Einführung

Dieser Artikel erinnert daran, was AWS, Java (fast) Anfänger vor dem Einfügen von S3-Objekten in EC2 DB (SQL Server) mit Lambda @ java getan haben. Dies ist die endgültige Ausgabe der ersten Post-Trilogie (+ α). Wenn Sie darauf hinweisen, dass dies hier besser ist, bitte! !!

1: AWS Edition 2: Java [Teil 1] 3: Java [Teil 2] 3.5: Java [Fortsetzung] <-Main

Lambda-Rollen und Netzwerkeinstellungen

IAM-Rolleneinstellungen

Bevor wir die Quelle bis zur letzten Phase bearbeiten, richten wir Lambda ein. Wenn Lambda auf andere Dienste in der VPC zugreifen möchte, wie z. B. EC2 und RDS, muss die von Lambda ausgeführte Funktion selbst ebenfalls zur VPC gehören. Zu diesem Zweck muss die IAM-Rolle usw. festgelegt werden. Wenn diese abgeschlossen ist, muss die Rolle, die den Zugriff auf die VPC ermöglicht, wenn Lambda ein Triggerereignis erkennt, ENI (Elastic Network Interface). Da //docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/using-eni.html) automatisch zugewiesen wird, können Lambda-Funktionen auf Ressourcen in der VPC zugreifen. Ich werde. (Je mehr Sie wissen, desto besser ist AWS ...)

Hinweis) Die Quellversion sollte mssql-jdbc-7.0.0.jre8.jar sein.

Wählen Sie in der Lambda-Verwaltungskonsole die erstellte lambda_s3_exec_role aus und fügen Sie eine Richtlinie hinzu. Fügen wir eine Richtlinie "AWSLambdaVPCAccessExecutionRole" hinzu, um auf Ressourcen in der VPC zuzugreifen. Wenn das Zugriffsrecht auf CloudWatch-Protokolle angehängt und eingegeben ist, ist die Vorbereitung abgeschlossen.

Netzwerkeinstellungen

Öffnen Sie die Lambda-Konsole, stellen Sie die Ausführungsumgebung auf Java8 ein und erstellen Sie eine neue Funktion. Öffnen Sie die Seite mit den Funktionsdetails und setzen Sie die Ausführungsrolle auf lambda_s3_exec_role. 01_lambda_exec_role.png Wählen Sie als Nächstes in [Netzwerk] "test_vpc" aus, das in der AWS-Edition erstellt wurde (um genau zu sein, wählen Sie "VPC, zu der die zu aktivierende Ressource gehört" wie EC2 oder RDS). * 1 Dies führt dazu, dass die Lambda-Funktion zur VPC gehört und eine ENI ausgibt. Wählen Sie außerdem das entsprechende Subnetz und die Sicherheitsgruppe aus. 02_lambda_network.png Speichern Sie nach Abschluss der Netzwerkeinstellungen die Funktionseinstellungen.

Hinweis

Hier ist ein Teil zu beachten.

Um auf die Ressourcen (EC2, RDS usw.) in der VPC zugreifen zu können, musste die Lambda-Funktion in der VPC wie im vorherigen Ablauf registriert werden. Sobald die Lambda-Funktion jedoch zu einer Ressource innerhalb der VPC wird, kann sie nicht mehr auf Dienste außerhalb der VPC zugreifen (S3, Kinesis usw.).

Weitere Informationen finden Sie im folgenden Artikel. Zugriff auf externe Dienste von Lambda in VPC

Um dies zu vermeiden,

--Erstellen eines NAT-Gateways --Erstellen Sie den Endpunkt

Es gibt, aber diesmal ist es einfach, also möchte ich mit der Einstellung mit letzterem fortfahren.

Erstellen eines Endpunkts

Wählen Sie in der Navigationsleiste der VPC-Verwaltungskonsole "Endpunkt" aus und klicken Sie auf "Endpunkt erstellen". Dieses Mal ist kein Zugriff auf andere als S3 erforderlich, daher lautet der Status wie folgt. 03_create_endpoint.png Wählen Sie als Nächstes die VPC aus. Sie können die Routentabelle auswählen, indem Sie die VPC auswählen, zu der die Lambda-Funktion oder die EC2-Instanz gehört. Wenn Sie mehrere Routentabellen haben, wählen Sie die richtige aus. 04_create_endpoint02.png

Zu diesem Zeitpunkt sind die Einstellungen fast abgeschlossen. Das AWS-Konfigurationsdiagramm, in dem die bisher vorgenommenen Änderungen zusammengefasst sind, lautet wie folgt.

05_AWS_network.png 1. EC2 gehört zu VPC und befindet sich in einem Subnetz. EIP ist ebenfalls zugewiesen. 2. Lambda gehört zum selben Subnetz wie EC2. 3. Der Endpunkt wird verwendet, um die Kommunikation zwischen Lambda innerhalb der VPC und S3 außerhalb der VPC herzustellen. 4. Der Endpunkt wird in der Routentabelle des Subnetzes festgelegt, zu dem EC2 und Lambda gehören.

Quelle bearbeiten

Lassen Sie uns nun noch einmal bestätigen, dass "die Lambda-Funktion ausgeführt und die entsprechende Datei gelesen werden kann, indem der Upload der CSV-Datei nach S3 ausgelöst wird".

DetectS3Event.java


package lambdaTest.S3toLambda;

/*Import weggelassen*/

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;
	}
}

Laden Sie nach dem Erstellen der obigen Datei das mit Maven usw. verpackte Glas auf Lambda hoch.

Laden Sie die folgende CSV in S3 hoch.

emp_values.csv


1001,Dean,28
1002,Sam,25
1003,John,51
1004,Bobby,54
1005,Meg,26

Stellen Sie eine Verbindung zu CloudWatch her und überprüfen Sie das Protokoll. 06_lambda_executed.png Sie können sehen, dass die obige CSV Zeile für Zeile in das Protokoll ausgegeben wird.

Zuletzt fügen wir diese CSV in die DB auf EC2 ein.

INSERT in DB

Die Datenbank und die Tabelle sind die vorherigen [Java-Teil [Teil 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% Verwenden Sie die in B6% E3% 81% AE% E4% BD% 9C% E6% 88% 90 erstellte LambdaTestDB-Mitarbeitertabelle.

Stellen Sie sicher, dass die Tabelle keine Datensätze enthält.

1> SELECT * FROM employee;
2> go
emp_id      emp_name             age        
----------- -------------------- -----------

(0 rows affected)

Jetzt bearbeiten wir die Quelle.

DetectS3Event.java


package lambdaTest.S3toLambda;

/*Import weggelassen*/

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;
	}
}

In der while-Anweisung werden CSVs, die zeilenweise gelesen werden, in einem durch Kommas getrennten Array angeordnet und jeweils als Wert jeder Spalte des Datensatzes eingefügt. Sie benötigen eine Verbindung, um eine Verbindung zur Datenbank herzustellen. Erstellen Sie daher unten eine neue Datei.

SqlServer.java


package lambdaTest.db;

/*Import weggelassen*/

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();
		}
		
	}
}

Delegieren Sie die Verbindungsverwaltung an die Datenbank an diese Klasse. Es gibt kein Problem mit der harten Codierung für jeden für die Verbindung erforderlichen Parameter wie Verbindungs-URL, Benutzername, Kennwort usw. Stellen Sie es als Eigenschaftendatei mit Schwerpunkt auf Wiederverwendbarkeit bereit.

sqlServer.properties


driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
url=jdbc:sqlserver://<EC2-privateIP>:<portNo>;databaseName=<databaseName>
user=<userName>
pass=<password>

Da Sie zum Verknüpfen der Eigenschaftendatei eine Klasse benötigen, erstellen wir auch die folgende Klasse.

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;
	}
}

Fügen Sie abschließend ein paar Zeilen zu pom.xml hinzu, damit Maven die externe Eigenschaftendatei korrekt lesen kann. Hier wird nur der hinzuzufügende Build-Abschnitt extrahiert und die hinzugefügte Linie mit einem Stern markiert.

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>
                        <!--Postscript-Teil-->
            <configuration>
              <target>
                <!--Kopieren: /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>
                        <!--Bisher-->
            <goals>
              <goal>shade</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

Die Bearbeitung ist jetzt abgeschlossen. Laden Sie nach dem Erstellen das Glas auf Lambda hoch und fügen Sie emp_values.csv erneut in S3 ein.

Wenn ich eine Verbindung zu SQL Server auf EC2 herstelle und mir die Tabelle ansehe. .. ..

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)

** Es ist fertig! !! !! ** ** **

Zusammenfassung

Es ist ein paar Jahre her, seit ich Java zum ersten Mal beim Schreiben dieses Artikels berührt habe und AWS ist das erste Ich war in einem zerlumpten Zustand mit fast null Vorbereitung, aber ich war erleichtert, dass ich realisierte, was ich tun wollte. Beim Lesen des Handbuchs, bei der Suche nach Wissen usw. betrug die Arbeitszeit pro Tag weniger als 3 Stunden und das Arbeitsgefühl etwa 2 Wochen. Ich habe das Gefühl, dass der größte Teil der Arbeit darin bestand, Stolperfehler auf dem Weg zu vermeiden.

Ich möchte die Arbeitseffizienz verbessern. Verzweifelt.

Recommended Posts

Bis INSERT S3-Objekt in EC2 DB mit Lambda @ java: Java [Fortsetzung]
Bis INSERT S3 Objekt in EC2 DB mit Lambda @ java: AWS
Bis INSERT S3-Objekt in EC2 DB mit Lambda @ java: Java [Teil 2]
Bis das S3-Objekt mit Lambda @ java in Java eingefügt wird: Java [Teil 1]
[Java] Batch Insert Inserts werden beim Umgang mit MySQL DB in Doma zu einem zusammengefasst.
Versuchen Sie eine DB-Verbindung mit Java
Stellen Sie mit Java eine Verbindung zur Datenbank her